2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
IOSTargetPlatform . cpp : Implements the FIOSTargetPlatform class .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "IOSTargetPlatformPrivatePCH.h"
2014-07-22 17:53:31 -04:00
# include "IProjectManager.h"
2014-03-14 14:13:41 -04:00
/* FIOSTargetPlatform structors
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
FIOSTargetPlatform : : FIOSTargetPlatform ( )
{
# if WITH_ENGINE
FConfigCacheIni : : LoadLocalIniFile ( EngineSettings , TEXT ( " Engine " ) , true , * PlatformName ( ) ) ;
TextureLODSettings . Initialize ( EngineSettings , TEXT ( " SystemSettings " ) ) ;
StaticMeshLODSettings . Initialize ( EngineSettings ) ;
# endif // #if WITH_ENGINE
// Initialize Ticker for device discovery
TickDelegate = FTickerDelegate : : CreateRaw ( this , & FIOSTargetPlatform : : HandleTicker ) ;
FTicker : : GetCoreTicker ( ) . AddTicker ( TickDelegate , 10.0f ) ;
2014-07-30 15:36:36 -04:00
// initialize the connected device detector
DeviceHelper . OnDeviceConnected ( ) . AddRaw ( this , & FIOSTargetPlatform : : HandleDeviceConnected ) ;
DeviceHelper . OnDeviceDisconnected ( ) . AddRaw ( this , & FIOSTargetPlatform : : HandleDeviceDisconnected ) ;
DeviceHelper . Initialize ( ) ;
2014-03-14 14:13:41 -04:00
}
FIOSTargetPlatform : : ~ FIOSTargetPlatform ( )
{
FTicker : : GetCoreTicker ( ) . RemoveTicker ( TickDelegate ) ;
}
/* ITargetPlatform interface
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-04-23 17:23:52 -04:00
void FIOSTargetPlatform : : EnableDeviceCheck ( bool OnOff )
{
FIOSDeviceHelper : : EnableDeviceCheck ( OnOff ) ;
}
2014-03-14 14:13:41 -04:00
void FIOSTargetPlatform : : GetAllDevices ( TArray < ITargetDevicePtr > & OutDevices ) const
{
OutDevices . Reset ( ) ;
for ( auto Iter = Devices . CreateConstIterator ( ) ; Iter ; + + Iter )
{
OutDevices . Add ( Iter . Value ( ) ) ;
}
}
ITargetDevicePtr FIOSTargetPlatform : : GetDefaultDevice ( ) const
{
if ( Devices . Num ( ) > 0 )
{
// first device is the default
auto Iter = Devices . CreateConstIterator ( ) ;
if ( Iter )
{
return Iter . Value ( ) ;
}
}
return NULL ;
}
ITargetDevicePtr FIOSTargetPlatform : : GetDevice ( const FTargetDeviceId & DeviceId )
{
return Devices . FindRef ( DeviceId ) ;
}
2014-04-02 18:09:23 -04:00
bool FIOSTargetPlatform : : IsSdkInstalled ( bool bProjectHasCode , FString & OutDocumentationPath ) const
{
bool biOSSDKInstalled = true ; // @todo How do we check that the iOS SDK is installed when building from Windows? Is that even possible?
# if PLATFORM_MAC
OutDocumentationPath = FString ( " Shared/Tutorials/InstallingXCodeTutorial " ) ;
biOSSDKInstalled = IFileManager : : Get ( ) . DirectoryExists ( TEXT ( " /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform " ) ) ;
2014-07-22 17:53:31 -04:00
# else
{
HKEY hKey ;
LRESULT lRes = RegOpenKeyEx ( HKEY_LOCAL_MACHINE , TEXT ( " SOFTWARE \\ Wow6432Node \\ Apple Inc. \\ Apple Mobile Device Support \\ Shared " ) , 0 , KEY_READ , & hKey ) ;
TCHAR dllPath [ 256 ] ;
unsigned long pathSize = 256 ;
if ( lRes ! = ERROR_SUCCESS | | RegQueryValueEx ( hKey , TEXT ( " iTunesMobileDeviceDLL " ) , 0 , NULL , ( BYTE * ) dllPath , & pathSize ) ! = ERROR_SUCCESS | | IFileManager : : Get ( ) . FileSize ( * FString ( dllPath ) ) = = INDEX_NONE )
{
OutDocumentationPath = FString ( " Shared/Tutorials/InstallingiTunesTutorial " ) ;
biOSSDKInstalled = false ;
}
}
2014-04-02 18:09:23 -04:00
# endif
return biOSSDKInstalled ;
}
2014-08-22 17:36:22 -04:00
static FString OutputMessage ;
static void OnOutput ( FString Message )
{
OutputMessage + = Message ;
UE_LOG ( LogTemp , Display , TEXT ( " %s " ) , * Message ) ;
}
2014-08-01 20:30:13 -04:00
int FIOSTargetPlatform : : DoesntHaveRequirements ( const FString & ProjectPath , bool bProjectHasCode , FString & OutDocumentationPath ) const
2014-07-22 17:53:31 -04:00
{
int bReadyToBuild = ETargetPlatformReadyStatus : : Ready ; // @todo How do we check that the iOS SDK is installed when building from Windows? Is that even possible?
if ( ! IsSdkInstalled ( bProjectHasCode , OutDocumentationPath ) )
{
bReadyToBuild | = ETargetPlatformReadyStatus : : SDKNotFound ;
}
# if PLATFORM_MAC
OutDocumentationPath = FString ( " Shared/Tutorials/InstallingXCodeTutorial " ) ;
# else
if ( bProjectHasCode & & FRocketSupport : : IsRocket ( ) )
{
OutDocumentationPath = FString ( " Shared/Tutorials/iOSonPCRestrictions " ) ;
bReadyToBuild | = ETargetPlatformReadyStatus : : CodeUnsupported ;
}
if ( FRocketSupport : : IsRocket ( ) & & IProjectManager : : Get ( ) . IsNonDefaultPluginEnabled ( ) )
{
OutDocumentationPath = FString ( " Shared/Tutorials/iOSonPCValidPlugins " ) ;
bReadyToBuild | = ETargetPlatformReadyStatus : : PluginsUnsupported ;
}
// shell to IPP and get the status of the provision and cert
FString CmdExe = FPaths : : ConvertRelativePathToFull ( FPaths : : EngineDir ( ) / TEXT ( " Binaries/DotNet/IOS/IPhonePackager.exe " ) ) ;
2014-08-22 17:36:22 -04:00
FString CommandLine = FString : : Printf ( TEXT ( " Validate Engine -project \" %s \" " ) , * ProjectPath ) ;
2014-07-31 13:31:22 -04:00
TSharedPtr < FMonitoredProcess > IPPProcess = MakeShareable ( new FMonitoredProcess ( CmdExe , CommandLine , true ) ) ;
2014-08-22 17:36:22 -04:00
OutputMessage = TEXT ( " " ) ;
IPPProcess - > OnOutput ( ) . BindStatic ( & OnOutput ) ;
2014-07-22 17:53:31 -04:00
IPPProcess - > Launch ( ) ;
while ( IPPProcess - > IsRunning ( ) )
{
FPlatformProcess : : Sleep ( 0.01f ) ;
}
int RetCode = IPPProcess - > GetReturnCode ( ) ;
if ( RetCode = = 14 )
{
OutDocumentationPath = FString ( " Shared/Tutorials/CreatingInfoPlist " ) ;
bReadyToBuild | = ETargetPlatformReadyStatus : : ManifestNotFound ;
}
else if ( RetCode = = 13 )
{
OutDocumentationPath = FString ( " Shared/Tutorials/CreatingSigningCertAndProvision " ) ;
bReadyToBuild | = ETargetPlatformReadyStatus : : SigningKeyNotFound ;
bReadyToBuild | = ETargetPlatformReadyStatus : : ProvisionNotFound ;
}
else if ( RetCode = = 12 )
{
OutDocumentationPath = FString ( " Shared/Tutorials/CreatingSigningCertAndProvision " ) ;
bReadyToBuild | = ETargetPlatformReadyStatus : : SigningKeyNotFound ;
}
else if ( RetCode = = 11 )
{
OutDocumentationPath = FString ( " Shared/Tutorials/CreatingSigningCertAndProvision " ) ;
bReadyToBuild | = ETargetPlatformReadyStatus : : ProvisionNotFound ;
}
# endif
return bReadyToBuild ;
}
2014-03-14 14:13:41 -04:00
/* FIOSTargetPlatform implementation
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void FIOSTargetPlatform : : PingNetworkDevices ( )
{
if ( ! MessageEndpoint . IsValid ( ) )
{
MessageEndpoint = FMessageEndpoint : : Builder ( " FIOSTargetPlatform " )
. Handling < FIOSLaunchDaemonPong > ( this , & FIOSTargetPlatform : : HandlePongMessage ) ;
}
if ( MessageEndpoint . IsValid ( ) )
{
MessageEndpoint - > Publish ( new FIOSLaunchDaemonPing ( ) , EMessageScope : : Network ) ;
}
// remove disconnected & timed out devices
FDateTime Now = FDateTime : : UtcNow ( ) ;
for ( auto DeviceIt = Devices . CreateIterator ( ) ; DeviceIt ; + + DeviceIt )
{
FIOSTargetDevicePtr Device = DeviceIt - > Value ;
if ( Now > Device - > LastPinged + FTimespan : : FromSeconds ( 60.0 ) )
{
DeviceIt . RemoveCurrent ( ) ;
DeviceLostEvent . Broadcast ( Device . ToSharedRef ( ) ) ;
}
}
}
/* FIOSTargetPlatform callbacks
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void FIOSTargetPlatform : : HandlePongMessage ( const FIOSLaunchDaemonPong & Message , const IMessageContextRef & Context )
{
FTargetDeviceId DeviceId ;
FTargetDeviceId : : Parse ( Message . DeviceID , DeviceId ) ;
FIOSTargetDevicePtr & Device = Devices . FindOrAdd ( DeviceId ) ;
if ( ! Device . IsValid ( ) )
{
Device = MakeShareable ( new FIOSTargetDevice ( * this ) ) ;
Device - > SetFeature ( ETargetDeviceFeatures : : Reboot , Message . bCanReboot ) ;
Device - > SetFeature ( ETargetDeviceFeatures : : PowerOn , Message . bCanPowerOn ) ;
Device - > SetFeature ( ETargetDeviceFeatures : : PowerOff , Message . bCanPowerOff ) ;
Device - > SetDeviceId ( DeviceId ) ;
Device - > SetDeviceName ( Message . DeviceName ) ;
Device - > SetDeviceType ( Message . DeviceType ) ;
Device - > SetDeviceEndpoint ( Context - > GetSender ( ) ) ;
Device - > SetIsSimulated ( Message . DeviceID . Contains ( TEXT ( " Simulator " ) ) ) ;
DeviceDiscoveredEvent . Broadcast ( Device . ToSharedRef ( ) ) ;
}
Device - > LastPinged = FDateTime : : UtcNow ( ) ;
}
void FIOSTargetPlatform : : HandleDeviceConnected ( const FIOSLaunchDaemonPong & Message )
{
FTargetDeviceId DeviceId ;
FTargetDeviceId : : Parse ( Message . DeviceID , DeviceId ) ;
2014-07-30 15:36:36 -04:00
2014-03-14 14:13:41 -04:00
FIOSTargetDevicePtr & Device = Devices . FindOrAdd ( DeviceId ) ;
2014-07-30 15:36:36 -04:00
2014-03-14 14:13:41 -04:00
if ( ! Device . IsValid ( ) )
{
Device = MakeShareable ( new FIOSTargetDevice ( * this ) ) ;
2014-07-30 15:36:36 -04:00
2014-03-14 14:13:41 -04:00
Device - > SetFeature ( ETargetDeviceFeatures : : Reboot , Message . bCanReboot ) ;
Device - > SetFeature ( ETargetDeviceFeatures : : PowerOn , Message . bCanPowerOn ) ;
Device - > SetFeature ( ETargetDeviceFeatures : : PowerOff , Message . bCanPowerOff ) ;
Device - > SetDeviceId ( DeviceId ) ;
Device - > SetDeviceName ( Message . DeviceName ) ;
Device - > SetDeviceType ( Message . DeviceType ) ;
Device - > SetIsSimulated ( Message . DeviceID . Contains ( TEXT ( " Simulator " ) ) ) ;
2014-07-30 15:36:36 -04:00
2014-03-14 14:13:41 -04:00
DeviceDiscoveredEvent . Broadcast ( Device . ToSharedRef ( ) ) ;
}
2014-07-30 15:36:36 -04:00
2014-03-14 14:13:41 -04:00
// Add a very long time period to prevent the devices from getting disconnected due to a lack of pong messages
Device - > LastPinged = FDateTime : : UtcNow ( ) + FTimespan ( 100 , 0 , 0 , 0 , 0 ) ;
}
void FIOSTargetPlatform : : HandleDeviceDisconnected ( const FIOSLaunchDaemonPong & Message )
{
FTargetDeviceId DeviceId ;
FTargetDeviceId : : Parse ( Message . DeviceID , DeviceId ) ;
2014-07-30 15:36:36 -04:00
2014-03-14 14:13:41 -04:00
FIOSTargetDevicePtr & Device = Devices . FindOrAdd ( DeviceId ) ;
2014-07-30 15:36:36 -04:00
2014-03-14 14:13:41 -04:00
if ( Device . IsValid ( ) )
{
2014-07-30 15:36:36 -04:00
DeviceLostEvent . Broadcast ( Device . ToSharedRef ( ) ) ;
Devices . Remove ( DeviceId ) ;
2014-03-14 14:13:41 -04:00
}
}
bool FIOSTargetPlatform : : HandleTicker ( float DeltaTime )
{
PingNetworkDevices ( ) ;
return true ;
}
/* ITargetPlatform interface
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if WITH_ENGINE
2014-05-09 08:51:44 -04:00
void FIOSTargetPlatform : : GetAllPossibleShaderFormats ( TArray < FName > & OutFormats ) const
2014-03-14 14:13:41 -04:00
{
static FName NAME_OPENGL_ES2_IOS ( TEXT ( " GLSL_ES2_IOS " ) ) ;
2014-06-17 18:27:26 -04:00
static FName NAME_SF_METAL ( TEXT ( " SF_METAL " ) ) ;
2014-06-24 18:38:35 -04:00
2014-07-08 10:53:56 -04:00
// default to supporting ES2
2014-08-26 09:31:26 -04:00
bool bSupportsOpenGLES2 = true ;
GConfig - > GetBool ( TEXT ( " /Script/IOSRuntimeSettings.IOSRuntimeSettings " ) , TEXT ( " bSupportsOpenGLES2 " ) , bSupportsOpenGLES2 , GEngineIni ) ;
if ( bSupportsOpenGLES2 )
2014-07-08 10:53:56 -04:00
{
OutFormats . AddUnique ( NAME_OPENGL_ES2_IOS ) ;
}
// default to NOT supporting metal
2014-08-26 09:31:26 -04:00
bool bSupportsMetal = false ;
GConfig - > GetBool ( TEXT ( " /Script/IOSRuntimeSettings.IOSRuntimeSettings " ) , TEXT ( " bSupportsMetal " ) , bSupportsMetal , GEngineIni ) ;
if ( bSupportsMetal )
2014-06-24 18:38:35 -04:00
{
OutFormats . AddUnique ( NAME_SF_METAL ) ;
}
2014-03-14 14:13:41 -04:00
}
2014-05-09 08:51:44 -04:00
void FIOSTargetPlatform : : GetAllTargetedShaderFormats ( TArray < FName > & OutFormats ) const
{
GetAllPossibleShaderFormats ( OutFormats ) ;
}
2014-03-14 14:13:41 -04:00
void FIOSTargetPlatform : : GetTextureFormats ( const UTexture * Texture , TArray < FName > & OutFormats ) const
{
check ( Texture ) ;
FName TextureFormatName = NAME_None ;
//// Supported texture format names.
// Compressed Texture Formats
static FName NamePVRTC2 ( TEXT ( " PVRTC2 " ) ) ;
static FName NamePVRTC4 ( TEXT ( " PVRTC4 " ) ) ;
// Same as PVRTC4, but derives Z from X and Y
static FName NamePVRTCN ( TEXT ( " PVRTCN " ) ) ;
static FName NameAutoPVRTC ( TEXT ( " AutoPVRTC " ) ) ;
// Uncompressed Texture Formats
static FName NameBGRA8 ( TEXT ( " BGRA8 " ) ) ;
static FName NameG8 ( TEXT ( " G8 " ) ) ;
static FName NameVU8 ( TEXT ( " VU8 " ) ) ;
static FName NameRGBA16F ( TEXT ( " RGBA16F " ) ) ;
bool bIsCubemap = Texture - > IsA ( UTextureCube : : StaticClass ( ) ) ;
bool bNoCompression = Texture - > CompressionNone // Code wants the texture uncompressed.
| | ( Texture - > LODGroup = = TEXTUREGROUP_ColorLookupTable ) // Textures in certain LOD groups should remain uncompressed.
| | ( Texture - > LODGroup = = TEXTUREGROUP_Bokeh )
| | ( Texture - > CompressionSettings = = TC_EditorIcon )
| | ( Texture - > Source . GetSizeX ( ) < 4 ) // Don't compress textures smaller than the DXT block size.
| | ( Texture - > Source . GetSizeY ( ) < 4 )
| | ( Texture - > Source . GetSizeX ( ) % 4 ! = 0 )
| | ( Texture - > Source . GetSizeY ( ) % 4 ! = 0 ) ;
ETextureSourceFormat SourceFormat = Texture - > Source . GetFormat ( ) ;
// Determine the pixel format of the compressed texture.
if ( bNoCompression )
{
if ( Texture - > HasHDRSource ( ) )
{
TextureFormatName = NameRGBA16F ;
}
else if ( SourceFormat = = TSF_G8 | | Texture - > CompressionSettings = = TC_Grayscale )
{
TextureFormatName = NameG8 ;
}
else if ( Texture - > LODGroup = = TEXTUREGROUP_Shadowmap )
{
TextureFormatName = NameG8 ;
}
else
{
TextureFormatName = NameBGRA8 ;
}
}
else if ( Texture - > CompressionSettings = = TC_HDR )
{
TextureFormatName = NameRGBA16F ;
}
else if ( Texture - > CompressionSettings = = TC_Normalmap )
{
TextureFormatName = NamePVRTCN ;
}
else if ( Texture - > CompressionSettings = = TC_Displacementmap )
{
TextureFormatName = NameG8 ;
}
else if ( Texture - > CompressionSettings = = TC_VectorDisplacementmap )
{
TextureFormatName = NameBGRA8 ;
}
else if ( Texture - > CompressionSettings = = TC_Grayscale )
{
TextureFormatName = NameG8 ;
}
else if ( Texture - > CompressionSettings = = TC_Alpha )
{
TextureFormatName = NameG8 ;
}
2014-07-30 15:36:36 -04:00
else if ( Texture - > CompressionSettings = = TC_DistanceFieldFont )
{
TextureFormatName = NameG8 ;
}
2014-03-14 14:13:41 -04:00
else if ( Texture - > bForcePVRTC4 )
{
TextureFormatName = NamePVRTC4 ;
}
else if ( Texture - > CompressionNoAlpha )
{
TextureFormatName = NamePVRTC2 ;
}
else if ( Texture - > bDitherMipMapAlpha )
{
TextureFormatName = NamePVRTC4 ;
}
else
{
TextureFormatName = NameAutoPVRTC ;
}
// Some PC GPUs don't support sRGB read from G8 textures (e.g. AMD DX10 cards on ShaderModel3.0)
// This solution requires 4x more memory but a lot of PC HW emulate the format anyway
if ( ( TextureFormatName = = NameG8 ) & & Texture - > SRGB )
{
TextureFormatName = NameG8 ;
}
OutFormats . Add ( TextureFormatName ) ;
}
const FTextureLODSettings & FIOSTargetPlatform : : GetTextureLODSettings ( ) const
{
return TextureLODSettings ;
}
FName FIOSTargetPlatform : : GetWaveFormat ( class USoundWave * Wave ) const
{
static FName NAME_ADPCM ( TEXT ( " ADPCM " ) ) ;
return NAME_ADPCM ;
}
# endif // WITH_ENGINE