Godot-proposals: Implement Apple TV support

Created on 11 Nov 2019  路  7Comments  路  Source: godotengine/godot-proposals

Describe the project you are working on:
A game for Apple Arcade that requires MacOS, iOS and tvOS support.

Describe the problem or limitation you are having in your project:
Godot does not seem to currently support tvOS.

Describe how this feature / enhancement will help you overcome this problem or limitation:
It will allow games made with Godot to be exported to tvOS and released on Apple Arcade.

Show a mock up screenshots/video or a flow diagram explaining how your proposal will work:
Create Game -> Export for tvOS -> Release -> Great Happiness

Describe implementation detail for your proposal (in code), if possible:
Using the iOS platform as a basis, tvOS support would require a fairly straight forward implementation as the system is (almost) identical to iOS. Support for the AppleTV remote control as an input device would be the biggest problem.

If this enhancement will not be used often, can it be worked around with a few lines of script?:
No.

Is there a reason why this should be core and not an add-on in the asset library?:
This is a core feature for sure.

archived porting

Most helpful comment

I don't think Godot uses SDL2 though. I've done a few tests and AppleTV is indeed the same as iOS in terms of entry point, app delegate and view controllers. So I can only assume that creating the graphics context is identical as well.

Godot do not use SDL, but we can reuse some of SDL code.

tvOS is pretty close to iOS, but simply rebuilding Godot export template with tvOS SDK is not enough, some modification is definitely needed:


diff used for test

diff --git a/methods.py b/methods.py
index 86ab7cd9a..e5c51e701 100644
--- a/methods.py
+++ b/methods.py
@@ -604,6 +604,12 @@ def detect_darwin_sdk_path(platform, env):
     elif platform == 'iphonesimulator':
         sdk_name = 'iphonesimulator'
         var_name = 'IPHONESDK'
+    elif platform == 'appletv':
+        sdk_name = 'appletvos'
+        var_name = 'IPHONESDK'
+    elif platform == 'appletvsimulator':
+        sdk_name = 'appletvsimulator'
+        var_name = 'IPHONESDK'
     else:
         raise Exception("Invalid platform argument passed to detect_darwin_sdk_path")
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index f646b8b1d..47a28f12b 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -27,6 +27,7 @@ def get_opts():
         BoolVariable('store_kit', 'Support for in-app store', True),
         BoolVariable('icloud', 'Support for iCloud', True),
         BoolVariable('ios_exceptions', 'Enable exceptions', False),
+        BoolVariable('target_tvos', 'Target tvOS instead of iOS', False),
         ('ios_triple', 'Triple for ios toolchain', ''),
     ]

@@ -99,19 +100,31 @@ def configure(env):
     env['AR'] = compiler_path + 'ar'
     env['RANLIB'] = compiler_path + 'ranlib'

+    if env["target_tvos"]:
+        env.extra_suffix += '.tvos'
+        ios_sim_name = "appletvsimulator"
+        ios_name = "appletv"
+        ios_sim_ver = "tvos-simulator-version-min=12.0"
+        ios_ver = "tvos-version-min=12.0"
+    else:
+        ios_sim_name = "iphonesimulator"
+        ios_name = "iphone"
+        ios_sim_ver = "ios-simulator-version-min=10.0"
+        ios_ver = "iphoneos-version-min=10.0"
+
     ## Compile flags

     if (env["arch"] == "x86" or env["arch"] == "x86_64"):
-        detect_darwin_sdk_path('iphonesimulator', env)
+        detect_darwin_sdk_path(ios_sim_name, env)
         env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
         arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
-        env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=10.0').split())
+        env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -m' + ios_sim_ver).split())
     elif (env["arch"] == "arm"):
-        detect_darwin_sdk_path('iphone', env)
-        env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=10.0 -MMD -MT dependencies'.split())
+        detect_darwin_sdk_path(ios_name, env)
+        env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -m' + ios_ver + ' -MMD -MT dependencies'.split())
     elif (env["arch"] == "arm64"):
