LCOV - code coverage report
Current view: top level - Core - GameController.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 29 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : GameController.m
       4             : 
       5             : Oolite
       6             : Copyright (C) 2004-2013 Giles C Williams and contributors
       7             : 
       8             : This program is free software; you can redistribute it and/or
       9             : modify it under the terms of the GNU General Public License
      10             : as published by the Free Software Foundation; either version 2
      11             : of the License, or (at your option) any later version.
      12             : 
      13             : This program is distributed in the hope that it will be useful,
      14             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             : GNU General Public License for more details.
      17             : 
      18             : You should have received a copy of the GNU General Public License
      19             : along with this program; if not, write to the Free Software
      20             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      21             : MA 02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : #import "GameController.h"
      26             : #import "Universe.h"
      27             : #import "ResourceManager.h"
      28             : #import "MyOpenGLView.h"
      29             : #import "OOSound.h"
      30             : #import "OOOpenGL.h"
      31             : #import "PlayerEntityLoadSave.h"
      32             : #include <stdlib.h>
      33             : #import "OOCollectionExtractors.h"
      34             : #import "OOOXPVerifier.h"
      35             : #import "OOLoggingExtended.h"
      36             : #import "NSFileManagerOOExtensions.h"
      37             : #import "OOLogOutputHandler.h"
      38             : #import "OODebugFlags.h"
      39             : #import "OOJSFrameCallbacks.h"
      40             : #import "OOOpenGLExtensionManager.h"
      41             : #import "OOOpenALController.h"
      42             : #import "OODebugSupport.h"
      43             : #import "legacy_random.h"
      44             : #import "OOOXZManager.h"
      45             : #import "OOOpenGLMatrixManager.h"
      46             : 
      47             : #if OOLITE_MAC_OS_X
      48             : #import "JAPersistentFileReference.h"
      49             : #import <Sparkle/Sparkle.h>
      50             : #import "OoliteApp.h"
      51             : #import "OOMacJoystickManager.h"
      52             : 
      53             : static void SetUpSparkle(void);
      54             : #elif (OOLITE_GNUSTEP && !defined(NDEBUG))
      55             : #import "OODebugMonitor.h"
      56             : #endif
      57             : 
      58             : 
      59           0 : static GameController *sSharedController = nil;
      60             : 
      61             : 
      62             : @interface GameController (OOPrivate)
      63             : 
      64           0 : - (void)reportUnhandledStartupException:(NSException *)exception;
      65             : 
      66           0 : - (void)doPerformGameTick;
      67             : 
      68             : @end
      69             : 
      70             : 
      71             : @implementation GameController
      72             : 
      73             : + (GameController *) sharedController
      74             : {
      75             :         if (sSharedController == nil)
      76             :         {
      77             :                 sSharedController = [[self alloc] init];
      78             :         }
      79             :         return sSharedController;
      80             : }
      81             : 
      82             : 
      83           0 : - (id) init
      84             : {
      85             :         if (sSharedController != nil)
      86             :         {
      87             :                 [self release];
      88             :                 [NSException raise:NSInternalInconsistencyException format:@"%s: expected only one GameController to exist at a time.", __PRETTY_FUNCTION__];
      89             :         }
      90             :         
      91             :         if ((self = [super init]))
      92             :         {
      93             :                 last_timeInterval = [NSDate timeIntervalSinceReferenceDate];
      94             :                 delta_t = 0.01; // one hundredth of a second 
      95             :                 _animationTimerInterval = [[NSUserDefaults standardUserDefaults] oo_doubleForKey:@"animation_timer_interval" defaultValue:MINIMUM_ANIMATION_TICK];
      96             :                 
      97             :                 // rather than seeding this with the date repeatedly, seed it
      98             :                 // once here at startup
      99             :                 ranrot_srand((uint32_t)[[NSDate date] timeIntervalSince1970]);   // reset randomiser with current time
     100             :                 
     101             :                 _splashStart = [[NSDate alloc] init];
     102             :         }
     103             :         
     104             :         return self;
     105             : }
     106             : 
     107             : 
     108           0 : - (void) dealloc
     109             : {
     110             : #if OOLITE_MAC_OS_X
     111             :         [[[NSWorkspace sharedWorkspace] notificationCenter]     removeObserver:UNIVERSE];
     112             : #endif
     113             :         
     114             :         [timer release];
     115             :         [gameView release];
     116             :         [UNIVERSE release];
     117             :         
     118             :         [playerFileToLoad release];
     119             :         [playerFileDirectory release];
     120             :         [expansionPathsToInclude release];
     121             :         
     122             :         [super dealloc];
     123             : }
     124             : 
     125             : 
     126             : - (BOOL) isGamePaused
     127             : {
     128             :         return gameIsPaused;
     129             : }
     130             : 
     131             : 
     132             : - (void) setGamePaused:(BOOL)value
     133             : {
     134             :         if (value && !gameIsPaused)
     135             :         {
     136             :                 _resumeMode = [self mouseInteractionMode];
     137             :                 [self setMouseInteractionModeForUIWithMouseInteraction:NO];
     138             :                 gameIsPaused = YES;
     139             :                 [PLAYER doScriptEvent:OOJSID("gamePaused")];
     140             :         }
     141             :         else if (!value && gameIsPaused)
     142             :         {
     143             :                 [self setMouseInteractionMode:_resumeMode];
     144             :                 gameIsPaused = NO;
     145             :                 [PLAYER doScriptEvent:OOJSID("gameResumed")];
     146             :         }
     147             : }
     148             : 
     149             : 
     150             : - (OOMouseInteractionMode) mouseInteractionMode
     151             : {
     152             :         return _mouseMode;
     153             : }
     154             : 
     155             : 
     156             : - (void) setMouseInteractionMode:(OOMouseInteractionMode)mode
     157             : {
     158             :         OOMouseInteractionMode oldMode = _mouseMode;
     159             :         if (mode == oldMode)  return;
     160             :         
     161             :         _mouseMode = mode;
     162             :         OOLog(@"input.mouseMode.changed", @"Mouse interaction mode changed from %@ to %@", OOStringFromMouseInteractionMode(oldMode), OOStringFromMouseInteractionMode(mode));
     163             :         
     164             : #if OO_USE_FULLSCREEN_CONTROLLER
     165             :         if ([self inFullScreenMode])
     166             :         {
     167             :                 [_fullScreenController noteMouseInteractionModeChangedFrom:oldMode to:mode];
     168             :         }
     169             :         else
     170             : #endif
     171             :         {
     172             :                 [[self gameView] noteMouseInteractionModeChangedFrom:oldMode to:mode];
     173             :         }
     174             : }
     175             : 
     176             : 
     177             : - (void) setMouseInteractionModeForFlight
     178             : {
     179             :         [self setMouseInteractionMode:[PLAYER isMouseControlOn] ? MOUSE_MODE_FLIGHT_WITH_MOUSE_CONTROL : MOUSE_MODE_FLIGHT_NO_MOUSE_CONTROL];
     180             : }
     181             : 
     182             : 
     183             : - (void) setMouseInteractionModeForUIWithMouseInteraction:(BOOL)interaction
     184             : {
     185             :         [self setMouseInteractionMode:interaction ? MOUSE_MODE_UI_SCREEN_WITH_INTERACTION : MOUSE_MODE_UI_SCREEN_NO_INTERACTION];
     186             : }
     187             : 
     188             : 
     189             : - (MyOpenGLView *) gameView
     190             : {
     191             :         return gameView;
     192             : }
     193             : 
     194             : 
     195             : - (void) setGameView:(MyOpenGLView *)view
     196             : {
     197             :         [gameView release];
     198             :         gameView = [view retain];
     199             :         [gameView setGameController:self];
     200             :         [UNIVERSE setGameView:gameView];
     201             : }
     202             : 
     203             : 
     204             : - (void) applicationDidFinishLaunching:(NSNotification *)notification
     205             : {
     206             :         NSAutoreleasePool       *pool = nil;
     207             :         unsigned                        i;
     208             :         
     209             :         pool = [[NSAutoreleasePool alloc] init];
     210             :         
     211             :         @try
     212             :         {
     213             :                 // if not verifying oxps, ensure that gameView is drawn to using beginSplashScreen
     214             :                 // OpenGL is initialised and that allows textures to initialise too.
     215             : 
     216             : #if OO_OXP_VERIFIER_ENABLED
     217             : 
     218             :                 if ([OOOXPVerifier runVerificationIfRequested])
     219             :                 {
     220             :                         [self exitAppWithContext:@"OXP verifier run"];
     221             :                 }
     222             :                 else 
     223             :                 {
     224             :                         [self beginSplashScreen];
     225             :                 }
     226             :                 
     227             : #else
     228             :                 [self beginSplashScreen];
     229             : #endif
     230             :                 
     231             : #if OOLITE_MAC_OS_X
     232             :                 [OOJoystickManager setStickHandlerClass:[OOMacJoystickManager class]];
     233             :                 SetUpSparkle();
     234             : #endif
     235             :                 
     236             :                 [self setUpDisplayModes];
     237             :                 
     238             :                 // moved to before the Universe is created
     239             :                 if (expansionPathsToInclude)
     240             :                 {
     241             :                         for (i = 0; i < [expansionPathsToInclude count]; i++)
     242             :                         {
     243             :                                 [ResourceManager addExternalPath: (NSString*)[expansionPathsToInclude objectAtIndex: i]];
     244             :                         }
     245             :                 }
     246             :                 
     247             :                 // initialise OXZ manager
     248             :                 [OOOXZManager sharedManager];
     249             : 
     250             :                 // moved here to try to avoid initialising this before having an Open GL context
     251             :                 //[self logProgress:DESC(@"Initialising universe")]; // DESC expansions only possible after Universe init
     252             :                 [[Universe alloc] initWithGameView:gameView];
     253             :                 
     254             :                 [self loadPlayerIfRequired];
     255             :                 
     256             :                 [self logProgress:@""];
     257             :                 
     258             :                 // get the run loop and add the call to performGameTick:
     259             :                 [self startAnimationTimer];
     260             :                 
     261             :                 [self endSplashScreen];
     262             :         }
     263             :         @catch (NSException *exception)
     264             :         {
     265             :                 [self reportUnhandledStartupException:exception];
     266             :                 exit(EXIT_FAILURE);
     267             :         }
     268             :         
     269             :         OOLog(@"startup.complete", @"========== Loading complete in %.2f seconds. ==========", -[_splashStart timeIntervalSinceNow]);
     270             :         
     271             : #if OO_USE_FULLSCREEN_CONTROLLER
     272             :         [self setFullScreenMode:[[NSUserDefaults standardUserDefaults] boolForKey:@"fullscreen"]];
     273             : #endif
     274             :         
     275             :         // Release anything allocated above that is not required.
     276             :         [pool release];
     277             :         
     278             : #if !OOLITE_MAC_OS_X
     279             :         [[NSRunLoop currentRunLoop] run];
     280             : #endif
     281             : }
     282             : 
     283             : 
     284             : - (void) loadPlayerIfRequired
     285             : {
     286             :         if (playerFileToLoad != nil)
     287             :         {
     288             :                 [self logProgress:DESC(@"loading-player")];
     289             :                 // fix problem with non-shader lighting when starting skips
     290             :                 // the splash screen
     291             :                 [UNIVERSE useGUILightSource:YES];
     292             :                 [UNIVERSE useGUILightSource:NO];
     293             :                 [PLAYER loadPlayerFromFile:playerFileToLoad asNew:NO];
     294             :         }
     295             : }
     296             : 
     297             : 
     298             : - (void) beginSplashScreen
     299             : {
     300             : #if !OOLITE_MAC_OS_X
     301             :         if(!gameView)
     302             :         {
     303             :                 gameView = [MyOpenGLView alloc];
     304             :                 [gameView init];
     305             :                 [gameView setGameController:self];
     306             :                 [gameView initSplashScreen];
     307             :         }
     308             : #else
     309             :         [gameView updateScreen];
     310             : #endif
     311             : }
     312             : 
     313             : 
     314             : #if OOLITE_MAC_OS_X
     315             : 
     316             : - (void) performGameTick:(id)sender
     317             : {
     318             :         [gameView pollControls];
     319             :         [self doPerformGameTick];
     320             : }
     321             : 
     322             : #else
     323             : 
     324             : - (void) performGameTick:(id)sender
     325             : {
     326             :         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     327             :         
     328             :         [gameView pollControls];
     329             :         [self doPerformGameTick];
     330             :         
     331             :         [pool release];
     332             : }
     333             : 
     334             : #endif
     335             : 
     336             : 
     337           0 : - (void) doPerformGameTick
     338             : {
     339             :         @try
     340             :         {
     341             :                 if (gameIsPaused)
     342             :                         delta_t = 0.0;  // no movement!
     343             :                 else
     344             :                 {
     345             :                         delta_t = [NSDate timeIntervalSinceReferenceDate] - last_timeInterval;
     346             :                         last_timeInterval += delta_t;
     347             :                         if (delta_t > MINIMUM_GAME_TICK)
     348             :                                 delta_t = MINIMUM_GAME_TICK;            // peg the maximum pause (at 0.5->1.0 seconds) to protect against when the machine sleeps    
     349             :                 }
     350             :                 
     351             :                 [UNIVERSE update:delta_t];
     352             :                 if (EXPECT_NOT([PLAYER status] == STATUS_RESTART_GAME))
     353             :                 {
     354             :                         [UNIVERSE reinitAndShowDemo:YES];
     355             :                 }
     356             :                 [OOSound update];
     357             :                 if (!gameIsPaused)
     358             :                 {
     359             :                         OOJSFrameCallbacksInvoke(delta_t);
     360             :                 }
     361             :         }
     362             :         @catch (id exception) 
     363             :         {
     364             :                 OOLog(@"exception.backtrace",@"%@",[exception callStackSymbols]);
     365             :         }
     366             :         
     367             :         @try
     368             :         {
     369             :                 [gameView display];
     370             :         }
     371             :         @catch (id exception) {}
     372             : }
     373             : 
     374             : 
     375             : - (void) startAnimationTimer
     376             : {
     377             :         if (timer == nil)
     378             :         {   
     379             :                 NSTimeInterval ti = _animationTimerInterval; // default one two-hundredth of a second (should be a fair bit faster than expected frame rate ~60Hz to avoid problems with phase differences)
     380             :                 
     381             :                 timer = [[NSTimer timerWithTimeInterval:ti target:self selector:@selector(performGameTick:) userInfo:nil repeats:YES] retain];
     382             :                 
     383             :                 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
     384             : #if OOLITE_MAC_OS_X
     385             :                 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode];
     386             : #endif
     387             : 
     388             :         }
     389             : }
     390             : 
     391             : 
     392             : - (void) stopAnimationTimer
     393             : {
     394             :         if (timer != nil)
     395             :         {
     396             :                 [timer invalidate];
     397             :                 [timer release];
     398             :                 timer = nil;
     399             :         }
     400             : }
     401             : 
     402             : 
     403             : #if OOLITE_MAC_OS_X
     404             : 
     405             : - (void) recenterVirtualJoystick
     406             : {
     407             :         // FIXME: does this really need to be spread across GameController and MyOpenGLView? -- Ahruman 2011-01-22
     408             :         my_mouse_x = my_mouse_y = 0;    // center mouse
     409             :         [gameView setVirtualJoystick:0.0 :0.0];
     410             : }
     411             : 
     412             : 
     413             : - (IBAction) showLogAction:sender
     414             : {
     415             :         [[NSWorkspace sharedWorkspace] openFile:[OOLogHandlerGetLogBasePath() stringByAppendingPathComponent:@"Previous.log"]];
     416             : }
     417             : 
     418             : 
     419             : - (IBAction) showLogFolderAction:sender
     420             : {
     421             :         [[NSWorkspace sharedWorkspace] openFile:OOLogHandlerGetLogBasePath()];
     422             : }
     423             : 
     424             : 
     425             : // Helpers to allow -snapshotsURLCreatingIfNeeded: code to be identical here and in dock tile plug-in.
     426           0 : static id GetPreference(NSString *key, Class expectedClass)
     427             : {
     428             :         id result = [[NSUserDefaults standardUserDefaults] objectForKey:key];
     429             :         if (expectedClass != Nil && ![result isKindOfClass:expectedClass])  result = nil;
     430             :         
     431             :         return result;
     432             : }
     433             : 
     434             : 
     435           0 : static void SetPreference(NSString *key, id value)
     436             : {
     437             :         [[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
     438             : }
     439             : 
     440             : 
     441           0 : static void RemovePreference(NSString *key)
     442             : {
     443             :         [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
     444             : }
     445             : 
     446             : 
     447           0 : #define kSnapshotsDirRefKey             @"snapshots-directory-reference"
     448           0 : #define kSnapshotsDirNameKey    @"snapshots-directory-name"
     449             : 
     450             : - (NSURL *) snapshotsURLCreatingIfNeeded:(BOOL)create
     451             : {
     452             :         BOOL                    stale = NO;
     453             :         NSDictionary    *snapshotDirDict = GetPreference(kSnapshotsDirRefKey, [NSDictionary class]);
     454             :         NSURL                   *url = nil;
     455             :         NSString                *name = DESC(@"snapshots-directory-name-mac");
     456             :         
     457             :         if (snapshotDirDict != nil)
     458             :         {
     459             :                 url = JAURLFromPersistentFileReference(snapshotDirDict, kJAPersistentFileReferenceWithoutUI | kJAPersistentFileReferenceWithoutMounting, &stale);
     460             :                 if (url != nil)
     461             :                 {
     462             :                         NSString *existingName = [[url path] lastPathComponent];
     463             :                         if ([existingName compare:name options:NSCaseInsensitiveSearch] != 0)
     464             :                         {
     465             :                                 // Check name from previous access, because we might have changed localizations.
     466             :                                 NSString *originalOldName = GetPreference(kSnapshotsDirNameKey, [NSString class]);
     467             :                                 if (originalOldName == nil || [existingName compare:originalOldName options:NSCaseInsensitiveSearch] != 0)
     468             :                                 {
     469             :                                         url = nil;
     470             :                                 }
     471             :                         }
     472             :                         
     473             :                         // did we put the old directory in the trash?
     474             :                         Boolean inTrash = false;
     475             :                         const UInt8 *utfPath = (const UInt8 *)[[url path] UTF8String];
     476             :                         
     477             :                         OSStatus err = DetermineIfPathIsEnclosedByFolder(kOnAppropriateDisk, kTrashFolderType, utfPath, false, &inTrash);
     478             :                         // if so, create a new directory.
     479             :                         if (err == noErr && inTrash == true) url = nil;
     480             :                 }
     481             :         }
     482             :         
     483             :         if (url == nil)
     484             :         {
     485             :                 NSString *path = nil;
     486             :                 NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES);
     487             :                 if ([searchPaths count] > 0)
     488             :                 {
     489             :                         path = [[searchPaths objectAtIndex:0] stringByAppendingPathComponent:name];
     490             :                 }
     491             :                 url = [NSURL fileURLWithPath:path];
     492             :                 
     493             :                 if (url != nil)
     494             :                 {
     495             :                         stale = YES;
     496             :                         if (create)
     497             :                         {
     498             :                                 NSFileManager *fmgr = [NSFileManager defaultManager];
     499             :                                 if (![fmgr fileExistsAtPath:path])
     500             :                                 {
     501             :                                         [fmgr oo_createDirectoryAtPath:path attributes:nil];
     502             :                                 }
     503             :                         }
     504             :                 }
     505             :         }
     506             :         
     507             :         if (stale)
     508             :         {
     509             :                 snapshotDirDict = JAPersistentFileReferenceFromURL(url);
     510             :                 if (snapshotDirDict != nil)
     511             :                 {
     512             :                         SetPreference(kSnapshotsDirRefKey, snapshotDirDict);
     513             :                         SetPreference(kSnapshotsDirNameKey, [[url path] lastPathComponent]);
     514             :                 }
     515             :                 else
     516             :                 {
     517             :                         RemovePreference(kSnapshotsDirRefKey);
     518             :                 }
     519             :         }
     520             :         
     521             :         return url;
     522             : }
     523             : 
     524             : 
     525             : - (IBAction) showSnapshotsAction:sender
     526             : {
     527             :         [[NSWorkspace sharedWorkspace] openURL:[self snapshotsURLCreatingIfNeeded:YES]];
     528             : }
     529             : 
     530             : 
     531             : - (IBAction) showAddOnsAction:sender
     532             : {
     533             :         NSArray *paths = ResourceManager.userRootPaths;
     534             :         
     535             :         // Look for an AddOns directory that actually contains some AddOns.
     536             :         for (NSString *path in paths) {
     537             :                 if ([self addOnsExistAtPath:path]) {
     538             :                         [self openPath:path];
     539             :                         return;
     540             :                 }
     541             :         }
     542             :         
     543             :         // If that failed, look for an AddOns directory that actually exists.
     544             :         for (NSString *path in paths) {
     545             :                 if ([self isDirectoryAtPath:path]) {
     546             :                         [self openPath:path];
     547             :                         return;
     548             :                 }
     549             :         }
     550             :         
     551             :         // None found, create the default path.
     552             :         [NSFileManager.defaultManager createDirectoryAtPath:[paths objectAtIndex:0]
     553             :                                                         withIntermediateDirectories:YES
     554             :                                                                                          attributes:nil
     555             :                                                                                                   error:NULL];
     556             :         [self openPath:[paths objectAtIndex:0]];
     557             : }
     558             : 
     559             : 
     560           0 : - (BOOL) isDirectoryAtPath:(NSString *)path
     561             : {
     562             :         BOOL isDirectory;
     563             :         return [NSFileManager.defaultManager fileExistsAtPath:path isDirectory:&isDirectory] && isDirectory;
     564             : }
     565             : 
     566             : 
     567           0 : - (BOOL) addOnsExistAtPath:(NSString *)path
     568             : {
     569             :         if (![self isDirectoryAtPath:path])  return NO;
     570             :         
     571             :         NSWorkspace *workspace = NSWorkspace.sharedWorkspace;
     572             :         for (NSString *subPath in [NSFileManager.defaultManager enumeratorAtPath:path]) {
     573             :                 subPath = [path stringByAppendingPathComponent:subPath];
     574             :                 NSString *type = [workspace typeOfFile:subPath error:NULL];
     575             :                 if ([workspace type:type conformsToType:@"org.aegidian.oolite.expansion"])  return YES;
     576             :         }
     577             :         
     578             :         return NO;
     579             : }
     580             : 
     581             : 
     582           0 : - (void) openPath:(NSString *)path
     583             : {
     584             :         [NSWorkspace.sharedWorkspace openURL:[NSURL fileURLWithPath:path]];
     585             : }
     586             : 
     587             : 
     588           0 : - (BOOL) validateMenuItem:(NSMenuItem *)menuItem
     589             : {
     590             :         SEL action = menuItem.action;
     591             :         
     592             :         if (action == @selector(showLogAction:))
     593             :         {
     594             :                 // the first path is always Resources
     595             :                 return ([[NSFileManager defaultManager] fileExistsAtPath:[OOLogHandlerGetLogBasePath() stringByAppendingPathComponent:@"Previous.log"]]);
     596             :         }
     597             :         
     598             :         if (action == @selector(showAddOnsAction:))
     599             :         {
     600             :                 // Always enabled in unrestricted mode, to allow users to add OXPs more easily.
     601             :                 return [ResourceManager useAddOns] != nil;
     602             :         }
     603             :         
     604             :         if (action == @selector(showSnapshotsAction:))
     605             :         {
     606             :                 BOOL    pathIsDirectory;
     607             :                 if(![[NSFileManager defaultManager] fileExistsAtPath:[self snapshotsURLCreatingIfNeeded:NO].path isDirectory:&pathIsDirectory])
     608             :                 {
     609             :                         return NO;
     610             :                 }
     611             :                 return pathIsDirectory;
     612             :         }
     613             :         
     614             :         if (action == @selector(toggleFullScreenAction:))
     615             :         {
     616             :                 if (_fullScreenController.fullScreenMode)
     617             :                 {
     618             :                         // NOTE: not DESC, because menu titles are not generally localizable.
     619             :                         menuItem.title = NSLocalizedString(@"Exit Full Screen", NULL);
     620             :                 }
     621             :                 else
     622             :                 {
     623             :                         menuItem.title = NSLocalizedString(@"Enter Full Screen", NULL);
     624             :                 }
     625             :         }
     626             :         
     627             :         // default
     628             :         return YES;
     629             : }
     630             : 
     631             : 
     632           0 : - (NSMenu *)applicationDockMenu:(NSApplication *)sender
     633             : {
     634             :         return dockMenu;
     635             : }
     636             : 
     637             : #elif OOLITE_SDL
     638             : 
     639             : - (NSURL *) snapshotsURLCreatingIfNeeded:(BOOL)create
     640             : {
     641             :         NSURL *url = [NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingPathComponent:DESC(@"snapshots-directory-name")]];
     642             :         
     643             :         if (create)
     644             :         {
     645             :                 NSString *path = [url path];
     646             :                 NSFileManager *fmgr = [NSFileManager defaultManager];
     647             :                 if (![fmgr fileExistsAtPath:path])
     648             :                 {
     649             :                         [fmgr createDirectoryAtPath:path attributes:nil];
     650             :                 }
     651             :         }
     652             :         return url;
     653             : }
     654             : 
     655             : #else
     656             :         #error Unknown environment!
     657             : #endif
     658             : 
     659             : - (void) logProgress:(NSString *)message
     660             : {
     661             :         if (![UNIVERSE doingStartUp])  return;
     662             :         
     663             : #if OOLITE_MAC_OS_X
     664             :         [splashProgressTextField setStringValue:message];
     665             :         [splashProgressTextField display];
     666             : #endif
     667             :         if([message length] > 0)
     668             :         {
     669             :                 OOLog(@"startup.progress", @"===== [%.2f s] %@", -[_splashStart timeIntervalSinceNow], message);
     670             :         }
     671             : }
     672             : 
     673             : 
     674             : #if OO_DEBUG
     675             : #if OOLITE_MAC_OS_X
     676             : - (BOOL) debugMessageTrackingIsOn
     677             : {
     678             :         return splashProgressTextField != nil;
     679             : }
     680             : 
     681             : 
     682             : - (NSString *) debugMessageCurrentString
     683             : {
     684             :         return [splashProgressTextField stringValue];
     685             : }
     686             : #else
     687             : - (BOOL) debugMessageTrackingIsOn
     688             : {
     689             :         return OOLogWillDisplayMessagesInClass(@"startup.progress");
     690             : }
     691             : 
     692             : 
     693             : - (NSString *) debugMessageCurrentString
     694             : {
     695             :         return @"";
     696             : }
     697             : #endif
     698             : 
     699             : - (void) debugLogProgress:(NSString *)format, ...
     700             : {
     701             :         va_list args;
     702             :         va_start(args, format);
     703             :         [self debugLogProgress:format arguments:args];
     704             :         va_end(args);
     705             : }
     706             : 
     707             : 
     708             : - (void) debugLogProgress:(NSString *)format arguments:(va_list)arguments
     709             : {
     710             :         NSString *message = [[[NSString alloc] initWithFormat:format arguments:arguments] autorelease];
     711             :         [self logProgress:message];
     712             : }
     713             : 
     714             : 
     715             : static NSMutableArray *sMessageStack;
     716             : 
     717             : - (void) debugPushProgressMessage:(NSString *)format, ...
     718             : {
     719             :         if ([self debugMessageTrackingIsOn])
     720             :         {
     721             :                 if (sMessageStack == nil)  sMessageStack = [[NSMutableArray alloc] init];
     722             :                 [sMessageStack addObject:[self debugMessageCurrentString]];
     723             :                 
     724             :                 va_list args;
     725             :                 va_start(args, format);
     726             :                 [self debugLogProgress:format arguments:args];
     727             :                 va_end(args);
     728             :         }
     729             :         
     730             :         OOLogIndentIf(@"startup.progress");
     731             : }
     732             : 
     733             : 
     734             : - (void) debugPopProgressMessage
     735             : {
     736             :         OOLogOutdentIf(@"startup.progress");
     737             :         
     738             :         if ([sMessageStack count] > 0)
     739             :         {
     740             :                 NSString *message = [sMessageStack lastObject];
     741             :                 if ([message length] > 0)  [self logProgress:message];
     742             :                 [sMessageStack removeLastObject];
     743             :         }
     744             : }
     745             : 
     746             : #endif
     747             : 
     748             : 
     749             : - (void) endSplashScreen
     750             : {
     751             :         OOLogSetDisplayMessagesInClass(@"startup.progress", NO);
     752             :         
     753             : #if OOLITE_MAC_OS_X
     754             :         // These views will be released when we replace the content view.
     755             :         splashProgressTextField = nil;
     756             :         splashView = nil;
     757             :         
     758             :         [gameWindow setAcceptsMouseMovedEvents:YES];
     759             :         [gameWindow setContentView:gameView];
     760             :         [gameWindow makeFirstResponder:gameView];
     761             : #elif OOLITE_SDL
     762             :         [gameView endSplashScreen];
     763             : #endif
     764             : }
     765             : 
     766             : 
     767             : #if OOLITE_MAC_OS_X
     768             : 
     769             : // NIB methods
     770           0 : - (void)awakeFromNib
     771             : {
     772             :         NSString                                *path = nil;
     773             :         
     774             :         // Set contents of Help window
     775             :         path = [[NSBundle mainBundle] pathForResource:@"OoliteReadMe" ofType:@"pdf"];
     776             :         if (path != nil)
     777             :         {
     778             :                 PDFDocument *document = [[PDFDocument alloc] initWithURL:[NSURL fileURLWithPath:path]];
     779             :                 [helpView setDocument:document];
     780             :                 [document release];
     781             :         }
     782             :         [helpView setBackgroundColor:[NSColor whiteColor]];
     783             : }
     784             : 
     785             : 
     786             : // delegate methods
     787           0 : - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
     788             : {
     789             :         if ([[filename pathExtension] isEqual:@"oolite-save"])
     790             :         {
     791             :                 [self setPlayerFileToLoad:filename];
     792             :                 [self setPlayerFileDirectory:filename];
     793             :                 return YES;
     794             :         }
     795             :         if ([[filename pathExtension] isEqualToString:@"oxp"])
     796             :         {
     797             :                 BOOL dir_test;
     798             :                 [[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&dir_test];
     799             :                 if (dir_test)
     800             :                 {
     801             :                         if (expansionPathsToInclude == nil)
     802             :                         {
     803             :                                 expansionPathsToInclude = [[NSMutableArray alloc] init];
     804             :                         }
     805             :                         [expansionPathsToInclude addObject:filename];
     806             :                         return YES;
     807             :                 }
     808             :         }
     809             :         return NO;
     810             : }
     811             : 
     812             : 
     813             : - (void) exitAppWithContext:(NSString *)context
     814             : {
     815             :         [gameView.window orderOut:nil];
     816             :         [(OoliteApp *)NSApp setExitContext:context];
     817             :         [NSApp terminate:self];
     818             : }
     819             : 
     820             : 
     821           0 : - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
     822             : {
     823             :         [[OOCacheManager sharedCache] finishOngoingFlush];
     824             :         OOLoggingTerminate();
     825             :         return NSTerminateNow;
     826             : }
     827             : 
     828             : #elif OOLITE_SDL
     829             : 
     830             : - (void) exitAppWithContext:(NSString *)context
     831             : {
     832             :         OOLog(@"exit.context", @"Exiting: %@.", context);
     833             : #if (OOLITE_GNUSTEP && !defined(NDEBUG))
     834             :         [[OODebugMonitor sharedDebugMonitor] applicationWillTerminate];
     835             : #endif
     836             : #if OOLITE_WINDOWS
     837             :         // This should not be required normally but we have to ensure that
     838             :         // desktop resolution is restored also on some Intel cards on Win10
     839             :         if (![gameView atDesktopResolution])
     840             :         {
     841             :                 OOLog(@"gameController.exitApp", @"%@", @"Restoring desktop resolution.");
     842             :                 ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
     843             :         }
     844             : #endif
     845             :         [[NSUserDefaults standardUserDefaults] synchronize];
     846             :         OOLog(@"gameController.exitApp", @"%@", @".GNUstepDefaults synchronized.");
     847             :         OOLoggingTerminate();
     848             :         SDL_Quit();
     849             :         [[OOOpenALController sharedController] shutdown];
     850             :         exit(0);
     851             : }
     852             : 
     853             : #else
     854             :         #error Unknown environment!
     855             : #endif
     856             : 
     857             : 
     858             : - (void) exitAppCommandQ
     859             : {
     860             :         [self exitAppWithContext:@"Command-Q"];
     861             : }
     862             : 
     863             : 
     864             : - (void)windowDidResize:(NSNotification *)aNotification
     865             : {
     866             :         [gameView updateScreen];
     867             : }
     868             : 
     869             : 
     870             : - (NSString *) playerFileToLoad
     871             : {
     872             :         return playerFileToLoad;
     873             : }
     874             : 
     875             : 
     876             : - (void) setPlayerFileToLoad:(NSString *)filename
     877             : {
     878             :         if (playerFileToLoad)
     879             :                 [playerFileToLoad autorelease];
     880             :         playerFileToLoad = nil;
     881             :         if ([[[filename pathExtension] lowercaseString] isEqual:@"oolite-save"])
     882             :                 playerFileToLoad = [filename copy];
     883             : }
     884             : 
     885             : 
     886             : - (NSString *) playerFileDirectory
     887             : {
     888             :         if (playerFileDirectory == nil)
     889             :         {
     890             :                 playerFileDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"save-directory"];
     891             :                 if (playerFileDirectory != nil && ![[NSFileManager defaultManager] fileExistsAtPath:playerFileDirectory])
     892             :                 {
     893             :                         playerFileDirectory = nil;
     894             :                 }
     895             :                 if (playerFileDirectory == nil)  playerFileDirectory = [[NSFileManager defaultManager] defaultCommanderPath];
     896             :                 
     897             :                 [playerFileDirectory retain];
     898             :         }
     899             :         
     900             :         return playerFileDirectory;
     901             : }
     902             : 
     903             : 
     904             : - (void) setPlayerFileDirectory:(NSString *)filename
     905             : {       
     906             :         if (playerFileDirectory != nil)
     907             :         {
     908             :                 [playerFileDirectory autorelease];
     909             :                 playerFileDirectory = nil;
     910             :         }
     911             :         
     912             :         if ([[[filename pathExtension] lowercaseString] isEqual:@"oolite-save"])
     913             :         {
     914             :                 filename = [filename stringByDeletingLastPathComponent];
     915             :         }
     916             :         
     917             :         playerFileDirectory = [filename retain];
     918             :         [[NSUserDefaults standardUserDefaults] setObject:filename forKey:@"save-directory"];
     919             : }
     920             : 
     921             : 
     922           0 : - (void)reportUnhandledStartupException:(NSException *)exception
     923             : {
     924             :         OOLog(@"startup.exception", @"***** Unhandled exception during startup: %@ (%@).", [exception name], [exception reason]);
     925             :         
     926             :         #if OOLITE_MAC_OS_X
     927             :                 // Display an error alert.
     928             :                 // TODO: provide better information on reporting bugs in the manual, and refer to it here.
     929             :                 NSRunCriticalAlertPanel(@"Oolite failed to start up, because an unhandled exception occurred.", @"An exception of type %@ occurred. If this problem persists, please file a bug report.", @"OK", NULL, NULL, [exception name]);
     930             :         #endif
     931             : }
     932             : 
     933             : 
     934             : - (void)setUpBasicOpenGLStateWithSize:(NSSize)viewSize
     935             : {
     936             :         OOOpenGLExtensionManager        *extMgr = [OOOpenGLExtensionManager sharedManager];
     937             :         
     938             :         float   ratio = 0.5;
     939             :         float   aspect = viewSize.height/viewSize.width;
     940             :         
     941             :         OOGL(glClearColor(0.0, 0.0, 0.0, 0.0));
     942             :         OOGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
     943             :         
     944             :         OOGL(glClearDepth(1.0));
     945             :         OOGL(glViewport(0, 0, viewSize.width, viewSize.height));
     946             :         
     947             :         OOGLResetProjection(); // reset matrix
     948             :         OOGLFrustum(-ratio, ratio, -aspect*ratio, aspect*ratio, 1.0, MAX_CLEAR_DEPTH);  // set projection matrix
     949             :                 
     950             :         OOGL(glDepthFunc(GL_LESS));                     // depth buffer
     951             :         
     952             :         if (UNIVERSE)
     953             :         {
     954             :                 [UNIVERSE setLighting];
     955             :         }
     956             :         else
     957             :         {
     958             :                 GLfloat black[4] =      {0.0, 0.0, 0.0, 1.0};
     959             :                 GLfloat white[] =       {1.0, 1.0, 1.0, 1.0};
     960             :                 GLfloat stars_ambient[] =       {0.25, 0.2, 0.25, 1.0};
     961             :                 
     962             :                 OOGL(glLightfv(GL_LIGHT1, GL_AMBIENT, black));
     963             :                 OOGL(glLightfv(GL_LIGHT1, GL_SPECULAR, white));
     964             :                 OOGL(glLightfv(GL_LIGHT1, GL_DIFFUSE, white));
     965             :                 OOGL(glLightfv(GL_LIGHT1, GL_POSITION, black));
     966             :                 OOGL(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, stars_ambient));
     967             :                 
     968             :         }
     969             :         
     970             :         if ([extMgr usePointSmoothing])  OOGL(glEnable(GL_POINT_SMOOTH));
     971             :         if ([extMgr useLineSmoothing])  OOGL(glEnable(GL_LINE_SMOOTH));
     972             :         
     973             :         // world's simplest OpenGL optimisations...
     974             : #if GL_APPLE_transform_hint
     975             :         if ([extMgr haveExtension:@"GL_APPLE_transform_hint"])
     976             :         {
     977             :                 OOGL(glHint(GL_TRANSFORM_HINT_APPLE, GL_FASTEST));
     978             :         }
     979             : #endif
     980             :         
     981             :         OOGL(glDisable(GL_NORMALIZE));
     982             :         OOGL(glDisable(GL_RESCALE_NORMAL));
     983             :         
     984             : #if GL_VERSION_1_2
     985             :         // For OpenGL 1.2 or later, we want GL_SEPARATE_SPECULAR_COLOR all the time.
     986             :         if ([extMgr versionIsAtLeastMajor:1 minor:2])
     987             :         {
     988             :                 OOGL(glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR));
     989             :         }
     990             : #endif
     991             : }
     992             : 
     993             : 
     994             : #ifndef NDEBUG
     995             : /*      This method exists purely to suppress Clang static analyzer warnings that
     996             :         these ivars are unused (but may be used by categories, which they are).
     997             : */
     998           0 : - (BOOL) suppressClangStuff
     999             : {
    1000             :         return pauseSelector &&
    1001             :         pauseTarget;
    1002             : }
    1003             : #endif
    1004             : 
    1005             : @end
    1006             : 
    1007             : 
    1008             : #if OOLITE_MAC_OS_X
    1009             : 
    1010           0 : static void SetUpSparkle(void)
    1011             : {
    1012           0 : #define FEED_URL_BASE                   "http://www.oolite.org/updates/"
    1013           0 : #define TEST_RELEASE_FEED_NAME  "oolite-mac-test-release-appcast.xml"
    1014           0 : #define DEPLOYMENT_FEED_NAME    "oolite-mac-appcast.xml"
    1015             : 
    1016           0 : #define TEST_RELEASE_FEED_URL   (@ FEED_URL_BASE TEST_RELEASE_FEED_NAME)
    1017           0 : #define DEPLOYMENT_FEED_URL             (@ FEED_URL_BASE DEPLOYMENT_FEED_NAME)
    1018             : 
    1019             : // Default to test releases in test release or debug builds, and stable releases for deployment builds.
    1020             : #ifdef NDEBUG
    1021             : #define DEFAULT_TEST_RELEASE    0
    1022             : #else
    1023           0 : #define DEFAULT_TEST_RELEASE    1
    1024             : #endif
    1025             :         
    1026             :         BOOL useTestReleases = [[NSUserDefaults standardUserDefaults] oo_boolForKey:@"use-test-release-updates"
    1027             :                                                                                                                                    defaultValue:DEFAULT_TEST_RELEASE];
    1028             :         
    1029             :         SUUpdater *updater = [SUUpdater sharedUpdater];
    1030             :         [updater setFeedURL:[NSURL URLWithString:useTestReleases ? TEST_RELEASE_FEED_URL : DEPLOYMENT_FEED_URL]];
    1031             : }
    1032             : 
    1033             : #endif

Generated by: LCOV version 1.14