From c6b9772e960c8ef99f989b96544ea28ba682f589 Mon Sep 17 00:00:00 2001 From: Valerio Santinelli Date: Tue, 29 Sep 2015 09:24:11 +0200 Subject: [PATCH] Added the tvos target to the command line tool and started working on the TVOSPlatform and TVOSHelper --- docs/ImportAll.hx | 1 + lime/_backend/native/NativeApplication.hx | 4 +- lime/project/ProjectXMLParser.hx | 53 ++ lime/system/CFFI.hx | 2 +- lime/tools/helpers/TVOSHelper.hx | 328 +++++++++++ lime/tools/platforms/TVOSPlatform.hx | 609 +++++++++++++++++++++ project/src/backend/sdl/SDLApplication.cpp | 4 +- project/src/graphics/opengl/OpenGL.h | 2 +- templates/tvos/PROJ/haxe/makefile | 16 +- tools/CommandLineTools.hx | 2 +- 10 files changed, 999 insertions(+), 22 deletions(-) create mode 100644 lime/tools/helpers/TVOSHelper.hx create mode 100644 lime/tools/platforms/TVOSPlatform.hx diff --git a/docs/ImportAll.hx b/docs/ImportAll.hx index fc6d74c8e..d653a9640 100644 --- a/docs/ImportAll.hx +++ b/docs/ImportAll.hx @@ -178,6 +178,7 @@ import lime.tools.platforms.IOSPlatform; import lime.tools.platforms.LinuxPlatform; import lime.tools.platforms.MacPlatform; import lime.tools.platforms.TizenPlatform; +import lime.tools.platforms.TVOSPlatform; import lime.tools.platforms.WebOSPlatform; import lime.tools.platforms.WindowsPlatform; #end diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx index b0b423af7..271c84868 100644 --- a/lime/_backend/native/NativeApplication.hx +++ b/lime/_backend/native/NativeApplication.hx @@ -60,7 +60,7 @@ class NativeApplication { AudioManager.init (); - #if (ios || android) + #if (ios || android || tvos) Sensor.registerSensor (SensorType.ACCELEROMETER, 0); #end @@ -89,7 +89,7 @@ class NativeApplication { lime_touch_event_manager_register (handleTouchEvent, touchEventInfo); lime_window_event_manager_register (handleWindowEvent, windowEventInfo); - #if (ios || android) + #if (ios || android || tvos) lime_sensor_event_manager_register (handleSensorEvent, sensorEventInfo); #end diff --git a/lime/project/ProjectXMLParser.hx b/lime/project/ProjectXMLParser.hx index 1b0d6cd66..83895c59b 100644 --- a/lime/project/ProjectXMLParser.hx +++ b/lime/project/ProjectXMLParser.hx @@ -1580,6 +1580,59 @@ class ProjectXMLParser extends HXProject { } } + + case "tvos": + + if (target == Platform.TVOS) { + + if (element.has.deployment) { + + var deployment = Std.parseFloat (substitute (element.att.deployment)); + + // If it is specified, assume the dev knows what he is doing! + config.set ("tvos.deployment", deployment); + } + + if (element.has.binaries) { + + var binaries = substitute (element.att.binaries); + + switch (binaries) { + + case "arm64": + + ArrayHelper.addUnique (architectures, Architecture.ARM64); + + } + + } + + if (element.has.devices) { + + config.set ("tvos.device", substitute (element.att.devices).toLowerCase ()); + + } + + if (element.has.compiler) { + + config.set ("tvos.compiler", substitute (element.att.compiler)); + + } + + if (element.has.resolve ("prerendered-icon")) { + + config.set ("tvos.prerenderedIcon", substitute (element.att.resolve ("prerendered-icon"))); + + } + + if (element.has.resolve ("linker-flags")) { + + config.push ("tvos.linker-flags", substitute (element.att.resolve ("linker-flags"))); + //config.ios.linkerFlags.push (substitute (element.att.resolve ("linker-flags"))); + + } + + } case "config": diff --git a/lime/system/CFFI.hx b/lime/system/CFFI.hx index be82e8451..018bbd628 100644 --- a/lime/system/CFFI.hx +++ b/lime/system/CFFI.hx @@ -91,7 +91,7 @@ class CFFI { } else { - #if (iphone || emscripten || android || static_link) + #if (iphone || emscripten || android || static_link || tvos) return cpp.Lib.load (library, method, args); #end diff --git a/lime/tools/helpers/TVOSHelper.hx b/lime/tools/helpers/TVOSHelper.hx new file mode 100644 index 000000000..438aec83c --- /dev/null +++ b/lime/tools/helpers/TVOSHelper.hx @@ -0,0 +1,328 @@ +package lime.tools.helpers; + + +import haxe.io.Path; +import lime.tools.helpers.PathHelper; +import lime.tools.helpers.ProcessHelper; +import lime.project.Haxelib; +import lime.project.HXProject; +import sys.io.Process; +import sys.FileSystem; + + +class TVOSHelper { + + + private static var initialized = false; + + + public static function build (project:HXProject, workingDirectory:String, additionalArguments:Array = null):Void { + + initialize (project); + + var platformName = "iphoneos"; + + if (project.targetFlags.exists ("simulator")) { + + platformName = "iphonesimulator"; + + } + + var configuration = "Release"; + + if (project.debug) { + + configuration = "Debug"; + + } + + var iphoneVersion = project.environment.get ("IPHONE_VER"); + var commands = [ "-configuration", configuration, "PLATFORM_NAME=" + platformName, "SDKROOT=" + platformName + iphoneVersion ]; + + if (project.targetFlags.exists("simulator")) { + + commands.push ("-arch"); + commands.push ("i386"); + + } + + if (additionalArguments != null) { + + commands = commands.concat (additionalArguments); + + } + + ProcessHelper.runCommand (workingDirectory, "xcodebuild", commands); + + } + + + public static function getSDKDirectory (project:HXProject):String { + + initialize (project); + + var platformName = "iPhoneOS"; + + if (project.targetFlags.exists ("simulator")) { + + platformName = "iPhoneSimulator"; + + } + + var process = new Process ("xcode-select", [ "--print-path" ]); + var directory = process.stdout.readLine (); + process.close (); + + if (directory == "" || directory.indexOf ("Run xcode-select") > -1) { + + directory = "/Applications/Xcode.app/Contents/Developer"; + + } + + directory += "/Platforms/" + platformName + ".platform/Developer/SDKs/" + platformName + project.environment.get ("IPHONE_VER") + ".sdk"; + return directory; + + } + + + private static function getIOSVersion (project:HXProject):Void { + + if (!project.environment.exists("IPHONE_VER")) { + if (!project.environment.exists("DEVELOPER_DIR")) { + var proc = new Process("xcode-select", ["--print-path"]); + var developer_dir = proc.stdout.readLine(); + proc.close(); + project.environment.set("DEVELOPER_DIR", developer_dir); + } + var dev_path = project.environment.get("DEVELOPER_DIR") + "/Platforms/iPhoneOS.platform/Developer/SDKs"; + + if (FileSystem.exists (dev_path)) { + var best = ""; + var files = FileSystem.readDirectory (dev_path); + var extract_version = ~/^iPhoneOS(.*).sdk$/; + + for (file in files) { + if (extract_version.match (file)) { + var ver = extract_version.matched (1); + if (ver > best) + best = ver; + } + } + + if (best != "") + project.environment.set ("IPHONE_VER", best); + } + } + + } + + + private static function getOSXVersion ():String { + + var output = ProcessHelper.runProcess ("", "sw_vers", [ "-productVersion" ]); + + return StringTools.trim (output); + + } + + + public static function getProvisioningFile ():String { + + var path = PathHelper.expand ("~/Library/MobileDevice/Provisioning Profiles"); + var files = FileSystem.readDirectory (path); + + for (file in files) { + + if (Path.extension (file) == "mobileprovision") { + + return path + "/" + file; + + } + + } + + return ""; + + } + + + private static function getXcodeVersion ():String { + + var output = ProcessHelper.runProcess ("", "xcodebuild", [ "-version" ]); + var firstLine = output.split ("\n").shift (); + + return StringTools.trim (firstLine.substring ("Xcode".length, firstLine.length)); + + } + + + private static function initialize (project:HXProject):Void { + + if (!initialized) { + + getIOSVersion (project); + + initialized = true; + + } + + } + + + public static function launch (project:HXProject, workingDirectory:String):Void { + + initialize (project); + + var configuration = "Release"; + + if (project.debug) { + + configuration = "Debug"; + + } + + if (project.targetFlags.exists ("simulator")) { + + var applicationPath = ""; + + if (Path.extension (workingDirectory) == "app" || Path.extension (workingDirectory) == "ipa") { + + applicationPath = workingDirectory; + + } else { + + applicationPath = workingDirectory + "/build/" + configuration + "-iphonesimulator/" + project.app.file + ".app"; + + } + + var templatePaths = [ PathHelper.combine (PathHelper.getHaxelib (new Haxelib ("lime")), "templates") ].concat (project.templatePaths); + var launcher = PathHelper.findTemplate (templatePaths, "bin/ios-sim"); + Sys.command ("chmod", [ "+x", launcher ]); + + // device config + var defaultDevice = "iphone-6"; + var devices:Array = ["iphone-4s", "iphone-5", "iphone-5s", "iphone-6-plus", "iphone-6", "ipad-2", "ipad-retina", "ipad-air"]; + var oldDevices:Map = ["iphone" => "iphone-6", "ipad" => "ipad-air"]; + + var deviceFlag:String = null; + var deviceTypeID = null; + + // check if old device flag and convert to current + for (key in oldDevices.keys()) + { + if (project.targetFlags.exists(key)) + { + deviceFlag = oldDevices[key]; + break; + } + } + + // check known device in command line args + if(deviceFlag == null) + { + for( i in 0...devices.length ) + { + if (project.targetFlags.exists(devices[i])) + { + deviceFlag = devices[i]; + break; + } + } + } + + // default to iphone 6 + if(deviceFlag == null) + deviceFlag = defaultDevice; + + // check if device is available + // $ ios-sim showdevicetypes + var devicesOutput:String = ProcessHelper.runProcess ("", launcher, [ "showdevicetypes" ] ); + var deviceTypeList:Array = devicesOutput.split("\n"); + + for ( i in 0...deviceTypeList.length ) + { + var r:EReg = new EReg(deviceFlag+",", "i"); + if(r.match(deviceTypeList[i])) + { + deviceTypeID = deviceTypeList[i]; + break; + } + } + + if(deviceTypeID == null) + LogHelper.warn("Device \""+deviceFlag+"\" was not found"); + else + LogHelper.info("Launch app on \""+deviceTypeID+"\""); + + + // run command with --devicetypeid if exists + if(deviceTypeID != null) + ProcessHelper.runCommand ("", launcher, [ "launch", FileSystem.fullPath (applicationPath), /*"--sdk", project.environment.get ("IPHONE_VER"),*/ "--devicetypeid", deviceTypeID, "--timeout", "60" ] ); + else + ProcessHelper.runCommand ("", launcher, [ "launch", FileSystem.fullPath (applicationPath), /*"--sdk", project.environment.get ("IPHONE_VER"), "--devicetypeid", deviceTypeID,*/ "--timeout", "60" ] ); + + } else { + + var applicationPath = ""; + + if (Path.extension (workingDirectory) == "app" || Path.extension (workingDirectory) == "ipa") { + + applicationPath = workingDirectory; + + } else { + + applicationPath = workingDirectory + "/build/" + configuration + "-iphoneos/" + project.app.file + ".app"; + + } + + var templatePaths = [ PathHelper.combine (PathHelper.getHaxelib (new Haxelib ("lime")), "templates") ].concat (project.templatePaths); + var launcher = PathHelper.findTemplate (templatePaths, "bin/ios-deploy"); + Sys.command ("chmod", [ "+x", launcher ]); + + var xcodeVersion = getXcodeVersion (); + + ProcessHelper.runCommand ("", launcher, [ "install", "--noninteractive", "--debug", "--timeout", "5", "--bundle", FileSystem.fullPath (applicationPath) ]); + + } + + } + + + public static function sign (project:HXProject, workingDirectory:String, entitlementsPath:String):Void { + + initialize (project); + + var configuration = "Release"; + + if (project.debug) { + + configuration = "Debug"; + + } + + var identity = "iPhone Developer"; + + if (project.certificate != null && project.certificate.identity != null) { + + identity = project.certificate.identity; + + } + + var commands = [ "-s", identity ]; + + if (entitlementsPath != null) { + + commands.push ("--entitlements"); + commands.push (entitlementsPath); + + } + + var applicationPath = "build/" + configuration + "-iphoneos/" + project.app.file + ".app"; + commands.push (applicationPath); + + ProcessHelper.runCommand (workingDirectory, "codesign", commands, true, true); + + } + + +} diff --git a/lime/tools/platforms/TVOSPlatform.hx b/lime/tools/platforms/TVOSPlatform.hx new file mode 100644 index 000000000..a69c58830 --- /dev/null +++ b/lime/tools/platforms/TVOSPlatform.hx @@ -0,0 +1,609 @@ +package lime.tools.platforms; + + +//import openfl.display.BitmapData; +import haxe.io.Path; +import haxe.Json; +import haxe.Template; +import lime.tools.helpers.ArrayHelper; +import lime.tools.helpers.AssetHelper; +import lime.tools.helpers.CPPHelper; +import lime.tools.helpers.DeploymentHelper; +import lime.tools.helpers.FileHelper; +import lime.tools.helpers.IconHelper; +import lime.tools.helpers.TVOSHelper; +import lime.tools.helpers.LogHelper; +import lime.tools.helpers.PathHelper; +import lime.tools.helpers.PlatformHelper; +import lime.tools.helpers.ProcessHelper; +import lime.tools.helpers.StringHelper; +import lime.graphics.Image; +import lime.project.Architecture; +import lime.project.Asset; +import lime.project.AssetType; +import lime.project.Haxelib; +import lime.project.HXProject; +import lime.project.Icon; +import lime.project.Keystore; +import lime.project.NDLL; +import lime.project.Platform; +import lime.project.PlatformTarget; +import sys.io.File; +import sys.FileSystem; + + +class TVOSPlatform extends PlatformTarget { + + + public function new (command:String, _project:HXProject, targetFlags:Map ) { + + super (command, _project, targetFlags); + + targetDirectory = PathHelper.combine (project.app.path, "tvos"); + + } + + + public override function build ():Void { + + if (project.targetFlags.exists ("xcode") && PlatformHelper.hostPlatform == Platform.MAC) { + + ProcessHelper.runCommand ("", "open", [ targetDirectory + "/" + project.app.file + ".xcodeproj" ] ); + + } else { + + TVOSHelper.build (project, targetDirectory); + + if (!project.targetFlags.exists ("simulator")) { + + var entitlements = targetDirectory + "/" + project.app.file + "/" + project.app.file + "-Entitlements.plist"; + TVOSHelper.sign (project, targetDirectory + "/bin", entitlements); + + } + + } + + } + + + public override function clean ():Void { + + if (FileSystem.exists (targetDirectory)) { + + PathHelper.removeDirectory (targetDirectory); + + } + + } + + + public override function deploy ():Void { + + DeploymentHelper.deploy (project, targetFlags, targetDirectory, "tvOS"); + + } + + + public override function display ():Void { + + var hxml = PathHelper.findTemplate (project.templatePaths, "tvos/PROJ/haxe/Build.hxml"); + var template = new Template (File.getContent (hxml)); + + Sys.println (template.execute (generateContext ())); + Sys.println ("-D display"); + + } + + + private function generateContext ():Dynamic { + + project = project.clone (); + + project.sources.unshift (""); + project.sources = PathHelper.relocatePaths (project.sources, PathHelper.combine (targetDirectory, project.app.file + "/haxe")); + //project.dependencies.push ("stdc++"); + + if (project.certificate == null || project.certificate.identity == null) { + + project.certificate = new Keystore (); + project.certificate.identity = "tvOS Developer"; + + } + + if (project.targetFlags.exists ("xml")) { + + project.haxeflags.push ("-xml " + targetDirectory + "/types.xml"); + + } + + if (project.targetFlags.exists ("final")) { + + project.haxedefs.set ("final", ""); + + } + + var context = project.templateContext; + + context.HAS_ICON = false; + context.HAS_LAUNCH_IMAGE = false; + context.OBJC_ARC = false; + + context.linkedLibraries = []; + + for (dependency in project.dependencies) { + + if (!StringTools.endsWith (dependency.name, ".framework") && !StringTools.endsWith (dependency.path, ".framework")) { + + if (dependency.path != "") { + + var name = Path.withoutDirectory (Path.withoutExtension (dependency.path)); + + project.config.push ("tvos.linker-flags", "-force_load $SRCROOT/$PRODUCT_NAME/lib/$CURRENT_ARCH/" + Path.withoutDirectory (dependency.path)); + + if (StringTools.startsWith (name, "lib")) { + + name = name.substring (3, name.length); + + } + + context.linkedLibraries.push (name); + + } else if (dependency.name != "") { + + context.linkedLibraries.push (dependency.name); + + } + + } + + } + + var valid_archs = new Array (); + var arm64 = false; + var architectures = project.architectures; + + if (architectures == null || architectures.length == 0) { + + architectures = [ Architecture.ARM64 ]; + + } + + /*if (project.config.getString ("ios.device", "universal") == "universal" || project.config.getString ("ios.device") == "iphone") { + + if (project.config.getFloat ("ios.deployment", 5.1) < 5) { + + ArrayHelper.addUnique (architectures, Architecture.ARMV6); + + } + + }*/ + + for (architecture in project.architectures) { + + switch (architecture) { + + case ARM64: valid_archs.push ("arm64"); arm64 = true; + default: + + } + + } + + context.CURRENT_ARCHS = "( " + valid_archs.join(",") + ") "; + + valid_archs.push ("i386"); + + context.VALID_ARCHS = valid_archs.join(" "); + context.THUMB_SUPPORT = ""; + + var requiredCapabilities = []; + + requiredCapabilities.push( { name: "armv64", value: true } ); + + context.REQUIRED_CAPABILITY = requiredCapabilities; + context.ARM64 = arm64; + context.TARGET_DEVICES = switch (project.config.getString ("ios.device", "universal")) { case "iphone": "1"; case "ipad": "2"; default: "1,2"; } + context.DEPLOYMENT = project.config.getString ("ios.deployment", "5.1.1"); + + if (project.config.getString ("tvos.compiler") == "llvm" || project.config.getString ("tvos.compiler", "clang") == "clang") { + + context.OBJC_ARC = true; + + } + + context.ENABLE_BITCODE = project.config.getBool ("tvos.enable-bitcode", false); + context.IOS_COMPILER = project.config.getString ("tvos.compiler", "clang"); + context.CPP_BUILD_LIBRARY = project.config.getString ("cpp.buildLibrary", "hxcpp"); + + var json = Json.parse (File.getContent (PathHelper.getHaxelib (new Haxelib ("hxcpp"), true) + "/haxelib.json")); + + if (Std.parseFloat (json.version) > 3.1) { + + context.CPP_LIBPREFIX = "lib"; + + } else { + + context.CPP_LIBPREFIX = ""; + + } + + context.IOS_LINKER_FLAGS = ["-stdlib=libc++"].concat (project.config.getArrayString ("tvos.linker-flags")); + + switch (project.window.orientation) { + + case PORTRAIT: + context.IOS_APP_ORIENTATION = "UIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown"; + case LANDSCAPE: + context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRight"; + case ALL: + context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown"; + //case "allButUpsideDown": + //context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortrait"; + default: + context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown"; + + } + + context.ADDL_PBX_BUILD_FILE = ""; + context.ADDL_PBX_FILE_REFERENCE = ""; + context.ADDL_PBX_FRAMEWORKS_BUILD_PHASE = ""; + context.ADDL_PBX_FRAMEWORK_GROUP = ""; + + context.frameworkSearchPaths = []; + + for (dependency in project.dependencies) { + + var name = null; + var path = null; + + if (Path.extension (dependency.name) == "framework") { + + name = dependency.name; + path = "/System/Library/Frameworks/" + dependency.name; + + } else if (Path.extension (dependency.path) == "framework") { + + name = Path.withoutDirectory (dependency.path); + path = PathHelper.tryFullPath (dependency.path); + + } + + if (name != null) { + + var frameworkID = "11C0000000000018" + StringHelper.getUniqueID (); + var fileID = "11C0000000000018" + StringHelper.getUniqueID (); + + ArrayHelper.addUnique (context.frameworkSearchPaths, Path.directory (path)); + + context.ADDL_PBX_BUILD_FILE += " " + frameworkID + " /* " + name + " in Frameworks */ = {isa = PBXBuildFile; fileRef = " + fileID + " /* " + name + " */; };\n"; + context.ADDL_PBX_FILE_REFERENCE += " " + fileID + " /* " + name + " */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = \"" + name + "\"; path = \"" + path + "\"; sourceTree = SDKROOT; };\n"; + context.ADDL_PBX_FRAMEWORKS_BUILD_PHASE += " " + frameworkID + " /* " + name + " in Frameworks */,\n"; + context.ADDL_PBX_FRAMEWORK_GROUP += " " + fileID + " /* " + name + " */,\n"; + + } + + } + + context.HXML_PATH = PathHelper.findTemplate (project.templatePaths, "tvos/PROJ/haxe/Build.hxml"); + context.PRERENDERED_ICON = project.config.getBool ("tvos.prerenderedIcon", false); + + /*var assets = new Array (); + + for (asset in project.assets) { + + var newAsset = asset.clone (); + + assets.push (); + + }*/ + + //updateIcon (); + //updateLaunchImage (); + + return context; + + } + + + public override function rebuild ():Void { + + var arm64 = (command == "rebuild" || (project.architectures.indexOf (Architecture.ARM64) > -1 && !project.targetFlags.exists ("simulator"))); + var i386 = (command == "rebuild" || project.targetFlags.exists ("simulator")); + var x86_64 = (command == "rebuild" || project.targetFlags.exists ("simulator")); + + var commands = []; + + if (arm64) commands.push ([ "-Dtvos", "-Dios", "-DHXCPP_CPP11", "-DHXCPP_ARM64" ]); + if (i386) commands.push ([ "-Dtvos", "-Dios", "-Dsimulator", "-DHXCPP_CPP11" ]); + if (x86_64) commands.push ([ "-Dtvos", "-Dios", "-Dsimulator", "-DHXCPP_M64", "-DHXCPP_CPP11" ]); + + CPPHelper.rebuild (project, commands); + + } + + + public override function run ():Void { + + if (project.targetFlags.exists ("xcode")) return; + + TVOSHelper.launch (project, targetDirectory); + + } + + + public override function update ():Void { + + project = project.clone (); + + var manifest = new Asset (); + manifest.id = "__manifest__"; + manifest.data = AssetHelper.createManifest (project); + manifest.resourceName = manifest.flatName = manifest.targetPath = "manifest"; + manifest.type = AssetType.TEXT; + project.assets.push (manifest); + + var context = generateContext (); + + var projectDirectory = targetDirectory + "/" + project.app.file + "/"; + + PathHelper.mkdir (targetDirectory); + PathHelper.mkdir (projectDirectory); + PathHelper.mkdir (projectDirectory + "/haxe"); + PathHelper.mkdir (projectDirectory + "/haxe/lime/installer"); + + var iconSizes:Array = [ + { name : "Icon-Small.png", size : 29 }, + { name : "Icon-Small-40.png", size : 40 }, + { name : "Icon-Small-50.png", size : 50 }, + { name : "Icon.png", size : 57 }, + { name : "Icon-Small@2x.png", size : 58 }, + { name : "Icon-72.png", size : 72 }, + { name : "Icon-76.png", size : 76 }, + { name : "Icon-Small-40@2x.png", size : 80 }, + { name : "Icon-Small-50@2x.png", size : 100 }, + { name : "Icon@2x.png", size : 114 }, + { name : "Icon-60@2x.png", size : 120 }, + { name : "Icon-72@2x.png", size : 144 }, + { name : "Icon-76@2x.png", size : 152 }, + { name : "Icon-60@3x.png", size : 180 }, + ]; + + context.HAS_ICON = true; + + var iconPath = PathHelper.combine (projectDirectory, "Images.xcassets/AppIcon.appiconset"); + PathHelper.mkdir (iconPath); + + var icons = project.icons; + + if (icons.length == 0) { + + icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ]; + + } + + for (iconSize in iconSizes) { + + if (!IconHelper.createIcon (icons, iconSize.size, iconSize.size, PathHelper.combine (iconPath, iconSize.name))) { + + context.HAS_ICON = false; + + } + + } + + var splashSizes:Array = [ + { name: "Default.png", w: 320, h: 480 }, // iPhone, portrait + { name: "Default@2x.png", w: 640, h: 960 }, // iPhone Retina, portrait + { name: "Default-568h@2x.png", w: 640, h: 1136 }, // iPhone 5, portrait + { name: "Default-Portrait.png", w: 768, h: 1024 }, // iPad, portrait + { name: "Default-Landscape.png", w: 1024, h: 768 }, // iPad, landscape + { name: "Default-Portrait@2x.png", w: 1536, h: 2048 }, // iPad Retina, portrait + { name: "Default-Landscape@2x.png", w: 2048, h: 1536 }, // iPad Retina, landscape + { name: "Default-667h@2x.png", w: 750, h: 1334 }, // iPhone 6, portrait + { name: "Default-736h@3x.png", w: 1242, h: 2208 }, // iPhone 6 Plus, portrait + { name: "Default-736h-Landscape@3x.png", w: 2208, h: 1242 }, // iPhone 6 Plus, landscape + ]; + + var splashScreenPath = PathHelper.combine (projectDirectory, "Images.xcassets/LaunchImage.launchimage"); + PathHelper.mkdir (splashScreenPath); + + for (size in splashSizes) { + + var match = false; + + for (splashScreen in project.splashScreens) { + + if (splashScreen.width == size.w && splashScreen.height == size.h && Path.extension (splashScreen.path) == "png") { + + FileHelper.copyFile (splashScreen.path, PathHelper.combine (splashScreenPath, size.name)); + match = true; + + } + + } + + if (!match) { + + var imagePath = PathHelper.combine (splashScreenPath, size.name); + + if (!FileSystem.exists (imagePath)) { + + LogHelper.info ("", " - \x1b[1mGenerating image:\x1b[0m " + imagePath); + + var image = new Image (null, 0, 0, size.w, size.h, (0xFF << 24) | (project.window.background & 0xFFFFFF)); + var bytes = image.encode ("png"); + + File.saveBytes (imagePath, bytes); + + } + + } + + } + + context.HAS_LAUNCH_IMAGE = true; + + PathHelper.mkdir (projectDirectory + "/resources"); + PathHelper.mkdir (projectDirectory + "/haxe/build"); + + FileHelper.recursiveCopyTemplate (project.templatePaths, "tvos/resources", projectDirectory + "/resources", context, true, false); + FileHelper.recursiveCopyTemplate (project.templatePaths, "tvos/PROJ/haxe", projectDirectory + "/haxe", context); + FileHelper.recursiveCopyTemplate (project.templatePaths, "haxe", projectDirectory + "/haxe", context); + FileHelper.recursiveCopyTemplate (project.templatePaths, "tvos/PROJ/Classes", projectDirectory + "/Classes", context); + FileHelper.recursiveCopyTemplate (project.templatePaths, "tvos/PROJ/Images.xcassets", projectDirectory + "/Images.xcassets", context); + FileHelper.copyFileTemplate (project.templatePaths, "tvos/PROJ/PROJ-Entitlements.plist", projectDirectory + "/" + project.app.file + "-Entitlements.plist", context); + FileHelper.copyFileTemplate (project.templatePaths, "tvos/PROJ/PROJ-Info.plist", projectDirectory + "/" + project.app.file + "-Info.plist", context); + FileHelper.copyFileTemplate (project.templatePaths, "tvos/PROJ/PROJ-Prefix.pch", projectDirectory + "/" + project.app.file + "-Prefix.pch", context); + FileHelper.recursiveCopyTemplate (project.templatePaths, "tvos/PROJ.xcodeproj", targetDirectory + "/" + project.app.file + ".xcodeproj", context); + + //SWFHelper.generateSWFClasses (project, projectDirectory + "/haxe"); + + PathHelper.mkdir (projectDirectory + "/lib"); + + for (archID in 0...3) { + + var arch = [ "arm64", "i386", "x86_64" ][archID]; + + if (arch == "arm64" && !context.ARM64) + continue; + + var libExt = [ ".tvos-64.a", ".tvossim.a", ".tvossim-64.a" ][archID]; + + PathHelper.mkdir (projectDirectory + "/lib/" + arch); + PathHelper.mkdir (projectDirectory + "/lib/" + arch + "-debug"); + + for (ndll in project.ndlls) { + + //if (ndll.haxelib != null) { + + var releaseLib = PathHelper.getLibraryPath (ndll, "tvOS", "lib", libExt); + LogHelper.info("releaseLib: " + releaseLib); + var debugLib = PathHelper.getLibraryPath (ndll, "tvOS", "lib", libExt, true); + var releaseDest = projectDirectory + "/lib/" + arch + "/lib" + ndll.name + ".a"; + LogHelper.info("releaseDest: " + releaseDest); + var debugDest = projectDirectory + "/lib/" + arch + "-debug/lib" + ndll.name + ".a"; + + if (!FileSystem.exists (releaseLib)) { + + releaseLib = PathHelper.getLibraryPath (ndll, "iPhone", "lib", ".iphoneos.a"); + LogHelper.info("alternative releaseLib: " + releaseLib); + debugLib = PathHelper.getLibraryPath (ndll, "iPhone", "lib", ".iphoneos.a", true); + + } + + FileHelper.copyIfNewer (releaseLib, releaseDest); + + if (FileSystem.exists (debugLib) && debugLib != releaseLib) { + + FileHelper.copyIfNewer (debugLib, debugDest); + + } else if (FileSystem.exists (debugDest)) { + + FileSystem.deleteFile (debugDest); + + } + + //} + + } + + for (dependency in project.dependencies) { + + if (StringTools.endsWith (dependency.path, ".a")) { + + var fileName = Path.withoutDirectory (dependency.path); + + if (!StringTools.startsWith (fileName, "lib")) { + + fileName = "lib" + fileName; + + } + + FileHelper.copyIfNewer (dependency.path, projectDirectory + "/lib/" + arch + "/" + fileName); + + } + + } + + } + + PathHelper.mkdir (projectDirectory + "/assets"); + + for (asset in project.assets) { + + if (asset.type != AssetType.TEMPLATE) { + + var targetPath = PathHelper.combine (projectDirectory + "/assets/", asset.resourceName); + + //var sourceAssetPath:String = projectDirectory + "haxe/" + asset.sourcePath; + + PathHelper.mkdir (Path.directory (targetPath)); + FileHelper.copyAssetIfNewer (asset, targetPath); + + //PathHelper.mkdir (Path.directory (sourceAssetPath)); + //FileHelper.linkFile (flatAssetPath, sourceAssetPath, true, true); + + } else { + + var targetPath = PathHelper.combine (projectDirectory, asset.targetPath); + + PathHelper.mkdir (Path.directory (targetPath)); + FileHelper.copyAsset (asset, targetPath, context); + + } + + } + + if (project.targetFlags.exists ("xcode") && PlatformHelper.hostPlatform == Platform.MAC && command == "update") { + + ProcessHelper.runCommand ("", "open", [ targetDirectory + "/" + project.app.file + ".xcodeproj" ] ); + + } + + } + + + /*private function updateLaunchImage () { + + var destination = buildDirectory + "/ios"; + PathHelper.mkdir (destination); + + var has_launch_image = false; + if (launchImages.length > 0) has_launch_image = true; + + for (launchImage in launchImages) { + + var splitPath = launchImage.name.split ("/"); + var path = destination + "/" + splitPath[splitPath.length - 1]; + FileHelper.copyFile (launchImage.name, path, context, false); + + } + + context.HAS_LAUNCH_IMAGE = has_launch_image; + + }*/ + + + @ignore public override function install ():Void {} + @ignore public override function trace ():Void {} + @ignore public override function uninstall ():Void {} + + +} + + +private typedef IconSize = { + + name:String, + size:Int, + +} + + +private typedef SplashSize = { + + name:String, + w:Int, + h:Int, + +} diff --git a/project/src/backend/sdl/SDLApplication.cpp b/project/src/backend/sdl/SDLApplication.cpp index d00e14e16..3e3a89a60 100644 --- a/project/src/backend/sdl/SDLApplication.cpp +++ b/project/src/backend/sdl/SDLApplication.cpp @@ -54,7 +54,7 @@ namespace lime { TouchEvent touchEvent; WindowEvent windowEvent; - #if defined(IOS) || defined(ANDROID) + #if defined(IOS) || defined(ANDROID) || defined(TVOS) for (int i = 0; i < SDL_NumJoysticks (); i++) { if (strstr (SDL_JoystickNameForIndex (i), "Accelerometer")) { @@ -166,7 +166,7 @@ namespace lime { case SDL_JOYAXISMOTION: - #if defined(IOS) || defined(ANDROID) + #if defined(IOS) || defined(ANDROID) || defined(TVOS) if (event->jaxis.which == accelerometerID) { ProcessSensorEvent (event); diff --git a/project/src/graphics/opengl/OpenGL.h b/project/src/graphics/opengl/OpenGL.h index 935855b2f..501d44dc7 100644 --- a/project/src/graphics/opengl/OpenGL.h +++ b/project/src/graphics/opengl/OpenGL.h @@ -14,7 +14,7 @@ #include #include -#elif defined (IPHONE) +#elif defined (IPHONE) || defined(TVOS) #define LIME_GLES #include diff --git a/templates/tvos/PROJ/haxe/makefile b/templates/tvos/PROJ/haxe/makefile index bbc3bf29a..f217e2e35 100644 --- a/templates/tvos/PROJ/haxe/makefile +++ b/templates/tvos/PROJ/haxe/makefile @@ -1,6 +1,6 @@ ifeq ("$(ARCHS)","normal") - ARCHS = armv6 armv7 i386 + ARCHS = armv64 i386 endif HAXE_BUILDS := $(ARCHS:%=build-haxe-%) @@ -59,20 +59,6 @@ build-haxe-x86_64: cp build/$(CONFIG)-64/::CPP_LIBPREFIX::ApplicationMain$(DEBUG).iphonesim-64.a ../lib/x86_64$(LIB_DEST) touch ../Classes/Main.mm -build-haxe-armv6: - @echo "Haxe device build: $(CONFIG)" - haxe Build.hxml -D HXCPP_ARMV6 -cpp build/$(CONFIG) $(DEBUG) - cd build/$(CONFIG); export HXCPP_NO_COLOR=1; haxelib run ::CPP_BUILD_LIBRARY:: Build.xml -Dtvos -DHXCPP_ARMV6 -DHXCPP_CPP11 $(DEF_DEBUG) $(HXCPP_CLANG) `cat Options.txt | while read LINE; do printf " -D$$LINE"; done` - cp build/$(CONFIG)/::CPP_LIBPREFIX::ApplicationMain$(DEBUG).iphoneos.a ../lib/armv6$(LIB_DEST) - touch ../Classes/Main.mm - -build-haxe-armv7: - @echo "Haxe device build: $(CONFIG)-v7" - haxe Build.hxml -D HXCPP_ARMV7 -cpp build/$(CONFIG)-v7 $(DEBUG) - cd build/$(CONFIG)-v7; export HXCPP_NO_COLOR=1; haxelib run ::CPP_BUILD_LIBRARY:: Build.xml -Dtvos -DHXCPP_ARMV7 -DHXCPP_CPP11 $(DEF_DEBUG) $(HXCPP_CLANG) `cat Options.txt | while read LINE; do printf " -D$$LINE"; done` - cp build/$(CONFIG)-v7/::CPP_LIBPREFIX::ApplicationMain$(DEBUG).iphoneos-v7.a ../lib/armv7$(LIB_DEST) - touch ../Classes/Main.mm - build-haxe-arm64: @echo "Haxe device build: $(CONFIG)-64" haxe Build.hxml -D HXCPP_ARM64 -cpp build/$(CONFIG)-64 $(DEBUG) diff --git a/tools/CommandLineTools.hx b/tools/CommandLineTools.hx index 6bff1468d..23f138653 100644 --- a/tools/CommandLineTools.hx +++ b/tools/CommandLineTools.hx @@ -584,7 +584,7 @@ class CommandLineTools { case TVOS: - platform = new IOSPlatform (command, project, targetFlags); + platform = new TVOSPlatform (command, project, targetFlags); default: