2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "DesktopPlatformPrivatePCH.h"
# include "MacApplication.h"
2014-05-13 18:23:53 -04:00
# include "FeedbackContextMarkup.h"
2014-05-14 18:56:27 -04:00
# include "MacNativeFeedbackContext.h"
2014-08-19 10:46:30 -04:00
# include "CocoaThread.h"
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "DesktopPlatform"
2014-09-26 14:32:24 -04:00
class FMacScopedSystemModalMode
{
public :
FMacScopedSystemModalMode ( )
{
MacApplication - > SystemModalMode ( true ) ;
}
~ FMacScopedSystemModalMode ( )
{
MacApplication - > SystemModalMode ( false ) ;
}
private :
FScopedSystemModalMode SystemModalMode ;
} ;
2014-03-14 14:13:41 -04:00
class FCocoaScopeContext
{
public :
FCocoaScopeContext ( void )
{
SCOPED_AUTORELEASE_POOL ;
PreviousContext = [ NSOpenGLContext currentContext ] ;
}
~ FCocoaScopeContext ( void )
{
SCOPED_AUTORELEASE_POOL ;
NSOpenGLContext * NewContext = [ NSOpenGLContext currentContext ] ;
if ( PreviousContext ! = NewContext )
{
if ( PreviousContext )
{
[ PreviousContext makeCurrentContext ] ;
}
else
{
[ NSOpenGLContext clearCurrentContext ] ;
}
}
}
private :
NSOpenGLContext * PreviousContext ;
} ;
/**
* Custom accessory view class to allow choose kind of file extension
*/
@ interface FFileDialogAccessoryView : NSView
{
@ private
NSPopUpButton * PopUpButton ;
NSTextField * TextField ;
NSSavePanel * DialogPanel ;
NSMutableArray * AllowedFileTypes ;
2014-10-30 13:21:40 -04:00
int32 SelectedExtension ;
2014-03-14 14:13:41 -04:00
}
- ( id ) initWithFrame : ( NSRect ) frameRect dialogPanel : ( NSSavePanel * ) panel ;
- ( void ) PopUpButtonAction : ( id ) sender ;
- ( void ) AddAllowedFileTypes : ( NSArray * ) array ;
- ( void ) SetExtensionsAtIndex : ( int32 ) index ;
2014-10-30 13:21:40 -04:00
- ( int32 ) SelectedExtension ;
2014-03-14 14:13:41 -04:00
@ end
@ implementation FFileDialogAccessoryView
- ( id ) initWithFrame : ( NSRect ) frameRect dialogPanel : ( NSSavePanel * ) panel
{
self = [ super initWithFrame : frameRect ] ;
DialogPanel = panel ;
FString FieldText = LOCTEXT ( " FileExtension " , " File extension: " ) . ToString ( ) ;
CFStringRef FieldTextCFString = FPlatformString : : TCHARToCFString ( * FieldText ) ;
TextField = [ [ NSTextField alloc ] initWithFrame : NSMakeRect ( 0.0 , 48.0 , 90.0 , 25.0 ) ] ;
[ TextField setStringValue : ( NSString * ) FieldTextCFString ] ;
[ TextField setEditable : NO ] ;
[ TextField setBordered : NO ] ;
[ TextField setBackgroundColor : [ NSColor controlColor ] ] ;
PopUpButton = [ [ NSPopUpButton alloc ] initWithFrame : NSMakeRect ( 88.0 , 50.0 , 160.0 , 25.0 ) ] ;
[ PopUpButton setTarget : self ] ;
[ PopUpButton setAction : @ selector ( PopUpButtonAction : ) ] ;
[ self addSubview : TextField ] ;
[ self addSubview : PopUpButton ] ;
return self ;
}
- ( void ) AddAllowedFileTypes : ( NSMutableArray * ) array
{
check ( array ) ;
AllowedFileTypes = array ;
int32 ArrayCount = [ AllowedFileTypes count ] ;
if ( ArrayCount )
{
check ( ArrayCount % 2 = = 0 ) ;
[ PopUpButton removeAllItems ] ;
for ( int32 Index = 0 ; Index < ArrayCount ; Index + = 2 )
{
[ PopUpButton addItemWithTitle : [ AllowedFileTypes objectAtIndex : Index ] ] ;
}
// Set allowed extensions
[ self SetExtensionsAtIndex : 0 ] ;
}
else
{
// Allow all file types
[ DialogPanel setAllowedFileTypes : nil ] ;
}
}
- ( void ) PopUpButtonAction : ( id ) sender
{
NSInteger Index = [ PopUpButton indexOfSelectedItem ] ;
[ self SetExtensionsAtIndex : Index ] ;
}
- ( void ) SetExtensionsAtIndex : ( int32 ) index
{
check ( [ AllowedFileTypes count ] > = index * 2 ) ;
2014-10-30 13:21:40 -04:00
SelectedExtension = index ;
2014-03-14 14:13:41 -04:00
NSString * ExtsToParse = [ AllowedFileTypes objectAtIndex : index * 2 + 1 ] ;
if ( [ ExtsToParse compare : @ " *.* " ] = = NSOrderedSame )
{
[ DialogPanel setAllowedFileTypes : nil ] ;
}
else
{
NSArray * ExtensionsWildcards = [ ExtsToParse componentsSeparatedByString : @ " ; " ] ;
NSMutableArray * Extensions = [ NSMutableArray arrayWithCapacity : [ ExtensionsWildcards count ] ] ;
for ( int32 Index = 0 ; Index < [ ExtensionsWildcards count ] ; + + Index )
{
NSString * Temp = [[ExtensionsWildcards objectAtIndex:Index] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"*."]] ;
[ Extensions addObject : Temp ] ;
}
[ DialogPanel setAllowedFileTypes : Extensions ] ;
}
}
2014-10-30 13:21:40 -04:00
- ( int32 ) SelectedExtension {
return SelectedExtension ;
}
2014-03-14 14:13:41 -04:00
@ end
/**
* Custom accessory view class to allow choose kind of file extension
*/
@ interface FFontDialogAccessoryView : NSView
{
@ private
NSButton * OKButton ;
NSButton * CancelButton ;
bool Result ;
}
- ( id ) initWithFrame : ( NSRect ) frameRect ;
- ( bool ) result ;
- ( IBAction ) onCancel : ( id ) sender ;
- ( IBAction ) onOK : ( id ) sender ;
@ end
@ implementation FFontDialogAccessoryView : NSView
- ( id ) initWithFrame : ( NSRect ) frameRect
{
[ super initWithFrame : frameRect ] ;
CancelButton = [ [ NSButton alloc ] initWithFrame : NSMakeRect ( 10 , 10 , 80 , 24 ) ] ;
[ CancelButton setTitle : @ " Cancel " ] ;
[ CancelButton setBezelStyle : NSRoundedBezelStyle ] ;
[ CancelButton setButtonType : NSMomentaryPushInButton ] ;
[ CancelButton setAction : @ selector ( onCancel : ) ] ;
[ CancelButton setTarget : self ] ;
[ self addSubview : CancelButton ] ;
OKButton = [ [ NSButton alloc ] initWithFrame : NSMakeRect ( 100 , 10 , 80 , 24 ) ] ;
[ OKButton setTitle : @ " OK " ] ;
[ OKButton setBezelStyle : NSRoundedBezelStyle ] ;
[ OKButton setButtonType : NSMomentaryPushInButton ] ;
[ OKButton setAction : @ selector ( onOK : ) ] ;
[ OKButton setTarget : self ] ;
[ self addSubview : OKButton ] ;
Result = false ;
return self ;
}
- ( bool ) result
{
return Result ;
}
- ( IBAction ) onCancel : ( id ) sender
{
Result = false ;
[ NSApp stopModal ] ;
}
- ( IBAction ) onOK : ( id ) sender
{
Result = true ;
[ NSApp stopModal ] ;
}
@ end
bool FDesktopPlatformMac : : OpenFileDialog ( const void * ParentWindowHandle , const FString & DialogTitle , const FString & DefaultPath , const FString & DefaultFile , const FString & FileTypes , uint32 Flags , TArray < FString > & OutFilenames )
{
2014-10-30 13:21:40 -04:00
int32 DummyIdx = 0 ;
return FileDialogShared ( false , ParentWindowHandle , DialogTitle , DefaultPath , DefaultFile , FileTypes , Flags , OutFilenames , DummyIdx ) ;
2014-03-14 14:13:41 -04:00
}
2014-06-17 16:16:40 -04:00
bool FDesktopPlatformMac : : OpenFileDialog ( const void * ParentWindowHandle , const FString & DialogTitle , const FString & DefaultPath , const FString & DefaultFile , const FString & FileTypes , uint32 Flags , TArray < FString > & OutFilenames , int32 & OutFilterIndex )
{
2014-10-30 13:21:40 -04:00
return FileDialogShared ( false , ParentWindowHandle , DialogTitle , DefaultPath , DefaultFile , FileTypes , Flags , OutFilenames , OutFilterIndex ) ;
2014-06-17 16:16:40 -04:00
}
2014-03-14 14:13:41 -04:00
bool FDesktopPlatformMac : : SaveFileDialog ( const void * ParentWindowHandle , const FString & DialogTitle , const FString & DefaultPath , const FString & DefaultFile , const FString & FileTypes , uint32 Flags , TArray < FString > & OutFilenames )
{
2014-10-30 13:21:40 -04:00
int32 DummyIdx = 0 ;
return FileDialogShared ( true , ParentWindowHandle , DialogTitle , DefaultPath , DefaultFile , FileTypes , Flags , OutFilenames , DummyIdx ) ;
2014-03-14 14:13:41 -04:00
}
bool FDesktopPlatformMac : : OpenDirectoryDialog ( const void * ParentWindowHandle , const FString & DialogTitle , const FString & DefaultPath , FString & OutFolderName )
{
MacApplication - > SetCapture ( NULL ) ;
2014-08-19 11:21:24 -04:00
bool bSuccess = false ;
{
2014-09-26 14:32:24 -04:00
FMacScopedSystemModalMode SystemModalScope ;
2014-08-19 11:21:24 -04:00
bSuccess = MainThreadReturn ( ^ {
SCOPED_AUTORELEASE_POOL ;
FCocoaScopeContext ContextGuard ;
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
NSOpenPanel * Panel = [ NSOpenPanel openPanel ] ;
[ Panel setCanChooseFiles : false ] ;
[ Panel setCanChooseDirectories : true ] ;
[ Panel setAllowsMultipleSelection : false ] ;
[ Panel setCanCreateDirectories : true ] ;
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
CFStringRef Title = FPlatformString : : TCHARToCFString ( * DialogTitle ) ;
[ Panel setTitle : ( NSString * ) Title ] ;
CFRelease ( Title ) ;
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
CFStringRef DefaultPathCFString = FPlatformString : : TCHARToCFString ( * DefaultPath ) ;
NSURL * DefaultPathURL = [ NSURL fileURLWithPath : ( NSString * ) DefaultPathCFString ] ;
[ Panel setDirectoryURL : DefaultPathURL ] ;
CFRelease ( DefaultPathCFString ) ;
2014-03-14 14:13:41 -04:00
2015-02-23 16:18:13 -05:00
bool bResult = false ;
2014-03-14 14:13:41 -04:00
2014-08-19 10:46:30 -04:00
NSInteger Result = [ Panel runModal ] ;
2014-03-14 14:13:41 -04:00
2014-08-19 10:46:30 -04:00
if ( Result = = NSFileHandlingPanelOKButton )
{
NSURL * FolderURL = [ [ Panel URLs ] objectAtIndex : 0 ] ;
TCHAR FolderPath [ MAX_PATH ] ;
FPlatformString : : CFStringToTCHAR ( ( CFStringRef ) [ FolderURL path ] , FolderPath ) ;
OutFolderName = FolderPath ;
FPaths : : NormalizeFilename ( OutFolderName ) ;
2015-02-23 16:18:13 -05:00
bResult = true ;
2014-08-19 10:46:30 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
[ Panel close ] ;
2014-03-14 14:13:41 -04:00
2015-02-23 16:18:13 -05:00
return bResult ;
2014-08-19 11:21:24 -04:00
} ) ;
}
2014-03-14 14:13:41 -04:00
MacApplication - > ResetModifierKeys ( ) ;
2014-08-19 10:46:30 -04:00
2014-03-14 14:13:41 -04:00
return bSuccess ;
}
2014-08-13 12:53:47 -04:00
bool FDesktopPlatformMac : : OpenFontDialog ( const void * ParentWindowHandle , FString & OutFontName , float & OutHeight , EFontImportFlags & OutFlags )
2014-03-14 14:13:41 -04:00
{
MacApplication - > SetCapture ( NULL ) ;
2014-08-19 10:46:30 -04:00
2014-08-19 11:21:24 -04:00
bool bSuccess = false ;
{
2014-09-26 14:32:24 -04:00
FMacScopedSystemModalMode SystemModalScope ;
2014-08-19 11:21:24 -04:00
bSuccess = MainThreadReturn ( ^ {
SCOPED_AUTORELEASE_POOL ;
FCocoaScopeContext ContextGuard ;
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
NSFontPanel * Panel = [ NSFontPanel sharedFontPanel ] ;
[ Panel setFloatingPanel : false ] ;
[ [ Panel standardWindowButton : NSWindowCloseButton ] setEnabled : false ] ;
FFontDialogAccessoryView * AccessoryView = [ [ FFontDialogAccessoryView alloc ] initWithFrame : NSMakeRect ( 0.0 , 0.0 , 190.0 , 80.0 ) ] ;
[ Panel setAccessoryView : AccessoryView ] ;
2014-03-14 14:13:41 -04:00
2014-08-19 10:46:30 -04:00
[ NSApp runModalForWindow : Panel ] ;
2014-08-19 11:21:24 -04:00
[ Panel close ] ;
2014-03-14 14:13:41 -04:00
2015-02-23 16:18:13 -05:00
bool bResult = [ AccessoryView result ] ;
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
[ Panel setAccessoryView : NULL ] ;
[ AccessoryView release ] ;
[ [ Panel standardWindowButton : NSWindowCloseButton ] setEnabled : true ] ;
2014-08-19 10:46:30 -04:00
2015-02-23 16:18:13 -05:00
if ( bResult )
2014-08-19 10:46:30 -04:00
{
2014-08-19 11:21:24 -04:00
NSFont * Font = [ Panel panelConvertFont : [ NSFont userFontOfSize : 0 ] ] ;
TCHAR FontName [ MAX_PATH ] ;
FPlatformString : : CFStringToTCHAR ( ( CFStringRef ) [ Font fontName ] , FontName ) ;
OutFontName = FontName ;
OutHeight = [ Font pointSize ] ;
auto FontFlags = EFontImportFlags : : None ;
if ( [ Font underlineThickness ] > = 1.0 )
{
FontFlags | = EFontImportFlags : : EnableUnderline ;
}
OutFlags = FontFlags ;
2014-08-19 10:46:30 -04:00
}
2015-02-23 16:18:13 -05:00
return bResult ;
2014-08-19 11:21:24 -04:00
} ) ;
}
2014-08-19 10:46:30 -04:00
2014-03-14 14:13:41 -04:00
MacApplication - > ResetModifierKeys ( ) ;
2014-08-19 10:46:30 -04:00
2014-03-14 14:13:41 -04:00
return bSuccess ;
}
void OpenLauncherCommandLine ( const FString & InCommandLine )
{
FString CommandLine = InCommandLine ;
FString TransferFilePath = FPaths : : Combine ( FPlatformProcess : : UserSettingsDir ( ) , TEXT ( " UnrealEngineLauncher " ) , TEXT ( " com " ) , TEXT ( " transfer.tmp " ) ) ;
IFileManager & FileManager = IFileManager : : Get ( ) ;
FArchive * TransferFile = NULL ;
int32 RetryCount = 0 ;
while ( RetryCount < 2000 )
{
TransferFile = FileManager . CreateFileWriter ( * TransferFilePath , FILEWRITE_EvenIfReadOnly ) ;
if ( TransferFile ! = nullptr )
{
break ;
}
+ + RetryCount ;
FPlatformProcess : : Sleep ( 0.01f ) ;
}
if ( TransferFile = = NULL )
{
TransferFile = FileManager . CreateFileWriter ( * TransferFilePath , FILEWRITE_EvenIfReadOnly | FILEWRITE_NoFail ) ;
}
if ( TransferFile ! = NULL )
{
* TransferFile < < CommandLine ;
TransferFile - > Close ( ) ;
delete TransferFile ;
}
}
2014-08-19 09:54:22 -04:00
bool FDesktopPlatformMac : : CanOpenLauncher ( bool Install )
{
FString Path ;
return GetLauncherPath ( Path ) | | ( Install & & GetLauncherInstallerPath ( Path ) ) ;
}
2014-04-23 19:02:27 -04:00
bool FDesktopPlatformMac : : OpenLauncher ( bool Install , FString CommandLineParams )
2014-03-14 14:13:41 -04:00
{
2014-04-02 18:09:23 -04:00
// If the launcher is already running, bring it to front
NSArray * RunningLaunchers = [ NSRunningApplication runningApplicationsWithBundleIdentifier : @ " com.epicgames.UnrealEngineLauncher " ] ;
if ( [ RunningLaunchers count ] > 0 )
{
NSRunningApplication * Launcher = [ RunningLaunchers objectAtIndex : 0 ] ;
2014-10-03 08:54:52 -04:00
if ( ! Launcher . hidden | | Install | | CommandLineParams . Len ( ) > 0 ) // If the launcher is running, but hidden, don't activate on editor startup
{
[ Launcher activateWithOptions : NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps ] ;
OpenLauncherCommandLine ( CommandLineParams ) ; // create a temp file that will tell running Launcher instance to switch to Marketplace tab
}
2014-04-02 18:09:23 -04:00
return true ;
}
2014-08-19 09:54:22 -04:00
// Try to start a new instance
FString LauncherPath ;
if ( GetLauncherPath ( LauncherPath ) )
2014-03-14 14:13:41 -04:00
{
2014-08-19 09:54:22 -04:00
if ( FParse : : Param ( FCommandLine : : Get ( ) , TEXT ( " Dev " ) ) )
2014-03-14 14:13:41 -04:00
{
2014-08-19 09:54:22 -04:00
CommandLineParams + = TEXT ( " -noselfupdate " ) ;
2014-03-14 14:13:41 -04:00
}
2014-08-19 09:54:22 -04:00
return FPlatformProcess : : CreateProc ( * LauncherPath , * CommandLineParams , true , false , false , NULL , 0 , * FPaths : : GetPath ( LauncherPath ) , NULL ) . IsValid ( ) ;
2014-03-14 14:13:41 -04:00
}
2014-08-19 09:54:22 -04:00
// Try to install it
FString InstallerPath ;
if ( GetLauncherInstallerPath ( InstallerPath ) )
2014-03-14 14:13:41 -04:00
{
2014-08-19 09:54:22 -04:00
FPlatformProcess : : LaunchFileInDefaultExternalApplication ( * InstallerPath ) ;
return true ;
2014-03-14 14:13:41 -04:00
}
2014-08-19 09:54:22 -04:00
return false ;
2014-03-14 14:13:41 -04:00
}
2014-10-30 13:21:40 -04:00
bool FDesktopPlatformMac : : FileDialogShared ( bool bSave , const void * ParentWindowHandle , const FString & DialogTitle , const FString & DefaultPath , const FString & DefaultFile , const FString & FileTypes , uint32 Flags , TArray < FString > & OutFilenames , int32 & OutFilterIndex )
2014-03-14 14:13:41 -04:00
{
MacApplication - > SetCapture ( NULL ) ;
2014-08-19 11:21:24 -04:00
bool bSuccess = false ;
{
2014-09-26 14:32:24 -04:00
FMacScopedSystemModalMode SystemModalScope ;
2014-08-19 11:21:24 -04:00
bSuccess = MainThreadReturn ( ^ {
SCOPED_AUTORELEASE_POOL ;
FCocoaScopeContext ContextGuard ;
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
NSSavePanel * Panel = bSave ? [ NSSavePanel savePanel ] : [ NSOpenPanel openPanel ] ;
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
if ( ! bSave )
2014-03-14 14:13:41 -04:00
{
2014-08-19 11:21:24 -04:00
NSOpenPanel * OpenPanel = ( NSOpenPanel * ) Panel ;
[ OpenPanel setCanChooseFiles : true ] ;
[ OpenPanel setCanChooseDirectories : false ] ;
[ OpenPanel setAllowsMultipleSelection : Flags & EFileDialogFlags : : Multiple ] ;
2014-03-14 14:13:41 -04:00
}
2014-08-19 10:46:30 -04:00
2014-08-19 11:21:24 -04:00
[ Panel setCanCreateDirectories : bSave ] ;
2014-08-19 10:46:30 -04:00
2014-08-19 11:21:24 -04:00
CFStringRef Title = FPlatformString : : TCHARToCFString ( * DialogTitle ) ;
[ Panel setTitle : ( NSString * ) Title ] ;
CFRelease ( Title ) ;
2014-08-19 10:46:30 -04:00
2014-08-19 11:21:24 -04:00
CFStringRef DefaultPathCFString = FPlatformString : : TCHARToCFString ( * DefaultPath ) ;
NSURL * DefaultPathURL = [ NSURL fileURLWithPath : ( NSString * ) DefaultPathCFString ] ;
[ Panel setDirectoryURL : DefaultPathURL ] ;
CFRelease ( DefaultPathCFString ) ;
CFStringRef FileNameCFString = FPlatformString : : TCHARToCFString ( * DefaultFile ) ;
[ Panel setNameFieldStringValue : ( NSString * ) FileNameCFString ] ;
CFRelease ( FileNameCFString ) ;
FFileDialogAccessoryView * AccessoryView = [ [ FFileDialogAccessoryView alloc ] initWithFrame : NSMakeRect ( 0.0 , 0.0 , 250.0 , 85.0 ) dialogPanel : Panel ] ;
[ Panel setAccessoryView : AccessoryView ] ;
TArray < FString > FileTypesArray ;
2015-03-02 15:51:37 -05:00
int32 NumFileTypes = FileTypes . ParseIntoArray ( FileTypesArray , TEXT ( " | " ) , true ) ;
2014-08-19 11:21:24 -04:00
NSMutableArray * AllowedFileTypes = [ NSMutableArray arrayWithCapacity : NumFileTypes ] ;
if ( NumFileTypes > 0 )
{
for ( int32 Index = 0 ; Index < NumFileTypes ; + + Index )
{
CFStringRef Type = FPlatformString : : TCHARToCFString ( * FileTypesArray [ Index ] ) ;
[ AllowedFileTypes addObject : ( NSString * ) Type ] ;
CFRelease ( Type ) ;
}
}
[ AccessoryView AddAllowedFileTypes : AllowedFileTypes ] ;
2015-02-23 16:18:13 -05:00
bool bOkPressed = false ;
2014-08-19 11:21:24 -04:00
NSWindow * FocusWindow = [ [ NSApplication sharedApplication ] keyWindow ] ;
2014-08-19 10:46:30 -04:00
NSInteger Result = [ Panel runModal ] ;
[ AccessoryView release ] ;
if ( Result = = NSFileHandlingPanelOKButton )
2014-03-14 14:13:41 -04:00
{
2014-08-19 10:46:30 -04:00
if ( bSave )
2014-03-14 14:13:41 -04:00
{
TCHAR FilePath [ MAX_PATH ] ;
2014-08-19 10:46:30 -04:00
FPlatformString : : CFStringToTCHAR ( ( CFStringRef ) [ [ Panel URL ] path ] , FilePath ) ;
2014-03-14 14:13:41 -04:00
new ( OutFilenames ) FString ( FilePath ) ;
}
2014-08-19 10:46:30 -04:00
else
{
NSOpenPanel * OpenPanel = ( NSOpenPanel * ) Panel ;
for ( NSURL * FileURL in [ OpenPanel URLs ] )
{
TCHAR FilePath [ MAX_PATH ] ;
FPlatformString : : CFStringToTCHAR ( ( CFStringRef ) [ FileURL path ] , FilePath ) ;
new ( OutFilenames ) FString ( FilePath ) ;
}
2014-10-30 13:21:40 -04:00
OutFilterIndex = [ AccessoryView SelectedExtension ] ;
2014-08-19 10:46:30 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-19 10:46:30 -04:00
// Make sure all filenames gathered have their paths normalized
for ( auto FilenameIt = OutFilenames . CreateIterator ( ) ; FilenameIt ; + + FilenameIt )
{
FPaths : : NormalizeFilename ( * FilenameIt ) ;
}
2014-03-14 14:13:41 -04:00
2015-02-23 16:18:13 -05:00
bOkPressed = true ;
2014-08-19 10:46:30 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-19 11:21:24 -04:00
[ Panel close ] ;
if ( FocusWindow )
{
[ FocusWindow makeKeyWindow ] ;
}
2014-03-14 14:13:41 -04:00
2015-02-23 16:18:13 -05:00
return bOkPressed ;
2014-08-19 11:21:24 -04:00
} ) ;
}
2014-06-13 11:09:48 -04:00
2014-08-19 10:46:30 -04:00
MacApplication - > ResetModifierKeys ( ) ;
2014-03-14 14:13:41 -04:00
return bSuccess ;
}
2014-05-06 10:27:35 -04:00
bool FDesktopPlatformMac : : RegisterEngineInstallation ( const FString & RootDir , FString & OutIdentifier )
{
2014-05-13 10:10:18 -04:00
bool bRes = false ;
if ( IsValidRootDirectory ( RootDir ) )
{
FConfigFile ConfigFile ;
FString ConfigPath = FString ( FPlatformProcess : : ApplicationSettingsDir ( ) ) / FString ( TEXT ( " UnrealEngine " ) ) / FString ( TEXT ( " Install.ini " ) ) ;
ConfigFile . Read ( ConfigPath ) ;
FConfigSection & Section = ConfigFile . FindOrAdd ( TEXT ( " Installations " ) ) ;
OutIdentifier = FGuid : : NewGuid ( ) . ToString ( EGuidFormats : : DigitsWithHyphens ) ;
Section . AddUnique ( * OutIdentifier , RootDir ) ;
ConfigFile . Dirty = true ;
ConfigFile . Write ( ConfigPath ) ;
}
return bRes ;
2014-05-06 10:27:35 -04:00
}
2014-04-23 18:32:52 -04:00
void FDesktopPlatformMac : : EnumerateEngineInstallations ( TMap < FString , FString > & OutInstallations )
{
2015-03-13 08:26:18 -04:00
SCOPED_AUTORELEASE_POOL ;
2014-04-23 18:46:48 -04:00
EnumerateLauncherEngineInstallations ( OutInstallations ) ;
2014-04-23 18:59:02 -04:00
// Create temp .uproject file to use with LSCopyApplicationURLsForURL
2014-04-23 20:16:56 -04:00
FString UProjectPath = FString ( FPlatformProcess : : ApplicationSettingsDir ( ) ) / " Unreal.uproject " ;
2014-04-23 18:59:02 -04:00
FArchive * File = IFileManager : : Get ( ) . CreateFileWriter ( * UProjectPath , FILEWRITE_EvenIfReadOnly ) ;
if ( File )
{
File - > Close ( ) ;
delete File ;
}
else
{
2014-07-30 14:51:27 -04:00
FPlatformMisc : : MessageBoxExt ( EAppMsgType : : Ok , * UProjectPath , TEXT ( " Error " ) ) ;
2014-04-23 18:59:02 -04:00
}
FConfigFile ConfigFile ;
FString ConfigPath = FString ( FPlatformProcess : : ApplicationSettingsDir ( ) ) / FString ( TEXT ( " UnrealEngine " ) ) / FString ( TEXT ( " Install.ini " ) ) ;
ConfigFile . Read ( ConfigPath ) ;
FConfigSection & Section = ConfigFile . FindOrAdd ( TEXT ( " Installations " ) ) ;
2014-08-08 11:33:23 -04:00
// Remove invalid entries
TArray < FName > KeysToRemove ;
for ( auto It : Section )
{
const FString & EngineDir = It . Value ;
2014-11-17 14:59:07 -05:00
if ( EngineDir . Contains ( " Unreal Engine.app/Contents/ " ) | | EngineDir . Contains ( " Epic Games Launcher.app/Contents/ " ) | | EngineDir . Contains ( " /Users/Shared/UnrealEngine/Launcher " ) | | ! IFileManager : : Get ( ) . DirectoryExists ( * EngineDir ) )
2014-08-08 11:33:23 -04:00
{
KeysToRemove . Add ( It . Key ) ;
}
}
for ( auto Key : KeysToRemove )
{
Section . Remove ( Key ) ;
}
2014-04-23 18:59:02 -04:00
CFArrayRef AllApps = LSCopyApplicationURLsForURL ( ( __bridge CFURLRef ) [ NSURL fileURLWithPath : UProjectPath . GetNSString ( ) ] , kLSRolesAll ) ;
if ( AllApps )
{
const CFIndex AppsCount = CFArrayGetCount ( AllApps ) ;
for ( CFIndex Index = 0 ; Index < AppsCount ; + + Index )
{
NSURL * AppURL = ( NSURL * ) CFArrayGetValueAtIndex ( AllApps , Index ) ;
NSBundle * AppBundle = [ NSBundle bundleWithURL : AppURL ] ;
FString EngineDir = FString ( [ [ AppBundle bundlePath ] stringByDeletingLastPathComponent ] ) ;
if ( ( [ [ AppBundle bundleIdentifier ] isEqualToString : @ " com.epicgames.UE4Editor " ] | | [ [ AppBundle bundleIdentifier ] isEqualToString : @ " com.epicgames.UE4EditorServices " ] )
2014-11-17 14:59:07 -05:00
& & EngineDir . RemoveFromEnd ( TEXT ( " /Engine/Binaries/Mac " ) ) & & ! EngineDir . Contains ( " Unreal Engine.app/Contents/ " ) & & ! EngineDir . Contains ( " Epic Games Launcher.app/Contents/ " ) & & ! EngineDir . Contains ( " /Users/Shared/UnrealEngine/Launcher " ) )
2014-04-23 18:59:02 -04:00
{
FString EngineId ;
const FName * Key = Section . FindKey ( EngineDir ) ;
if ( Key )
{
EngineId = Key - > ToString ( ) ;
}
else
{
if ( ! OutInstallations . FindKey ( EngineDir ) )
{
2014-08-27 15:29:01 -04:00
EngineId = FGuid : : NewGuid ( ) . ToString ( EGuidFormats : : DigitsWithHyphensInBraces ) ;
2014-04-23 18:59:02 -04:00
Section . AddUnique ( * EngineId , EngineDir ) ;
ConfigFile . Dirty = true ;
}
}
if ( ! EngineId . IsEmpty ( ) & & ! OutInstallations . Find ( EngineId ) )
{
OutInstallations . Add ( EngineId , EngineDir ) ;
}
}
}
ConfigFile . Write ( ConfigPath ) ;
CFRelease ( AllApps ) ;
}
IFileManager : : Get ( ) . Delete ( * UProjectPath ) ;
2014-04-23 18:46:48 -04:00
}
2014-04-23 18:48:24 -04:00
bool FDesktopPlatformMac : : VerifyFileAssociations ( )
2014-04-23 18:46:48 -04:00
{
2014-04-23 18:59:02 -04:00
CFURLRef GlobalDefaultAppURL = NULL ;
OSStatus Status = LSGetApplicationForInfo ( kLSUnknownType , kLSUnknownCreator , CFSTR ( " uproject " ) , kLSRolesAll , NULL , & GlobalDefaultAppURL ) ;
if ( Status = = noErr )
{
NSBundle * GlobalDefaultAppBundle = [ NSBundle bundleWithURL : ( __bridge NSURL * ) GlobalDefaultAppURL ] ;
CFRelease ( GlobalDefaultAppURL ) ;
2014-06-20 13:37:52 -04:00
if ( [ [ GlobalDefaultAppBundle bundleIdentifier ] isEqualToString : @ " com.epicgames.UE4EditorServices " ] )
2014-04-23 18:59:02 -04:00
{
return true ;
}
}
return false ;
2014-04-23 18:46:48 -04:00
}
2014-04-23 18:48:24 -04:00
bool FDesktopPlatformMac : : UpdateFileAssociations ( )
2014-04-23 18:46:48 -04:00
{
2014-04-23 18:59:02 -04:00
OSStatus Status = LSSetDefaultRoleHandlerForContentType ( CFSTR ( " com.epicgames.uproject " ) , kLSRolesAll , CFSTR ( " com.epicgames.UE4EditorServices " ) ) ;
return Status = = noErr ;
2014-04-23 18:32:52 -04:00
}
2014-05-13 18:23:53 -04:00
bool FDesktopPlatformMac : : RunUnrealBuildTool ( const FText & Description , const FString & RootDir , const FString & Arguments , FFeedbackContext * Warn )
{
// Get the path to UBT
FString UnrealBuildToolPath = RootDir / TEXT ( " Engine/Binaries/DotNET/UnrealBuildTool.exe " ) ;
if ( IFileManager : : Get ( ) . FileSize ( * UnrealBuildToolPath ) < 0 )
{
Warn - > Logf ( ELogVerbosity : : Error , TEXT ( " Couldn't find UnrealBuildTool at '%s' " ) , * UnrealBuildToolPath ) ;
return false ;
}
// On Mac we launch UBT with Mono
FString ScriptPath = FPaths : : ConvertRelativePathToFull ( RootDir / TEXT ( " Engine/Build/BatchFiles/Mac/RunMono.sh " ) ) ;
FString CmdLineParams = FString : : Printf ( TEXT ( " \" %s \" \" %s \" %s " ) , * ScriptPath , * UnrealBuildToolPath , * Arguments ) ;
// Spawn it
int32 ExitCode = 0 ;
return FFeedbackContextMarkup : : PipeProcessOutput ( Description , TEXT ( " /bin/sh " ) , CmdLineParams , Warn , & ExitCode ) & & ExitCode = = 0 ;
}
2014-09-18 15:12:13 -04:00
bool FDesktopPlatformMac : : IsUnrealBuildToolRunning ( )
{
// For now assume that if mono application is running, we're running UBT
// @todo: we need to get the commandline for the mono process and check if UBT.exe is in there.
return FPlatformProcess : : IsApplicationRunning ( TEXT ( " mono " ) ) ;
}
2014-08-19 09:54:22 -04:00
bool FDesktopPlatformMac : : GetLauncherPath ( FString & OutLauncherPath ) const
{
// Try the default executable in the binaries directory
if ( FParse : : Param ( FCommandLine : : Get ( ) , TEXT ( " Dev " ) ) )
{
FString LauncherPath = FPaths : : Combine ( * FPaths : : EngineDir ( ) , TEXT ( " Binaries " ) , TEXT ( " Mac " ) , TEXT ( " UnrealEngineLauncher-Mac-Debug.app/Contents/MacOS/UnrealEngineLauncher-Mac-Debug " ) ) ;
if ( FPaths : : FileExists ( LauncherPath ) )
{
OutLauncherPath = LauncherPath ;
return true ;
}
}
else
{
2014-11-17 14:59:07 -05:00
FString LauncherPath = TEXT ( " /Applications/Epic Games Launcher.app/Contents/MacOS/UnrealEngineLauncher-Mac-Shipping " ) ;
2014-08-19 09:54:22 -04:00
if ( FPaths : : FileExists ( LauncherPath ) )
{
OutLauncherPath = LauncherPath ;
return true ;
}
}
// Otherwise search for it...
NSWorkspace * Workspace = [ NSWorkspace sharedWorkspace ] ;
2014-11-17 14:59:07 -05:00
NSString * Path = [ Workspace fullPathForApplication : @ " Epic Games Launcher " ] ;
2014-08-19 09:54:22 -04:00
if ( Path )
{
OutLauncherPath = FString ( Path ) ;
return true ;
}
2015-01-07 09:26:48 -05:00
// Otherwise search for the old Launcher...
Path = [ Workspace fullPathForApplication : @ " Unreal Engine " ] ;
if ( Path )
{
OutLauncherPath = FString ( Path ) ;
return true ;
}
2014-08-19 09:54:22 -04:00
return false ;
}
bool FDesktopPlatformMac : : GetLauncherInstallerPath ( FString & OutInstallerPath ) const
{
// Check if the installer exists
2014-11-17 14:59:07 -05:00
FString InstallerPath = FPaths : : ConvertRelativePathToFull ( FPaths : : Combine ( * FPaths : : EngineDir ( ) , TEXT ( " Extras/UnrealEngineLauncher/EpicGamesLauncher.dmg " ) ) ) ;
2014-08-19 09:54:22 -04:00
if ( FPaths : : FileExists ( InstallerPath ) )
{
OutInstallerPath = InstallerPath ;
return true ;
}
2015-01-07 09:26:48 -05:00
InstallerPath = FPaths : : ConvertRelativePathToFull ( FPaths : : Combine ( * FPaths : : EngineDir ( ) , TEXT ( " Extras/UnrealEngineLauncher/UnrealEngine.dmg " ) ) ) ;
if ( FPaths : : FileExists ( InstallerPath ) )
{
OutInstallerPath = InstallerPath ;
return true ;
}
2014-08-19 09:54:22 -04:00
return false ;
}
2014-05-14 14:53:19 -04:00
FFeedbackContext * FDesktopPlatformMac : : GetNativeFeedbackContext ( )
{
2014-05-14 18:56:27 -04:00
static FMacNativeFeedbackContext Warn ;
return & Warn ;
2014-05-14 14:53:19 -04:00
}
2015-01-16 13:29:54 -05:00
FString FDesktopPlatformMac : : GetUserTempPath ( )
{
2015-01-16 16:20:36 -05:00
return FString ( FPlatformProcess : : UserTempDir ( ) ) ;
2015-01-16 13:29:54 -05:00
}
2014-03-14 14:13:41 -04:00
# undef LOCTEXT_NAMESPACE