-        detect_darwin_sdk_path('iphone', env)
-        env.Append(CCFLAGS='-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -miphoneos-version-min=10.0 -isysroot $IPHONESDK'.split())
+        detect_darwin_sdk_path(ios_name, env)
+        env.Append(CCFLAGS='-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -m' + ios_ver + ' -isysroot $IPHONESDK'.split())
         env.Append(CPPDEFINES=['NEED_LONG_INT'])
         env.Append(CPPDEFINES=['LIBYUV_DISABLE_NEON'])

@@ -126,7 +139,7 @@ def configure(env):

     if (env["arch"] == "x86" or env["arch"] == "x86_64"):
         arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
-        env.Append(LINKFLAGS=['-arch', arch_flag, '-mios-simulator-version-min=10.0',
+        env.Append(LINKFLAGS=['-arch', arch_flag, '-m' + ios_sim_ver,
                               '-isysroot', '$IPHONESDK',
                               '-Xlinker',
                               '-objc_abi_version',
@@ -134,9 +147,9 @@ def configure(env):
                               '-F$IPHONESDK',
                               ])
     elif (env["arch"] == "arm"):
-        env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=10.0'])
+        env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-m' + ios_ver])
     if (env["arch"] == "arm64"):
-        env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=10.0'])
+        env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-m' + ios_ver])

     env.Append(LINKFLAGS=['-isysroot', '$IPHONESDK',
                           '-framework', 'AudioToolbox',
@@ -174,7 +187,13 @@ def configure(env):
                          '$IPHONESDK/System/Library/Frameworks/AudioUnit.framework/Headers',
                          ])

-    env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'
+    if env["target_tvos"]:
+        env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/AppleTVOS.platform/Developer/usr/bin/codesign_allocate'
+    else:
+        env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'

     env.Prepend(CPPPATH=['#platform/iphone'])
     env.Append(CPPDEFINES=['IPHONE_ENABLED', 'UNIX_ENABLED', 'GLES_ENABLED', 'COREAUDIO_ENABLED'])

Camera API/ARKit, multitouch, screen rotation and some other stuff are incompatible.

Godot uses the SDL game controller database

Godot uses ancient version of SDK controller db, all 2.0.4+ SDL stuff is currently unusable (see https://github.com/godotengine/godot/issues/8368),

All 7 comments

Support for the AppleTV remote control as an input device would be the biggest problem.

SDL2 seems to already have some level of support for the Apple TV, this shouldn't be a problem.

I don't think Godot uses SDL2 though. I've done a few tests and AppleTV is indeed the same as iOS in terms of entry point, app delegate and view controllers. So I can only assume that creating the graphics context is identical as well.

Godot uses the SDL game controller database for controller information, there are two entries called "Remote" under iOS, so this may be the Apple TV remote.

I don't think Godot uses SDL2 though. I've done a few tests and AppleTV is indeed the same as iOS in terms of entry point, app delegate and view controllers. So I can only assume that creating the graphics context is identical as well.

Godot do not use SDL, but we can reuse some of SDL code.

tvOS is pretty close to iOS, but simply rebuilding Godot export template with tvOS SDK is not enough, some modification is definitely needed:


diff used for test

diff --git a/methods.py b/methods.py
index 86ab7cd9a..e5c51e701 100644
--- a/methods.py
+++ b/methods.py
@@ -604,6 +604,12 @@ def detect_darwin_sdk_path(platform, env):
     elif platform == 'iphonesimulator':
         sdk_name = 'iphonesimulator'
         var_name = 'IPHONESDK'
+    elif platform == 'appletv':
+        sdk_name = 'appletvos'
+        var_name = 'IPHONESDK'
+    elif platform == 'appletvsimulator':
+        sdk_name = 'appletvsimulator'
+        var_name = 'IPHONESDK'
     else:
         raise Exception("Invalid platform argument passed to detect_darwin_sdk_path")
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index f646b8b1d..47a28f12b 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -27,6 +27,7 @@ def get_opts():
         BoolVariable('store_kit', 'Support for in-app store', True),
         BoolVariable('icloud', 'Support for iCloud', True),
         BoolVariable('ios_exceptions', 'Enable exceptions', False),
+        BoolVariable('target_tvos', 'Target tvOS instead of iOS', False),
         ('ios_triple', 'Triple for ios toolchain', ''),
     ]

@@ -99,19 +100,31 @@ def configure(env):
     env['AR'] = compiler_path + 'ar'
     env['RANLIB'] = compiler_path + 'ranlib'

+    if env["target_tvos"]:
+        env.extra_suffix += '.tvos'
+        ios_sim_name = "appletvsimulator"
+        ios_name = "appletv"
+        ios_sim_ver = "tvos-simulator-version-min=12.0"
+        ios_ver = "tvos-version-min=12.0"
+    else:
+        ios_sim_name = "iphonesimulator"
+        ios_name = "iphone"
+        ios_sim_ver = "ios-simulator-version-min=10.0"
+        ios_ver = "iphoneos-version-min=10.0"
+
     ## Compile flags

     if (env["arch"] == "x86" or env["arch"] == "x86_64"):
-        detect_darwin_sdk_path('iphonesimulator', env)
+        detect_darwin_sdk_path(ios_sim_name, env)
         env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
         arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
-        env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=10.0').split())
+        env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -m' + ios_sim_ver).split())
     elif (env["arch"] == "arm"):
-        detect_darwin_sdk_path('iphone', env)
-        env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=10.0 -MMD -MT dependencies'.split())
+        detect_darwin_sdk_path(ios_name, env)
+        env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -m' + ios_ver + ' -MMD -MT dependencies'.split())
     elif (env["arch"] == "arm64"):
-        detect_darwin_sdk_path('iphone', env)
-        env.Append(CCFLAGS='-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -miphoneos-version-min=10.0 -isysroot $IPHONESDK'.split())
+        detect_darwin_sdk_path(ios_name, env)
+        env.Append(CCFLAGS='-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -m' + ios_ver + ' -isysroot $IPHONESDK'.split())
         env.Append(CPPDEFINES=['NEED_LONG_INT'])
         env.Append(CPPDEFINES=['LIBYUV_DISABLE_NEON'])

@@ -126,7 +139,7 @@ def configure(env):

     if (env["arch"] == "x86" or env["arch"] == "x86_64"):
         arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
-        env.Append(LINKFLAGS=['-arch', arch_flag, '-mios-simulator-version-min=10.0',
+        env.Append(LINKFLAGS=['-arch', arch_flag, '-m' + ios_sim_ver,
                               '-isysroot', '$IPHONESDK',
                               '-Xlinker',
                               '-objc_abi_version',
@@ -134,9 +147,9 @@ def configure(env):
                               '-F$IPHONESDK',
                               ])
     elif (env["arch"] == "arm"):
-        env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=10.0'])
+        env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-m' + ios_ver])
     if (env["arch"] == "arm64"):
-        env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=10.0'])
+        env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-m' + ios_ver])

     env.Append(LINKFLAGS=['-isysroot', '$IPHONESDK',
                           '-framework', 'AudioToolbox',
@@ -174,7 +187,13 @@ def configure(env):
                          '$IPHONESDK/System/Library/Frameworks/AudioUnit.framework/Headers',
                          ])

-    env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'
+    if env["target_tvos"]:
+        env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/AppleTVOS.platform/Developer/usr/bin/codesign_allocate'
+    else:
+        env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'

     env.Prepend(CPPPATH=['#platform/iphone'])
     env.Append(CPPDEFINES=['IPHONE_ENABLED', 'UNIX_ENABLED', 'GLES_ENABLED', 'COREAUDIO_ENABLED'])

Camera API/ARKit, multitouch, screen rotation and some other stuff are incompatible.

Godot uses the SDL game controller database

Godot uses ancient version of SDK controller db, all 2.0.4+ SDL stuff is currently unusable (see https://github.com/godotengine/godot/issues/8368),

Is there any plan on supporting Apple TV?

@AlexRixhardson There are currently no official plans to add Apple TV support, but if a contributor does the required work, it may be merged.

Nevermind

Was this page helpful?
0 / 5 - 0 ratings

Related issues

regakakobigman picture regakakobigman  路  3Comments

WilliamTambellini picture WilliamTambellini  路  3Comments

wijat picture wijat  路  3Comments

SpyrexDE picture SpyrexDE  路  3Comments

rainlizard picture rainlizard  路  3Comments