Browse Source

Initial work for porting Urho3D to AppleTV platform.

Yao Wei Tjong 姚伟忠 10 years ago
parent
commit
75b8420a31
37 changed files with 310 additions and 131 deletions
  1. 1 1
      .bash_helpers.sh
  2. 6 5
      .travis.yml
  3. 47 19
      CMake/Modules/UrhoCommon.cmake
  4. 44 0
      CMake/Modules/tvOSBundleInfo.plist.template
  5. 5 3
      CMakeLists.txt
  6. 2 0
      Docs/GettingStarted.dox
  7. 10 10
      Rakefile
  8. 1 1
      Source/CMakeLists.txt
  9. 2 0
      Source/ThirdParty/Civetweb/CMakeLists.txt
  10. 1 1
      Source/ThirdParty/Lua/CMakeLists.txt
  11. 5 0
      Source/ThirdParty/Lua/src/loslib.c
  12. 30 12
      Source/ThirdParty/LuaJIT/CMakeLists.txt
  13. 4 1
      Source/ThirdParty/LuaJIT/src/lj_arch.h
  14. 7 3
      Source/ThirdParty/SDL/CMakeLists.txt
  15. 9 1
      Source/ThirdParty/SDL/src/video/uikit/SDL_uikitappdelegate.m
  16. 1 1
      Source/ThirdParty/SQLite/CMakeLists.txt
  17. 4 3
      Source/Tools/CMakeLists.txt
  18. 1 1
      Source/Tools/Urho3DPlayer/CMakeLists.txt
  19. 20 9
      Source/Urho3D/CMakeLists.txt
  20. 2 2
      Source/Urho3D/Core/Main.h
  21. 25 10
      Source/Urho3D/Core/ProcessUtils.cpp
  22. 6 6
      Source/Urho3D/Engine/Application.cpp
  23. 2 2
      Source/Urho3D/Engine/Application.h
  24. 4 4
      Source/Urho3D/Engine/Engine.cpp
  25. 1 1
      Source/Urho3D/Graphics/Graphics.cpp
  26. 1 1
      Source/Urho3D/Graphics/GraphicsDefs.h
  27. 9 10
      Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp
  28. 2 2
      Source/Urho3D/Graphics/OpenGL/OGLGraphicsImpl.h
  29. 11 3
      Source/Urho3D/IO/FileSystem.cpp
  30. 6 6
      Source/Urho3D/IO/FileWatcher.cpp
  31. 1 1
      Source/Urho3D/IO/FileWatcher.h
  32. 5 5
      Source/Urho3D/IO/Log.cpp
  33. 3 4
      Source/Urho3D/Input/Input.cpp
  34. 2 2
      Source/Urho3D/UI/Cursor.cpp
  35. 1 1
      Source/Urho3D/UI/UI.cpp
  36. 3 0
      cmake_generic.sh
  37. 26 0
      cmake_tvos.sh

+ 1 - 1
.bash_helpers.sh

@@ -103,7 +103,7 @@ post_cmake() {
         # Speed up build for Debug build configuration by building only active arch (currently this is not doable via CMake generator-expression as it only works for individual target instead of global)
         # Speed up build for Debug build configuration by building only active arch (currently this is not doable via CMake generator-expression as it only works for individual target instead of global)
         perl -i -pe 'BEGIN {$/=undef} s/(Debug \*\/ = {[^}]+?)SDKROOT/\1ONLY_ACTIVE_ARCH = YES; SDKROOT/s' "$BUILD"/*.xcodeproj/project.pbxproj
         perl -i -pe 'BEGIN {$/=undef} s/(Debug \*\/ = {[^}]+?)SDKROOT/\1ONLY_ACTIVE_ARCH = YES; SDKROOT/s' "$BUILD"/*.xcodeproj/project.pbxproj
         # Speed up build for Debug build configuration by skipping dSYM file generation
         # Speed up build for Debug build configuration by skipping dSYM file generation
-        if [[ $IOS ]]; then
+        if [[ $IOS ]] || [[ $TVOS ]]; then
             perl -i -pe 'BEGIN {$/=undef} s/(Debug \*\/ = {[^}]+?)SDKROOT/\1DEBUG_INFORMATION_FORMAT = dwarf; SDKROOT/s' "$BUILD"/*.xcodeproj/project.pbxproj
             perl -i -pe 'BEGIN {$/=undef} s/(Debug \*\/ = {[^}]+?)SDKROOT/\1DEBUG_INFORMATION_FORMAT = dwarf; SDKROOT/s' "$BUILD"/*.xcodeproj/project.pbxproj
         fi
         fi
     fi
     fi

+ 6 - 5
.travis.yml

@@ -470,11 +470,12 @@ env:
     - CCACHE_COMPRESS=1
     - CCACHE_COMPRESS=1
     - CCACHE_MAXSIZE=300M
     - CCACHE_MAXSIZE=300M
   matrix:
   matrix:
-    - MAKEFILE=1    URHO3D_LIB_TYPE=STATIC URHO3D_DEPLOYMENT_TARGET=generic
-    - MAKEFILE=1    URHO3D_LIB_TYPE=SHARED URHO3D_DEPLOYMENT_TARGET=generic
-    - XCODE=1       URHO3D_LIB_TYPE=STATIC CMAKE_OSX_DEPLOYMENT_TARGET=10.12 SF_DEFAULT=mac:OSX-64bit-STATIC.tar.gz
-    - XCODE=1       URHO3D_LIB_TYPE=SHARED CMAKE_OSX_DEPLOYMENT_TARGET=10.12
-    - XCODE=1 IOS=1 URHO3D_LIB_TYPE=STATIC IPHONEOS_DEPLOYMENT_TARGET=10.3 sdk=iphonesimulator
+    - MAKEFILE=1     URHO3D_LIB_TYPE=STATIC URHO3D_DEPLOYMENT_TARGET=generic
+    - MAKEFILE=1     URHO3D_LIB_TYPE=SHARED URHO3D_DEPLOYMENT_TARGET=generic
+    - XCODE=1        URHO3D_LIB_TYPE=STATIC CMAKE_OSX_DEPLOYMENT_TARGET=10.12 SF_DEFAULT=mac:OSX-64bit-STATIC.tar.gz
+    - XCODE=1        URHO3D_LIB_TYPE=SHARED CMAKE_OSX_DEPLOYMENT_TARGET=10.12
+    - XCODE=1 TVOS=1 URHO3D_LIB_TYPE=STATIC APPLETVOS_DEPLOYMENT_TARGET=10.2 sdk=appletvsimulator
+    - XCODE=1 IOS=1  URHO3D_LIB_TYPE=STATIC IPHONEOS_DEPLOYMENT_TARGET=10.3 sdk=iphonesimulator
 matrix:
 matrix:
   fast_finish: true
   fast_finish: true
 before_script:
 before_script:

+ 47 - 19
CMake/Modules/UrhoCommon.cmake

@@ -59,7 +59,7 @@ if (IOS)
     # This is a CMake hack in order to make standard CMake check modules that use try_compile() internally work on iOS platform
     # This is a CMake hack in order to make standard CMake check modules that use try_compile() internally work on iOS platform
     # The injected "flags" are not compiler flags, they are actually CMake variables meant for another CMake subprocess that builds the source file being passed in the try_compile() command
     # The injected "flags" are not compiler flags, they are actually CMake variables meant for another CMake subprocess that builds the source file being passed in the try_compile() command
     # CAVEAT: these injected "flags" must always be kept at the end of the string variable, i.e. when adding more compiler flags later on then those new flags must be prepended in front of these flags instead
     # CAVEAT: these injected "flags" must always be kept at the end of the string variable, i.e. when adding more compiler flags later on then those new flags must be prepended in front of these flags instead
-    set (CMAKE_REQUIRED_FLAGS ";-DSmileyHack=byYaoWT;-DCMAKE_MACOSX_BUNDLE=1;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=0")
+    set (CMAKE_REQUIRED_FLAGS ";-DSmileyHack=byYaoWT;-DCMAKE_MACOSX_BUNDLE=1;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=0;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=")
     if (NOT IOS_SYSROOT)
     if (NOT IOS_SYSROOT)
         execute_process (COMMAND xcodebuild -version -sdk ${CMAKE_OSX_SYSROOT} Path OUTPUT_VARIABLE IOS_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)   # Obtain iOS sysroot path
         execute_process (COMMAND xcodebuild -version -sdk ${CMAKE_OSX_SYSROOT} Path OUTPUT_VARIABLE IOS_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)   # Obtain iOS sysroot path
         set (IOS_SYSROOT ${IOS_SYSROOT} CACHE INTERNAL "Path to iOS system root")
         set (IOS_SYSROOT ${IOS_SYSROOT} CACHE INTERNAL "Path to iOS system root")
@@ -78,6 +78,22 @@ if (IOS)
     # Workaround what appears to be a bug in CMake/Xcode generator, ensure the CMAKE_OSX_DEPLOYMENT_TARGET is set to empty for iOS build
     # Workaround what appears to be a bug in CMake/Xcode generator, ensure the CMAKE_OSX_DEPLOYMENT_TARGET is set to empty for iOS build
     set (CMAKE_OSX_DEPLOYMENT_TARGET)
     set (CMAKE_OSX_DEPLOYMENT_TARGET)
     unset (CMAKE_OSX_DEPLOYMENT_TARGET CACHE)
     unset (CMAKE_OSX_DEPLOYMENT_TARGET CACHE)
+elseif (TVOS)
+    set (CMAKE_CROSSCOMPILING TRUE)
+    set (CMAKE_XCODE_EFFECTIVE_PLATFORMS -appletvos -appletvsimulator)
+    set (CMAKE_OSX_SYSROOT appletvos)    # Set Base SDK to "Latest tvOS"
+    set (CMAKE_REQUIRED_FLAGS ";-DSmileyHack=byYaoWT;-DCMAKE_MACOSX_BUNDLE=1;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=0;-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY=")
+    if (NOT TVOS_SYSROOT)
+        execute_process (COMMAND xcodebuild -version -sdk ${CMAKE_OSX_SYSROOT} Path OUTPUT_VARIABLE TVOS_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)   # Obtain tvOS sysroot path
+        set (TVOS_SYSROOT ${TVOS_SYSROOT} CACHE INTERNAL "Path to tvOS system root")
+    endif ()
+    set (CMAKE_FIND_ROOT_PATH ${TVOS_SYSROOT})
+    set (APPLETVOS_DEPLOYMENT_TARGET "" CACHE STRING "Specify tvOS deployment target (tvOS platform only); default to latest installed tvOS SDK if not specified")
+    set (CMAKE_XCODE_ATTRIBUTE_APPLETVOS_DEPLOYMENT_TARGET ${APPLETVOS_DEPLOYMENT_TARGET})
+    set (CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES)
+    # Just in case it has similar bug for tvOS build
+    set (CMAKE_OSX_DEPLOYMENT_TARGET)
+    unset (CMAKE_OSX_DEPLOYMENT_TARGET CACHE)
 elseif (XCODE)
 elseif (XCODE)
     set (CMAKE_OSX_SYSROOT macosx)    # Set Base SDK to "Latest OS X"
     set (CMAKE_OSX_SYSROOT macosx)    # Set Base SDK to "Latest OS X"
     if (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
     if (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
@@ -115,6 +131,7 @@ set (CMAKE_EXE_LINKER_FLAGS "${INDIRECT_DEPS_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKE
 include (CMakeDependentOption)
 include (CMakeDependentOption)
 option (URHO3D_C++11 "Enable C++11 standard")
 option (URHO3D_C++11 "Enable C++11 standard")
 cmake_dependent_option (IOS "Setup build for iOS platform" FALSE "XCODE" FALSE)
 cmake_dependent_option (IOS "Setup build for iOS platform" FALSE "XCODE" FALSE)
+cmake_dependent_option (TVOS "Setup build for tvOS platform" FALSE "XCODE" FALSE)
 cmake_dependent_option (URHO3D_64BIT "Enable 64-bit build, the default is set based on the native ABI of the chosen compiler toolchain" "${NATIVE_64BIT}" "NOT MSVC AND NOT ANDROID AND NOT (ARM AND NOT IOS) AND NOT WEB AND NOT POWERPC" "${NATIVE_64BIT}")     # Intentionally only enable the option for iOS but not for tvOS as the latter is 64-bit only
 cmake_dependent_option (URHO3D_64BIT "Enable 64-bit build, the default is set based on the native ABI of the chosen compiler toolchain" "${NATIVE_64BIT}" "NOT MSVC AND NOT ANDROID AND NOT (ARM AND NOT IOS) AND NOT WEB AND NOT POWERPC" "${NATIVE_64BIT}")     # Intentionally only enable the option for iOS but not for tvOS as the latter is 64-bit only
 option (URHO3D_ANGELSCRIPT "Enable AngelScript scripting support" TRUE)
 option (URHO3D_ANGELSCRIPT "Enable AngelScript scripting support" TRUE)
 option (URHO3D_IK "Enable inverse kinematics support" TRUE)
 option (URHO3D_IK "Enable inverse kinematics support" TRUE)
@@ -127,7 +144,7 @@ option (URHO3D_URHO2D "Enable 2D graphics and physics support" TRUE)
 if (ARM AND NOT ANDROID AND NOT RPI AND NOT IOS AND NOT TVOS)
 if (ARM AND NOT ANDROID AND NOT RPI AND NOT IOS AND NOT TVOS)
     set (ARM_ABI_FLAGS "" CACHE STRING "Specify ABI compiler flags (ARM on Linux platform only); e.g. Orange-Pi Mini 2 could use '-mcpu=cortex-a7 -mfpu=neon-vfpv4'")
     set (ARM_ABI_FLAGS "" CACHE STRING "Specify ABI compiler flags (ARM on Linux platform only); e.g. Orange-Pi Mini 2 could use '-mcpu=cortex-a7 -mfpu=neon-vfpv4'")
 endif ()
 endif ()
-if (IOS OR (RPI AND "${RPI_ABI}" MATCHES NEON) OR (ARM AND (URHO3D_64BIT OR "${ARM_ABI_FLAGS}" MATCHES neon)))    # Stringify in case RPI_ABI/ARM_ABI_FLAGS is not set explicitly
+if (IOS OR TVOS OR (RPI AND "${RPI_ABI}" MATCHES NEON) OR (ARM AND (URHO3D_64BIT OR "${ARM_ABI_FLAGS}" MATCHES neon)))    # Stringify in case RPI_ABI/ARM_ABI_FLAGS is not set explicitly
     # TODO: remove this logic when the compiler flags are set in each toolchain file, such that the CheckCompilerToolchain can perform the check automatically
     # TODO: remove this logic when the compiler flags are set in each toolchain file, such that the CheckCompilerToolchain can perform the check automatically
     set (NEON 1)
     set (NEON 1)
 endif ()
 endif ()
@@ -176,19 +193,19 @@ if (CMAKE_PROJECT_NAME STREQUAL Urho3D)
     option (URHO3D_BINDINGS "Enable API binding generation support for script subystems")
     option (URHO3D_BINDINGS "Enable API binding generation support for script subystems")
     cmake_dependent_option (URHO3D_CLANG_TOOLS "Build Clang tools (native on host system only)" FALSE "NOT CMAKE_CROSSCOMPILING" FALSE)
     cmake_dependent_option (URHO3D_CLANG_TOOLS "Build Clang tools (native on host system only)" FALSE "NOT CMAKE_CROSSCOMPILING" FALSE)
     mark_as_advanced (URHO3D_UPDATE_SOURCE_TREE URHO3D_BINDINGS URHO3D_CLANG_TOOLS)
     mark_as_advanced (URHO3D_UPDATE_SOURCE_TREE URHO3D_BINDINGS URHO3D_CLANG_TOOLS)
-    cmake_dependent_option (URHO3D_TOOLS "Build tools (native, RPI, and ARM on Linux only)" TRUE "NOT IOS AND NOT ANDROID AND NOT WEB" FALSE)
-    cmake_dependent_option (URHO3D_EXTRAS "Build extras (native, RPI, and ARM on Linux only)" FALSE "NOT IOS AND NOT ANDROID AND NOT WEB" FALSE)
+    cmake_dependent_option (URHO3D_TOOLS "Build tools (native, RPI, and ARM on Linux only)" TRUE "NOT IOS AND NOT TVOS AND NOT ANDROID AND NOT WEB" FALSE)
+    cmake_dependent_option (URHO3D_EXTRAS "Build extras (native, RPI, and ARM on Linux only)" FALSE "NOT IOS AND NOT TVOS AND NOT ANDROID AND NOT WEB" FALSE)
     option (URHO3D_DOCS "Generate documentation as part of normal build")
     option (URHO3D_DOCS "Generate documentation as part of normal build")
     option (URHO3D_DOCS_QUIET "Generate documentation as part of normal build, suppress generation process from sending anything to stdout")
     option (URHO3D_DOCS_QUIET "Generate documentation as part of normal build, suppress generation process from sending anything to stdout")
     option (URHO3D_PCH "Enable PCH support" TRUE)
     option (URHO3D_PCH "Enable PCH support" TRUE)
-    cmake_dependent_option (URHO3D_DATABASE_ODBC "Enable Database support with ODBC, requires vendor-specific ODBC driver" FALSE "NOT IOS AND NOT ANDROID AND NOT WEB;NOT MSVC OR NOT MSVC_VERSION VERSION_LESS 1900" FALSE)
+    cmake_dependent_option (URHO3D_DATABASE_ODBC "Enable Database support with ODBC, requires vendor-specific ODBC driver" FALSE "NOT IOS AND NOT TVOS AND NOT ANDROID AND NOT WEB;NOT MSVC OR NOT MSVC_VERSION VERSION_LESS 1900" FALSE)
     option (URHO3D_DATABASE_SQLITE "Enable Database support with SQLite embedded")
     option (URHO3D_DATABASE_SQLITE "Enable Database support with SQLite embedded")
     # Enable file watcher support for automatic resource reloads by default.
     # Enable file watcher support for automatic resource reloads by default.
     option (URHO3D_FILEWATCHER "Enable filewatcher support" TRUE)
     option (URHO3D_FILEWATCHER "Enable filewatcher support" TRUE)
     option (URHO3D_TESTING "Enable testing support")
     option (URHO3D_TESTING "Enable testing support")
     # By default this option is off (i.e. we use the MSVC dynamic runtime), this can be switched on if using Urho3D as a STATIC library
     # By default this option is off (i.e. we use the MSVC dynamic runtime), this can be switched on if using Urho3D as a STATIC library
     cmake_dependent_option (URHO3D_STATIC_RUNTIME "Use static C/C++ runtime libraries and eliminate the need for runtime DLLs installation (VS only)" FALSE "MSVC" FALSE)
     cmake_dependent_option (URHO3D_STATIC_RUNTIME "Use static C/C++ runtime libraries and eliminate the need for runtime DLLs installation (VS only)" FALSE "MSVC" FALSE)
-    if (((URHO3D_LUA AND NOT URHO3D_LUAJIT) OR URHO3D_DATABASE_SQLITE) AND NOT ANDROID AND NOT IOS AND NOT WEB AND NOT WIN32)
+    if (((URHO3D_LUA AND NOT URHO3D_LUAJIT) OR URHO3D_DATABASE_SQLITE) AND NOT ANDROID AND NOT IOS AND NOT TVOS AND NOT WEB AND NOT WIN32)
         # Find GNU Readline development library for Lua interpreter and SQLite's isql
         # Find GNU Readline development library for Lua interpreter and SQLite's isql
         find_package (Readline)
         find_package (Readline)
     endif ()
     endif ()
@@ -244,8 +261,8 @@ endif ()
 cmake_dependent_option (URHO3D_MINIDUMPS "Enable minidumps on crash (VS only)" TRUE "MSVC" FALSE)
 cmake_dependent_option (URHO3D_MINIDUMPS "Enable minidumps on crash (VS only)" TRUE "MSVC" FALSE)
 # By default Windows platform setups main executable as Windows application with WinMain() as entry point
 # By default Windows platform setups main executable as Windows application with WinMain() as entry point
 cmake_dependent_option (URHO3D_WIN32_CONSOLE "Use console main() instead of WinMain() as entry point when setting up Windows executable targets (Windows platform only)" FALSE "WIN32" FALSE)
 cmake_dependent_option (URHO3D_WIN32_CONSOLE "Use console main() instead of WinMain() as entry point when setting up Windows executable targets (Windows platform only)" FALSE "WIN32" FALSE)
-cmake_dependent_option (URHO3D_MACOSX_BUNDLE "Use MACOSX_BUNDLE when setting up macOS executable targets (Xcode/macOS platform only)" FALSE "XCODE AND NOT IOS" FALSE)
-if (CMAKE_CROSSCOMPILING AND NOT ANDROID AND NOT IOS)
+cmake_dependent_option (URHO3D_MACOSX_BUNDLE "Use MACOSX_BUNDLE when setting up macOS executable targets (Xcode/macOS platform only)" FALSE "XCODE AND NOT IOS AND NOT TVOS" FALSE)
+if (CMAKE_CROSSCOMPILING AND NOT ANDROID AND NOT IOS AND NOT TVOS)
     set (URHO3D_SCP_TO_TARGET "" CACHE STRING "Use scp to transfer executables to target system (non-Android cross-compiling build only), SSH digital key must be setup first for this to work, typical value has a pattern of usr@tgt:remote-loc")
     set (URHO3D_SCP_TO_TARGET "" CACHE STRING "Use scp to transfer executables to target system (non-Android cross-compiling build only), SSH digital key must be setup first for this to work, typical value has a pattern of usr@tgt:remote-loc")
 else ()
 else ()
     unset (URHO3D_SCP_TO_TARGET CACHE)
     unset (URHO3D_SCP_TO_TARGET CACHE)
@@ -345,7 +362,7 @@ if (URHO3D_LUAJIT)
 endif ()
 endif ()
 
 
 # Union all the sysroot variables into one so it can be referred to generically later
 # Union all the sysroot variables into one so it can be referred to generically later
-set (SYSROOT ${CMAKE_SYSROOT} ${MINGW_SYSROOT} ${IOS_SYSROOT} CACHE INTERNAL "Path to system root of the cross-compiling target")  # SYSROOT is empty for native build
+set (SYSROOT ${CMAKE_SYSROOT} ${MINGW_SYSROOT} ${IOS_SYSROOT} ${TVOS_SYSROOT} CACHE INTERNAL "Path to system root of the cross-compiling target")  # SYSROOT is empty for native build
 
 
 # Clang tools building
 # Clang tools building
 if (URHO3D_CLANG_TOOLS OR URHO3D_BINDINGS)
 if (URHO3D_CLANG_TOOLS OR URHO3D_BINDINGS)
@@ -478,7 +495,7 @@ if (URHO3D_C++11)
 endif ()
 endif ()
 if (APPLE)
 if (APPLE)
     if (IOS)
     if (IOS)
-        # IOS-specific setup
+        # iOS-specific setup
         add_definitions (-DIOS)
         add_definitions (-DIOS)
         if (URHO3D_64BIT)
         if (URHO3D_64BIT)
             if (DEFINED ENV{XCODE_64BIT_ONLY})                  # This environment variable is set automatically when ccache is just being cleared in Travis CI VM
             if (DEFINED ENV{XCODE_64BIT_ONLY})                  # This environment variable is set automatically when ccache is just being cleared in Travis CI VM
@@ -490,9 +507,13 @@ if (APPLE)
             # This is a legacy option and should not be used as we are phasing out 32-bit only mode
             # This is a legacy option and should not be used as we are phasing out 32-bit only mode
             set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_32_BIT))
             set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_32_BIT))
         endif ()
         endif ()
+    elseif (TVOS)
+        # tvOS-specific setup
+        add_definitions (-DTVOS)
+        set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD))
     else ()
     else ()
         if (XCODE)
         if (XCODE)
-            # OSX-specific setup
+            # macOS-specific setup
             if (URHO3D_64BIT)
             if (URHO3D_64BIT)
                 if (URHO3D_UNIVERSAL)
                 if (URHO3D_UNIVERSAL)
                     # This is a legacy option and should not be used as we are phasing out macOS universal binary mode
                     # This is a legacy option and should not be used as we are phasing out macOS universal binary mode
@@ -506,8 +527,8 @@ if (APPLE)
             endif ()
             endif ()
         endif ()
         endif ()
     endif ()
     endif ()
-    # Common OSX and iOS bundle setup
-    if (IOS OR URHO3D_MACOSX_BUNDLE)
+    # Common OSX and iOS/tvOS bundle setup
+    if (IOS OR TVOS OR URHO3D_MACOSX_BUNDLE)
         # Only set the bundle properties to its default when they are not explicitly specified by user
         # Only set the bundle properties to its default when they are not explicitly specified by user
         if (NOT MACOSX_BUNDLE_GUI_IDENTIFIER)
         if (NOT MACOSX_BUNDLE_GUI_IDENTIFIER)
             set (MACOSX_BUNDLE_GUI_IDENTIFIER com.github.urho3d.\${PRODUCT_NAME:rfc1034identifier:lower})
             set (MACOSX_BUNDLE_GUI_IDENTIFIER com.github.urho3d.\${PRODUCT_NAME:rfc1034identifier:lower})
@@ -714,8 +735,8 @@ else ()
 endif ()
 endif ()
 # LuaJIT specific - extra linker flags for linking against LuaJIT (adapted from LuaJIT's original Makefile)
 # LuaJIT specific - extra linker flags for linking against LuaJIT (adapted from LuaJIT's original Makefile)
 if (URHO3D_LUAJIT)
 if (URHO3D_LUAJIT)
-    if (URHO3D_64BIT AND APPLE AND NOT IOS)
-        # 64-bit Mac OS X: it simply won't work without these flags; if you are reading this comment then you may want to know the following also
+    if (URHO3D_64BIT AND APPLE AND NOT IOS AND NOT TVOS)
+        # 64-bit macOS: it simply won't work without these flags; if you are reading this comment then you may want to know the following also
         # it's recommended to rebase all (self-compiled) shared libraries which are loaded at runtime on OSX/x64 (e.g. C extension modules for Lua), see: man rebase
         # it's recommended to rebase all (self-compiled) shared libraries which are loaded at runtime on OSX/x64 (e.g. C extension modules for Lua), see: man rebase
         set (LUAJIT_EXE_LINKER_FLAGS_APPLE "-pagezero_size 10000 -image_base 100000000")
         set (LUAJIT_EXE_LINKER_FLAGS_APPLE "-pagezero_size 10000 -image_base 100000000")
         set (LUAJIT_SHARED_LINKER_FLAGS_APPLE "-image_base 7fff04c4a000")
         set (LUAJIT_SHARED_LINKER_FLAGS_APPLE "-image_base 7fff04c4a000")
@@ -1032,8 +1053,8 @@ macro (define_resource_dirs)
         if (NOT RESOURCE_FILES)
         if (NOT RESOURCE_FILES)
             # Default app bundle icon
             # Default app bundle icon
             set (RESOURCE_FILES ${CMAKE_SOURCE_DIR}/bin/Data/Textures/UrhoIcon.icns)
             set (RESOURCE_FILES ${CMAKE_SOURCE_DIR}/bin/Data/Textures/UrhoIcon.icns)
-            if (IOS)
-                # Default app icon on the iOS home screen
+            if (IOS OR TVOS)
+                # Default app icon on the iOS/tvOS home screen
                 list (APPEND RESOURCE_FILES ${CMAKE_SOURCE_DIR}/bin/Data/Textures/UrhoIcon.png)
                 list (APPEND RESOURCE_FILES ${CMAKE_SOURCE_DIR}/bin/Data/Textures/UrhoIcon.png)
             endif ()
             endif ()
         endif ()
         endif ()
@@ -1455,7 +1476,7 @@ macro (setup_executable)
                 list (APPEND FILES ${LOCATION}/${TARGET_NAME}.${EXT})
                 list (APPEND FILES ${LOCATION}/${TARGET_NAME}.${EXT})
             endforeach ()
             endforeach ()
             install (FILES ${FILES} DESTINATION ${DEST_BUNDLE_DIR} OPTIONAL)
             install (FILES ${FILES} DESTINATION ${DEST_BUNDLE_DIR} OPTIONAL)
-        elseif (DEST_RUNTIME_DIR AND (DEST_BUNDLE_DIR OR NOT IOS))
+        elseif (DEST_RUNTIME_DIR AND (DEST_BUNDLE_DIR OR NOT IOS OR NOT TVOS))
             install (TARGETS ${TARGET_NAME} RUNTIME DESTINATION ${DEST_RUNTIME_DIR} BUNDLE DESTINATION ${DEST_BUNDLE_DIR})
             install (TARGETS ${TARGET_NAME} RUNTIME DESTINATION ${DEST_RUNTIME_DIR} BUNDLE DESTINATION ${DEST_BUNDLE_DIR})
             if (WIN32 AND NOT ARG_NODEPS AND URHO3D_LIB_TYPE STREQUAL SHARED AND NOT URHO3D_DLL_INSTALLED)
             if (WIN32 AND NOT ARG_NODEPS AND URHO3D_LIB_TYPE STREQUAL SHARED AND NOT URHO3D_DLL_INSTALLED)
                 if (TARGET Urho3D)
                 if (TARGET Urho3D)
@@ -1585,6 +1606,9 @@ macro (setup_main_executable)
         elseif (IOS)
         elseif (IOS)
             set (EXE_TYPE MACOSX_BUNDLE)
             set (EXE_TYPE MACOSX_BUNDLE)
             list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY 1,2 MACOSX_BUNDLE_INFO_PLIST iOSBundleInfo.plist.template)
             list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY 1,2 MACOSX_BUNDLE_INFO_PLIST iOSBundleInfo.plist.template)
+        elseif (TVOS)
+            set (EXE_TYPE MACOSX_BUNDLE)
+            list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY 3 MACOSX_BUNDLE_INFO_PLIST tvOSBundleInfo.plist.template)
         elseif (APPLE)
         elseif (APPLE)
             if ((URHO3D_MACOSX_BUNDLE OR ARG_MACOSX_BUNDLE) AND NOT ARG_NOBUNDLE)
             if ((URHO3D_MACOSX_BUNDLE OR ARG_MACOSX_BUNDLE) AND NOT ARG_NOBUNDLE)
                 set (EXE_TYPE MACOSX_BUNDLE)
                 set (EXE_TYPE MACOSX_BUNDLE)
@@ -1904,8 +1928,12 @@ if (IOS)
         # Due to a bug in the CMake/Xcode generator (fixed in 3.4) that prevents iOS targets (library and bundle) to be installed correctly
         # Due to a bug in the CMake/Xcode generator (fixed in 3.4) that prevents iOS targets (library and bundle) to be installed correctly
         # (see http://public.kitware.com/Bug/bug_relationship_graph.php?bug_id=12506&graph=dependency),
         # (see http://public.kitware.com/Bug/bug_relationship_graph.php?bug_id=12506&graph=dependency),
         # below temporary fix is required to work around the bug
         # below temporary fix is required to work around the bug
-        list (APPEND POST_CMAKE_FIXES COMMAND sed -i '' 's/EFFECTIVE_PLATFORM_NAME//g' ${CMAKE_BINARY_DIR}/CMakeScripts/install_postBuildPhase.make* || exit 0)
+        list (APPEND POST_CMAKE_FIXES COMMAND sed -i '' 's/\$$\(EFFECTIVE_PLATFORM_NAME\)//g' ${CMAKE_BINARY_DIR}/CMakeScripts/install_postBuildPhase.make* || exit 0)
     endif ()
     endif ()
+elseif (TVOS)
+    # Almost the same bug as iOS one above but not quite, most probably because CMake does not support AppleTV platform yet
+    list (APPEND POST_CMAKE_FIXES COMMAND sed -i '' 's/\)\$$\(EFFECTIVE_PLATFORM_NAME\)/\) -DEFFECTIVE_PLATFORM_NAME=$$\(EFFECTIVE_PLATFORM_NAME\)/g' ${CMAKE_BINARY_DIR}/CMakeScripts/install_postBuildPhase.make* || exit 0)
+    add_custom_target (APPLETV_POST_CMAKE_FIX COMMAND sed -i '' -E 's,\(Debug|RelWithDebInfo|Release\)/,$$\(CONFIGURATION\)$$\(EFFECTIVE_PLATFORM_NAME\)/,g' ${CMAKE_BINARY_DIR}/Source/Urho3D/CMakeScripts/Urho3D_cmakeRulesBuildPhase.make* || exit 0)
 endif ()
 endif ()
 if (POST_CMAKE_FIXES)
 if (POST_CMAKE_FIXES)
     add_custom_target (POST_CMAKE_FIXES ALL ${POST_CMAKE_FIXES} COMMENT "Applying post-cmake fixes")
     add_custom_target (POST_CMAKE_FIXES ALL ${POST_CMAKE_FIXES} COMMENT "Applying post-cmake fixes")

+ 44 - 0
CMake/Modules/tvOSBundleInfo.plist.template

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleDevelopmentRegion</key>
+    <string>en</string>
+    <key>CFBundleExecutable</key>
+    <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+    <key>CFBundleGetInfoString</key>
+    <string>${MACOSX_BUNDLE_INFO_STRING}</string>
+    <key>CFBundleIconFile</key>
+    <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+    <key>CFBundleIdentifier</key>
+    <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundleLongVersionString</key>
+    <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
+    <key>CFBundleName</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleShortVersionString</key>
+    <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+    <key>CFBundleSignature</key>
+    <string>????</string>
+    <key>CFBundleVersion</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+    <key>CSResourcesFileMapped</key>
+    <true/>
+    <key>LSRequiresIPhoneOS</key>
+    <true/>
+    <key>UIRequiredDeviceCapabilities</key>
+    <array>
+        <string>arm64</string>
+    </array>
+    <key>NSHumanReadableCopyright</key>
+    <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+    <key>CFBundleIconFiles</key>
+    <array>
+        <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+    </array>
+</dict>
+</plist>

+ 5 - 3
CMakeLists.txt

@@ -97,8 +97,10 @@ if (ANDROID)
     set (CPACK_SYSTEM_NAME Android)
     set (CPACK_SYSTEM_NAME Android)
 elseif (IOS)
 elseif (IOS)
     set (CPACK_SYSTEM_NAME iOS)
     set (CPACK_SYSTEM_NAME iOS)
+elseif (TVOS)
+    set (CPACK_SYSTEM_NAME tvOS)
 elseif (APPLE)
 elseif (APPLE)
-    set (CPACK_SYSTEM_NAME OSX)
+    set (CPACK_SYSTEM_NAME macOS)
 elseif (WIN32)
 elseif (WIN32)
     if (MINGW)
     if (MINGW)
         set (CPACK_SYSTEM_NAME MinGW)   # MinGW implies Windows platform
         set (CPACK_SYSTEM_NAME MinGW)   # MinGW implies Windows platform
@@ -164,8 +166,8 @@ if (NOT DEFINED ENV{RELEASE_TAG})
 endif ()
 endif ()
 include (CPack)
 include (CPack)
 
 
-# Setup MacOSX and iOS bundle variables
-if (IOS OR URHO3D_MACOSX_BUNDLE)
+# Setup MacOSX and iOS/tvOS bundle variables
+if (IOS OR TVOS OR URHO3D_MACOSX_BUNDLE)
     if (NOT MACOSX_BUNDLE_ICON_FILE)
     if (NOT MACOSX_BUNDLE_ICON_FILE)
         set (MACOSX_BUNDLE_ICON_FILE UrhoIcon)
         set (MACOSX_BUNDLE_ICON_FILE UrhoIcon)
     endif ()
     endif ()

+ 2 - 0
Docs/GettingStarted.dox

@@ -100,6 +100,7 @@ A number of build options can be defined when invoking the build scripts or when
 |WIN32                |0|Configure project using MinGW (32-bit or 64-bit) cross-compiler toolchain (cmake_generic.sh only), cmake-gui users need to specify MinGW toolchain file for cross-compiling explicitly|
 |WIN32                |0|Configure project using MinGW (32-bit or 64-bit) cross-compiler toolchain (cmake_generic.sh only), cmake-gui users need to specify MinGW toolchain file for cross-compiling explicitly|
 |WEB                  |0|Configure project using Emscripten cross-compiler toolchain (cmake_generic.bat and cmake_generic.sh only), cmake-gui users need to specify Emscripten toolchain file for cross-compiling explicitly|
 |WEB                  |0|Configure project using Emscripten cross-compiler toolchain (cmake_generic.bat and cmake_generic.sh only), cmake-gui users need to specify Emscripten toolchain file for cross-compiling explicitly|
 |IOS                  |0|Configure project for targeting iOS platform (cmake_generic.sh and cmake-gui only)|
 |IOS                  |0|Configure project for targeting iOS platform (cmake_generic.sh and cmake-gui only)|
+|TVOS                 |0|Configure project for targeting tvOS platform (cmake_generic.sh and cmake-gui only)|
 |URHO3D_64BIT         |*|Enable 64-bit build, the default is set based on the native ABI of the chosen compiler toolchain|
 |URHO3D_64BIT         |*|Enable 64-bit build, the default is set based on the native ABI of the chosen compiler toolchain|
 |URHO3D_ANGELSCRIPT   |1|Enable AngelScript scripting support|
 |URHO3D_ANGELSCRIPT   |1|Enable AngelScript scripting support|
 |URHO3D_LUA           |1|Enable Lua scripting support|
 |URHO3D_LUA           |1|Enable Lua scripting support|
@@ -148,6 +149,7 @@ A number of build options can be defined when invoking the build scripts or when
 |CMAKE_INSTALL_PREFIX |*|Install path prefix, prepended onto install directories; default to 'c:/Program Files/Urho3D' on Windows host and '/usr/local' on all other non-Windows hosts|
 |CMAKE_INSTALL_PREFIX |*|Install path prefix, prepended onto install directories; default to 'c:/Program Files/Urho3D' on Windows host and '/usr/local' on all other non-Windows hosts|
 |CMAKE_OSX_DEPLOYMENT_TARGET|-|Specify macOS deployment target (macOS platform only); default to current running macOS if not specified, the minimum supported target is 10.5 due to constraint from SDL library|
 |CMAKE_OSX_DEPLOYMENT_TARGET|-|Specify macOS deployment target (macOS platform only); default to current running macOS if not specified, the minimum supported target is 10.5 due to constraint from SDL library|
 |IPHONEOS_DEPLOYMENT_TARGET|-|Specify iOS deployment target (iOS platform only); default to latest installed iOS SDK if not specified, the minimum supported target is 3.0 due to constraint from SDL library|
 |IPHONEOS_DEPLOYMENT_TARGET|-|Specify iOS deployment target (iOS platform only); default to latest installed iOS SDK if not specified, the minimum supported target is 3.0 due to constraint from SDL library|
+|APPLETVOS_DEPLOYMENT_TARGET|-|Specify AppleTV OS deployment target (tvOS platform only); default to latest installed tvOS SDK if not specified, the minimum spported target is 9.0|
 |ANDROID_NDK          |-|Path to Android NDK (Android platform only)|
 |ANDROID_NDK          |-|Path to Android NDK (Android platform only)|
 |ANDROID_TOOLCHAIN_NAME|*|Specify the name of compiler toolchain (Android platform only), possible values depends on installed Android NDK, default to Clang compiler toolchain|
 |ANDROID_TOOLCHAIN_NAME|*|Specify the name of compiler toolchain (Android platform only), possible values depends on installed Android NDK, default to Clang compiler toolchain|
 |ANDROID_ABI          |*|Specify target ABI (Android platform only), possible values depends on the target arch of the chosen Android compiler toolchain, default to first ABI of each target arch|
 |ANDROID_ABI          |*|Specify target ABI (Android platform only), possible values depends on the target arch of the chosen Android compiler toolchain, default to first ABI of each target arch|

+ 10 - 10
Rakefile

@@ -54,7 +54,7 @@ task :cmake do
   platform = 'native'
   platform = 'native'
   build_options = ''
   build_options = ''
   # TODO: Need to find a way to automatically populate the array with all the Urho3D supported build options, at the moment it only contains those being used in CI
   # TODO: Need to find a way to automatically populate the array with all the Urho3D supported build options, at the moment it only contains those being used in CI
-  ['URHO3D_64BIT', 'URHO3D_LIB_TYPE', 'URHO3D_STATIC_RUNTIME', 'URHO3D_PCH', 'URHO3D_BINDINGS', 'URHO3D_OPENGL', 'URHO3D_D3D11', 'URHO3D_TESTING', 'URHO3D_TEST_TIMEOUT', 'URHO3D_UPDATE_SOURCE_TREE', 'URHO3D_TOOLS', 'URHO3D_DEPLOYMENT_TARGET', 'URHO3D_USE_LIB64_RPM', 'CMAKE_BUILD_TYPE', 'CMAKE_OSX_DEPLOYMENT_TARGET', 'IOS', 'IPHONEOS_DEPLOYMENT_TARGET', 'WIN32', 'MINGW', 'DIRECTX_INC_SEARCH_PATHS', 'DIRECTX_LIB_SEARCH_PATHS', 'ANDROID', 'ANDROID_ABI', 'ANDROID_NATIVE_API_LEVEL', 'ANDROID_TOOLCHAIN_NAME', 'RPI', 'RPI_ABI', 'ARM', 'ARM_ABI_FLAGS', 'WEB', 'EMSCRIPTEN_SHARE_DATA', 'EMSCRIPTEN_WASM', 'EMSCRIPTEN_EMRUN_BROWSER'].each { |var|
+  ['URHO3D_64BIT', 'URHO3D_LIB_TYPE', 'URHO3D_STATIC_RUNTIME', 'URHO3D_PCH', 'URHO3D_BINDINGS', 'URHO3D_OPENGL', 'URHO3D_D3D11', 'URHO3D_TESTING', 'URHO3D_TEST_TIMEOUT', 'URHO3D_UPDATE_SOURCE_TREE', 'URHO3D_TOOLS', 'URHO3D_DEPLOYMENT_TARGET', 'URHO3D_USE_LIB64_RPM', 'CMAKE_BUILD_TYPE', 'CMAKE_OSX_DEPLOYMENT_TARGET', 'IOS', 'IPHONEOS_DEPLOYMENT_TARGET', 'TVOS', 'APPLETVOS_DEPLOYMENT_TARGET', 'WIN32', 'MINGW', 'DIRECTX_INC_SEARCH_PATHS', 'DIRECTX_LIB_SEARCH_PATHS', 'ANDROID', 'ANDROID_ABI', 'ANDROID_NATIVE_API_LEVEL', 'ANDROID_TOOLCHAIN_NAME', 'RPI', 'RPI_ABI', 'ARM', 'ARM_ABI_FLAGS', 'WEB', 'EMSCRIPTEN_SHARE_DATA', 'EMSCRIPTEN_WASM', 'EMSCRIPTEN_EMRUN_BROWSER'].each { |var|
     ARGV << "#{var}=\"#{ENV[var]}\"" if ENV[var] && !ARGV.find { |arg| /#{var}=/ =~ arg }
     ARGV << "#{var}=\"#{ENV[var]}\"" if ENV[var] && !ARGV.find { |arg| /#{var}=/ =~ arg }
   }
   }
   ARGV.each { |option|
   ARGV.each { |option|
@@ -64,11 +64,11 @@ task :cmake do
       # do nothing
       # do nothing
     when 'clean', 'codeblocks', 'codelite', 'eclipse', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'xcode'
     when 'clean', 'codeblocks', 'codelite', 'eclipse', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'xcode'
       script = "cmake_#{option}" unless script == 'cmake_clean'
       script = "cmake_#{option}" unless script == 'cmake_clean'
-    when 'android', 'arm', 'ios', 'mingw', 'rpi', 'web'
+    when 'android', 'arm', 'ios', 'tvos', 'mingw', 'rpi', 'web'
       platform = option
       platform = option
       build_options = "#{build_options} -D#{option == 'mingw' ? 'WIN32' : option.upcase}=1" unless script == 'cmake_clean'
       build_options = "#{build_options} -D#{option == 'mingw' ? 'WIN32' : option.upcase}=1" unless script == 'cmake_clean'
-      script = 'cmake_xcode' if option == 'ios'
-      script = 'cmake_mingw' if option == 'mingw' && ENV['OS']
+      script = 'cmake_xcode' if /(?:i|tv)os/ =~ option && script != 'cmake_clean'
+      script = 'cmake_mingw' if option == 'mingw' && ENV['OS'] && script != 'cmake_clean'
     when 'fix_scm'
     when 'fix_scm'
       build_options = "#{build_options} --fix-scm" if script == 'cmake_eclipse'
       build_options = "#{build_options} --fix-scm" if script == 'cmake_eclipse'
     else
     else
@@ -105,7 +105,7 @@ task :make do
     case option
     case option
     when 'codeblocks', 'codelite', 'eclipse', 'generic', 'make', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'xcode'
     when 'codeblocks', 'codelite', 'eclipse', 'generic', 'make', 'ninja', 'vs2008', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'xcode'
       # do nothing
       # do nothing
-    when 'android', 'arm', 'ios', 'mingw', 'rpi', 'web'
+    when 'android', 'arm', 'ios', 'tvos', 'mingw', 'rpi', 'web'
       platform = option
       platform = option
     when 'clean_first'
     when 'clean_first'
       cmake_build_options = "#{cmake_build_options} --clean-first"
       cmake_build_options = "#{cmake_build_options} --clean-first"
@@ -347,7 +347,7 @@ task :ci do
   # Always use a same build configuration to keep ccache's cache size small; single-config generator needs the option when configuring, while multi-config when building
   # Always use a same build configuration to keep ccache's cache size small; single-config generator needs the option when configuring, while multi-config when building
   ENV[ENV['XCODE'] ? 'config' : 'CMAKE_BUILD_TYPE'] = 'Release' if ENV['USE_CCACHE']
   ENV[ENV['XCODE'] ? 'config' : 'CMAKE_BUILD_TYPE'] = 'Release' if ENV['USE_CCACHE']
   # Currently we don't have the infra to test run all the platforms; also skip when doing packaging build due to time constraint
   # Currently we don't have the infra to test run all the platforms; also skip when doing packaging build due to time constraint
-  ENV['URHO3D_TESTING'] = '1' if (((ENV['LINUX'] && !ENV['URHO3D_64BIT']) || (ENV['OSX'] && !ENV['IOS']) || ENV['APPVEYOR']) && !ENV['PACKAGE_UPLOAD']) || ENV['WEB']
+  ENV['URHO3D_TESTING'] = '1' if (((ENV['LINUX'] && !ENV['URHO3D_64BIT']) || (ENV['OSX'] && !ENV['IOS'] && !ENV['TVOS']) || ENV['APPVEYOR']) && !ENV['PACKAGE_UPLOAD']) || ENV['WEB']
   # When not explicitly specified then use generic generator
   # When not explicitly specified then use generic generator
   generator = ENV['XCODE'] ? 'xcode' : (ENV['APPVEYOR'] && !ENV['MINGW'] ? 'vs2015' : '')
   generator = ENV['XCODE'] ? 'xcode' : (ENV['APPVEYOR'] && !ENV['MINGW'] ? 'vs2015' : '')
   # LuaJIT on MinGW build is not possible on Travis-CI with Ubuntu 14.04 LTS still as its GCC cross-compiler does not have native exception handling
   # LuaJIT on MinGW build is not possible on Travis-CI with Ubuntu 14.04 LTS still as its GCC cross-compiler does not have native exception handling
@@ -378,8 +378,8 @@ task :ci do
   else
   else
     test = ''
     test = ''
   end
   end
-  # Skip scaffolding test when time up or packaging for iOS and Web platform
-  unless ENV['CI'] && (ENV['IOS'] || ENV['WEB']) && ENV['PACKAGE_UPLOAD'] || ENV['XCODE_64BIT_ONLY'] || timeup
+  # Skip scaffolding test when time up or packaging for iOS, tvOS, and Web platform
+  unless ENV['CI'] && (ENV['IOS'] || ENV['TVOS'] || ENV['WEB']) && ENV['PACKAGE_UPLOAD'] || ENV['XCODE_64BIT_ONLY'] || timeup
     # Staged-install Urho3D SDK when on Travis-CI; normal install when on AppVeyor
     # Staged-install Urho3D SDK when on Travis-CI; normal install when on AppVeyor
     ENV['DESTDIR'] = ENV['HOME'] || Dir.home unless ENV['APPVEYOR']
     ENV['DESTDIR'] = ENV['HOME'] || Dir.home unless ENV['APPVEYOR']
     if !wait_for_block("Installing Urho3D SDK to #{ENV['DESTDIR'] ? "#{ENV['DESTDIR']}/usr/local" : 'default system-wide location'}...") { Thread.current[:subcommand_to_kill] = 'xcodebuild'; system "rake make target=install >#{ENV['OS'] ? 'nul' : '/dev/null'}" }
     if !wait_for_block("Installing Urho3D SDK to #{ENV['DESTDIR'] ? "#{ENV['DESTDIR']}/usr/local" : 'default system-wide location'}...") { Thread.current[:subcommand_to_kill] = 'xcodebuild'; system "rake make target=install >#{ENV['OS'] ? 'nul' : '/dev/null'}" }
@@ -616,8 +616,8 @@ task :ci_package_upload do
   end
   end
   # Make the package
   # Make the package
   puts "Packaging artifacts...\n\n"; $stdout.flush
   puts "Packaging artifacts...\n\n"; $stdout.flush
-  if ENV['IOS']
-    # There is a bug in CMake/CPack that causes the 'package' target failed to build for IOS platform, workaround by calling cpack directly; CMake 3.4 runs the target successfully, however, the result tarball is incomplete (somehow it misses packaging the library itself, another bug?)
+  if ENV['IOS'] || ENV['TVOS']
+    # There is a bug in CMake/CPack that causes the 'package' target failed to build for iOS and tvOS platforms, workaround by calling cpack directly; CMake 3.4 runs the target successfully, however, the result tarball is incomplete (somehow it misses packaging the library itself, another bug?)
     system 'cd ../Build && cpack -G TGZ 2>/dev/null' or abort 'Failed to make binary package'
     system 'cd ../Build && cpack -G TGZ 2>/dev/null' or abort 'Failed to make binary package'
   else
   else
     if ENV['ANDROID']
     if ENV['ANDROID']

+ 1 - 1
Source/CMakeLists.txt

@@ -37,7 +37,7 @@ include (CheckLibraryExists)
 check_library_exists (m sincosf "" HAVE_SINCOSF)
 check_library_exists (m sincosf "" HAVE_SINCOSF)
 
 
 # Setup RPATH settings
 # Setup RPATH settings
-if (URHO3D_LIB_TYPE STREQUAL SHARED AND NOT WIN32 AND NOT ANDROID AND NOT IOS AND NOT WEB)
+if (URHO3D_LIB_TYPE STREQUAL SHARED AND NOT WIN32 AND NOT ANDROID AND NOT IOS AND NOT TVOS AND NOT WEB)
     # Add RPATH entries when building
     # Add RPATH entries when building
     set (CMAKE_SKIP_BUILD_RPATH FALSE)
     set (CMAKE_SKIP_BUILD_RPATH FALSE)
     # But don't set them yet in the build tree
     # But don't set them yet in the build tree

+ 2 - 0
Source/ThirdParty/Civetweb/CMakeLists.txt

@@ -24,6 +24,8 @@
 set (TARGET_NAME Civetweb)
 set (TARGET_NAME Civetweb)
 
 
 # Define preprocessor macros
 # Define preprocessor macros
+# Always disable Common Gateway Interface
+add_definitions (-DNO_CGI)
 if (WIN32)
 if (WIN32)
     include (CheckStructHasMember)
     include (CheckStructHasMember)
     check_struct_has_member (struct\ timespec tv_sec time.h HAVE_STRUCT_TIMESPEC_TV_SEC)
     check_struct_has_member (struct\ timespec tv_sec time.h HAVE_STRUCT_TIMESPEC_TV_SEC)

+ 1 - 1
Source/ThirdParty/Lua/CMakeLists.txt

@@ -40,7 +40,7 @@ setup_library ()
 install_header_files (DIRECTORY src/ DESTINATION ${DEST_INCLUDE_DIR}/ThirdParty/Lua FILES_MATCHING PATTERN *.h)  # Note: the trailing slash is significant
 install_header_files (DIRECTORY src/ DESTINATION ${DEST_INCLUDE_DIR}/ThirdParty/Lua FILES_MATCHING PATTERN *.h)  # Note: the trailing slash is significant
 
 
 # Setup additional Lua standalone targets (these targets can be transfered and executed on an embedded device, such as Raspberry Pi and Android)
 # Setup additional Lua standalone targets (these targets can be transfered and executed on an embedded device, such as Raspberry Pi and Android)
-if (NOT IOS AND NOT WEB)
+if (NOT IOS AND NOT TVOS AND NOT WEB)
     # Define target name for Lua interpreter
     # Define target name for Lua interpreter
     set (TARGET_NAME lua_interpreter)   # Note: intended target name is 'lua' which clashes with 'Lua' library target above for case-insensitive platform
     set (TARGET_NAME lua_interpreter)   # Note: intended target name is 'lua' which clashes with 'Lua' library target above for case-insensitive platform
 
 

+ 5 - 0
Source/ThirdParty/Lua/src/loslib.c

@@ -36,7 +36,12 @@ static int os_pushresult (lua_State *L, int i, const char *filename) {
 
 
 
 
 static int os_execute (lua_State *L) {
 static int os_execute (lua_State *L) {
+// Urho3D - tvOS port, system not available for AppleTVOS and also its simulator
+#ifdef TVOS
+  lua_pushinteger(L, -1);
+#else
   lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
   lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
+#endif
   return 1;
   return 1;
 }
 }
 
 

+ 30 - 12
Source/ThirdParty/LuaJIT/CMakeLists.txt

@@ -203,7 +203,7 @@ if (NOT LUAJIT_CACHE STREQUAL "${URHO3D_64BIT}-${LUAJIT_DISABLE_FFI}-${LUAJIT_DI
         if (XCODE)
         if (XCODE)
             if (ARCH)    # The ARCH variable is defined only when we are building LuaJIT for non-native archs using external project
             if (ARCH)    # The ARCH variable is defined only when we are building LuaJIT for non-native archs using external project
                 set (ARCH_FLAGS -arch ${ARCH})
                 set (ARCH_FLAGS -arch ${ARCH})
-            elseif (IOS)
+            elseif (IOS OR TVOS)
                 if (URHO3D_64BIT)
                 if (URHO3D_64BIT)
                     set (ARCH_FLAGS -arch arm64)
                     set (ARCH_FLAGS -arch arm64)
                 else ()
                 else ()
@@ -245,7 +245,7 @@ if (NOT LUAJIT_CACHE STREQUAL "${URHO3D_64BIT}-${LUAJIT_DISABLE_FFI}-${LUAJIT_DI
     set (TARGET_ARCH ${TARGET_ARCH} -DLUAJIT_TARGET=LUAJIT_ARCH_${TARGET_LJARCH})
     set (TARGET_ARCH ${TARGET_ARCH} -DLUAJIT_TARGET=LUAJIT_ARCH_${TARGET_LJARCH})
 
 
     # Makefile: Target system detection
     # Makefile: Target system detection
-    if (IOS)
+    if (IOS OR TVOS)
         set (TARGET_SYS iOS)
         set (TARGET_SYS iOS)
     elseif (CMAKE_SYSTEM_NAME STREQUAL Linux)
     elseif (CMAKE_SYSTEM_NAME STREQUAL Linux)
         set (TARGET_SYS Linux)
         set (TARGET_SYS Linux)
@@ -383,9 +383,10 @@ if (CMAKE_CROSSCOMPILING)
     endforeach ()
     endforeach ()
     # When cross-compiling, build the host tool as external project
     # When cross-compiling, build the host tool as external project
     include (ExternalProject)
     include (ExternalProject)
-    if (IOS)
-        # For iOS target, ensure the host environment is cleared first; Also workaround a known CMake/Xcode generator bug which prevents it from installing binaries correctly
-        set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND} BUILD_COMMAND bash -c "sed -i '' 's/EFFECTIVE_PLATFORM_NAME//g' CMakeScripts/install_postBuildPhase.make*")
+    if (IOS OR TVOS)
+        # When cross-compiling for iOS/tvOS the host environment has been altered by xcodebuild for the said platform, the following fix is required to reset the host environment before spawning another process to configure/generate project file for external project
+        # Also workaround a known CMake/Xcode generator bug which prevents it from installing native tool binaries correctly
+        set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND} BUILD_COMMAND bash -c "sed -i '' 's/\$$\(EFFECTIVE_PLATFORM_NAME\)//g' CMakeScripts/install_postBuildPhase.make*")
     else ()
     else ()
         set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND})
         set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND})
     endif ()
     endif ()
@@ -475,10 +476,10 @@ set (INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/generated)
 if (XCODE)
 if (XCODE)
     if (ARCH)
     if (ARCH)
         list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_ARCHS ${ARCH})
         list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_ARCHS ${ARCH})
-    elseif (URHO3D_64BIT OR IOS)
+    elseif (URHO3D_64BIT OR IOS OR TVOS)
         set (EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL)
         set (EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL)
         list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH YES)
         list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH YES)
-        if (URHO3D_64BIT AND IOS)
+        if (URHO3D_64BIT AND (IOS OR TVOS))
             list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_ARCHS arm64)     # The ARCHS_STANDARD builds armv7 first, but we have setup LuaJIT target detection to detect arm64 as the default arch so we override Xcode to build arm64 first
             list (APPEND TARGET_PROPERTIES XCODE_ATTRIBUTE_ARCHS arm64)     # The ARCHS_STANDARD builds armv7 first, but we have setup LuaJIT target detection to detect arm64 as the default arch so we override Xcode to build arm64 first
         endif ()
         endif ()
     endif ()
     endif ()
@@ -487,12 +488,12 @@ setup_library (${EXCLUDE_FROM_ALL})
 if (XCODE AND NOT ARCH)    # These variables are used to control the recursion as this script is recursive in nature on Xcode
 if (XCODE AND NOT ARCH)    # These variables are used to control the recursion as this script is recursive in nature on Xcode
     # Add external and custom targets to build Mach-O universal binary LuaJIT sub-library
     # Add external and custom targets to build Mach-O universal binary LuaJIT sub-library
     include (ExternalProject)
     include (ExternalProject)
-    foreach (LUAJIT_OPT LUAJIT_ENABLE_GC64 LUAJIT_DISABLE_FFI LUAJIT_ENABLE_LUA52COMPAT LUAJIT_DISABLE_JIT LUAJIT_NUMMODE LUAJIT_USE_SYSMALLOC LUAJIT_USE_VALGRIND LUAJIT_USE_GDBJIT LUA_USE_APICHECK LUA_USE_ASSERT LUAJIT_NO_STACK_PROTECTION IOS IPHONEOS_DEPLOYMENT_TARGET URHO3D_LUAJIT_AMALG BAKED_CMAKE_SOURCE_DIR)
+    foreach (LUAJIT_OPT LUAJIT_ENABLE_GC64 LUAJIT_DISABLE_FFI LUAJIT_ENABLE_LUA52COMPAT LUAJIT_DISABLE_JIT LUAJIT_NUMMODE LUAJIT_USE_SYSMALLOC LUAJIT_USE_VALGRIND LUAJIT_USE_GDBJIT LUA_USE_APICHECK LUA_USE_ASSERT LUAJIT_NO_STACK_PROTECTION IOS IPHONEOS_DEPLOYMENT_TARGET TVOS APPLETVOS_DEPLOYMENT_TARGET URHO3D_LUAJIT_AMALG BAKED_CMAKE_SOURCE_DIR)
         if (DEFINED ${LUAJIT_OPT})
         if (DEFINED ${LUAJIT_OPT})
             list (APPEND LUAJIT_PASSTHRU_OPTS -D${LUAJIT_OPT}=${${LUAJIT_OPT}})
             list (APPEND LUAJIT_PASSTHRU_OPTS -D${LUAJIT_OPT}=${${LUAJIT_OPT}})
         endif ()
         endif ()
     endforeach ()
     endforeach ()
-    if (IOS)
+    if (IOS OR TVOS)
         set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CI=$ENV{CI} ${CMAKE_COMMAND})
         set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CI=$ENV{CI} ${CMAKE_COMMAND})
     else ()
     else ()
         set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CI=$ENV{CI} ${CMAKE_COMMAND})
         set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CI=$ENV{CI} ${CMAKE_COMMAND})
@@ -503,7 +504,7 @@ if (XCODE AND NOT ARCH)    # These variables are used to control the recursion a
             SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
             SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
             CMAKE_ARGS -DARCH=i386 -DINSTALL_ARCHIVE_DIR=${CMAKE_CURRENT_BINARY_DIR} -DURHO3D_64BIT=0 ${LUAJIT_PASSTHRU_OPTS} ${ALTERNATE_COMMAND} BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG> -- -sdk iphonesimulator)
             CMAKE_ARGS -DARCH=i386 -DINSTALL_ARCHIVE_DIR=${CMAKE_CURRENT_BINARY_DIR} -DURHO3D_64BIT=0 ${LUAJIT_PASSTHRU_OPTS} ${ALTERNATE_COMMAND} BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG> -- -sdk iphonesimulator)
         if (URHO3D_64BIT)
         if (URHO3D_64BIT)
-            # 64-bit iOS universal binary contains all the archs: arm64 and armv7 (iPhoneOS), and x86_64 and i386 (iPhoneSimulator)
+            # 64-bit iOS universal binaries: for iPhoneOS SDK contains arm64 and armv7 archs, and for iPhoneSimulator SDK contains x86_64 and i386 archs
             ExternalProject_Add (${TARGET_NAME}_x86_64
             ExternalProject_Add (${TARGET_NAME}_x86_64
                 SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
                 SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
                 CMAKE_ARGS -DARCH=x86_64 -DINSTALL_ARCHIVE_DIR=${CMAKE_CURRENT_BINARY_DIR} ${LUAJIT_PASSTHRU_OPTS} ${ALTERNATE_COMMAND} BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG> -- -sdk iphonesimulator)
                 CMAKE_ARGS -DARCH=x86_64 -DINSTALL_ARCHIVE_DIR=${CMAKE_CURRENT_BINARY_DIR} ${LUAJIT_PASSTHRU_OPTS} ${ALTERNATE_COMMAND} BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG> -- -sdk iphonesimulator)
@@ -530,6 +531,22 @@ if (XCODE AND NOT ARCH)    # These variables are used to control the recursion a
             COMMAND if [ '$(CONFIGURATION)' != 'Debug' ] || echo '$(ARCHS)' |grep -cq 86\; then xcodebuild ARCHS="$(ARCHS)" -target ${TARGET_NAME}_universal-iphonesimulator -configuration $(CONFIGURATION)\; fi
             COMMAND if [ '$(CONFIGURATION)' != 'Debug' ] || echo '$(ARCHS)' |grep -cq 86\; then xcodebuild ARCHS="$(ARCHS)" -target ${TARGET_NAME}_universal-iphonesimulator -configuration $(CONFIGURATION)\; fi
             WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
             WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
             COMMENT "Creating Mach-O universal binary LuaJIT library")
             COMMENT "Creating Mach-O universal binary LuaJIT library")
+    elseif (TVOS)
+        # 64-bit tvOS universal binary contains both arm64 (AppleTVOS) and x86_64 (AppleTVSimulator) archs
+        ExternalProject_Add (${TARGET_NAME}_x86_64
+            SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+            CMAKE_ARGS -DARCH=x86_64 -DINSTALL_ARCHIVE_DIR=${CMAKE_CURRENT_BINARY_DIR} ${LUAJIT_PASSTHRU_OPTS} ${ALTERNATE_COMMAND} BUILD_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install --config $<CONFIG> -- -sdk appletvsimulator)
+        add_custom_target (${TARGET_NAME}_universal-appletvsimulator
+            COMMAND xcodebuild -target ${TARGET_NAME}_x86_64 -configuration $(CONFIGURATION) && cp -p ${CMAKE_BINARY_DIR}/Source/ThirdParty/${TARGET_NAME}/$<CONFIG>-appletvsimulator/lib${TARGET_NAME}.a{.x86_64,}
+            WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
+        add_custom_target (${TARGET_NAME}_universal-appletvos
+            COMMAND xcodebuild -target ${TARGET_NAME} -configuration $(CONFIGURATION)
+            WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
+        add_custom_target (${TARGET_NAME}_universal ALL
+            COMMAND if [ '$(CONFIGURATION)' != 'Debug' ] || echo '$(ARCHS)' |grep -cq arm\; then xcodebuild ARCHS="$(ARCHS)" -target ${TARGET_NAME}_universal-appletvos -configuration $(CONFIGURATION)\; fi
+            COMMAND if [ '$(CONFIGURATION)' != 'Debug' ] || echo '$(ARCHS)' |grep -cq 86\; then xcodebuild ARCHS="$(ARCHS)" -target ${TARGET_NAME}_universal-appletvsimulator -configuration $(CONFIGURATION)\; fi
+            WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+            COMMENT "Creating Mach-O universal binary LuaJIT library")
     elseif (URHO3D_UNIVERSAL)
     elseif (URHO3D_UNIVERSAL)
         # macOS universal binary contains both x86_86 and i386 archs
         # macOS universal binary contains both x86_86 and i386 archs
         ExternalProject_Add (${TARGET_NAME}_i386
         ExternalProject_Add (${TARGET_NAME}_i386
@@ -541,14 +558,15 @@ if (XCODE AND NOT ARCH)    # These variables are used to control the recursion a
             COMMENT "Creating Mach-O universal binary LuaJIT library")
             COMMENT "Creating Mach-O universal binary LuaJIT library")
     endif ()
     endif ()
 elseif (INSTALL_ARCHIVE_DIR)
 elseif (INSTALL_ARCHIVE_DIR)
-    install (FILES $<TARGET_FILE:${TARGET_NAME}> DESTINATION ${INSTALL_ARCHIVE_DIR}/$<CONFIG>\${EFFECTIVE_PLATFORM_NAME} RENAME lib${TARGET_NAME}.a.${ARCH})   # This is a hack to workaround CMake (current) limitation
+    # This is a hack as it relies on CMake internal implementation
+    install (FILES $<TARGET_FILE:${TARGET_NAME}> DESTINATION ${INSTALL_ARCHIVE_DIR}/$<CONFIG>\${EFFECTIVE_PLATFORM_NAME} RENAME lib${TARGET_NAME}.a.${ARCH})
 endif ()
 endif ()
 
 
 # Install headers for building and using the Urho3D library (no direct dependencies but library user may need them)
 # Install headers for building and using the Urho3D library (no direct dependencies but library user may need them)
 install_header_files (DIRECTORY src/ DESTINATION ${DEST_INCLUDE_DIR}/ThirdParty/LuaJIT FILES_MATCHING PATTERN *.h *.hpp)  # Note: the trailing slash is significant
 install_header_files (DIRECTORY src/ DESTINATION ${DEST_INCLUDE_DIR}/ThirdParty/LuaJIT FILES_MATCHING PATTERN *.h *.hpp)  # Note: the trailing slash is significant
 
 
 # Setup additional Lua standalone target (this target can be transfered and executed on an embedded device, such as Raspberry Pi and Android)
 # Setup additional Lua standalone target (this target can be transfered and executed on an embedded device, such as Raspberry Pi and Android)
-if (NOT CMAKE_PROJECT_NAME MATCHES ^Urho3D-ExternalProject-LuaJIT AND NOT IOS AND NOT WEB)
+if (NOT CMAKE_PROJECT_NAME MATCHES ^Urho3D-ExternalProject-LuaJIT AND NOT IOS AND NOT TVOS AND NOT WEB)
     # Define target name for LuaJIT interpreter cum compiler
     # Define target name for LuaJIT interpreter cum compiler
     set (TARGET_NAME luajit_interpreter)   # Note: intended target name is 'luajit' which clashes with 'LuaJIT' library target above for case-insensitive platform
     set (TARGET_NAME luajit_interpreter)   # Note: intended target name is 'luajit' which clashes with 'LuaJIT' library target above for case-insensitive platform
 
 

+ 4 - 1
Source/ThirdParty/LuaJIT/src/lj_arch.h

@@ -3,6 +3,8 @@
 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h
 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h
 */
 */
 
 
+// Modified by Yao Wei Tjong for Urho3D
+
 #ifndef _LJ_ARCH_H
 #ifndef _LJ_ARCH_H
 #define _LJ_ARCH_H
 #define _LJ_ARCH_H
 
 
@@ -517,7 +519,8 @@
 #if defined(__symbian__) || LJ_TARGET_WINDOWS
 #if defined(__symbian__) || LJ_TARGET_WINDOWS
 #define LUAJIT_NO_EXP2
 #define LUAJIT_NO_EXP2
 #endif
 #endif
-#if LJ_TARGET_CONSOLE || (LJ_TARGET_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0)
+// Urho3D - tvOS port, system is not available for tvOS and also its simulator
+#if LJ_TARGET_CONSOLE || (LJ_TARGET_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0) || __TV_OS_VERSION_MIN_REQUIRED
 #define LJ_NO_SYSTEM		1
 #define LJ_NO_SYSTEM		1
 #endif
 #endif
 
 

+ 7 - 3
Source/ThirdParty/SDL/CMakeLists.txt

@@ -736,7 +736,7 @@ elseif(APPLE)
 
 
   if(SDL_JOYSTICK)
   if(SDL_JOYSTICK)
     # Urho3D - bug fix - make it work for iOS platform
     # Urho3D - bug fix - make it work for iOS platform
-    if (IOS)
+    if (IOS OR TVOS)
       set (SDL_JOYSTICK_MFI 1)
       set (SDL_JOYSTICK_MFI 1)
       file (GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/iphoneos/*.m)
       file (GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/iphoneos/*.m)
     else ()
     else ()
@@ -752,7 +752,7 @@ elseif(APPLE)
 
 
   if(SDL_HAPTIC)
   if(SDL_HAPTIC)
     # Urho3d - bug fix - make it work for iOS platform
     # Urho3d - bug fix - make it work for iOS platform
-    if (IOS)
+    if (IOS OR TVOS)
       set (SDL_HAPTIC_DUMMY 1)
       set (SDL_HAPTIC_DUMMY 1)
       file (GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/dummy/*.c)
       file (GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/dummy/*.c)
     else ()
     else ()
@@ -770,7 +770,7 @@ elseif(APPLE)
 
 
   if(SDL_POWER)
   if(SDL_POWER)
     # Urho3d - bug fix - make it work for iOS platform
     # Urho3d - bug fix - make it work for iOS platform
-    if (IOS)
+    if (IOS OR TVOS)
       set (SDL_POWER_UIKIT 1)
       set (SDL_POWER_UIKIT 1)
       file (GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/uikit/*.m)
       file (GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/uikit/*.m)
     else ()
     else ()
@@ -1427,6 +1427,10 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
 # Define target name
 # Define target name
 set (TARGET_NAME SDL)
 set (TARGET_NAME SDL)
 
 
+# Define source files
+file (GLOB H_FILES include/*.h)     # Adding the headers into source files list is just for easier file browsing in the IDE
+list (APPEND SOURCE_FILES ${H_FILES})
+
 # Setup target as STATIC library (as the result we never use EXTRA_LDFLAGS linker flags)
 # Setup target as STATIC library (as the result we never use EXTRA_LDFLAGS linker flags)
 setup_library ()
 setup_library ()
 
 

+ 9 - 1
Source/ThirdParty/SDL/src/video/uikit/SDL_uikitappdelegate.m

@@ -19,7 +19,7 @@
   3. This notice may not be removed or altered from any source distribution.
   3. This notice may not be removed or altered from any source distribution.
 */
 */
 
 
-// Modified by Lasse Oorni for Urho3D
+// Modified by Lasse Oorni and Yao Wei Tjong for Urho3D
 
 
 #include "../../SDL_internal.h"
 #include "../../SDL_internal.h"
 
 
@@ -113,6 +113,14 @@ const char* SDL_IOS_GetDocumentsDir()
     return documents_dir;
     return documents_dir;
 }
 }
 
 
+// Urho3D: added function
+#if TARGET_OS_TV
+unsigned SDL_TVOS_GetActiveProcessorCount()
+{
+    return [NSProcessInfo class] ? (unsigned)[[NSProcessInfo processInfo] activeProcessorCount] : 1;
+}
+#endif
+
 static void
 static void
 SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
 SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
 {
 {

+ 1 - 1
Source/ThirdParty/SQLite/CMakeLists.txt

@@ -48,7 +48,7 @@ setup_library ()
 install_header_files (DIRECTORY src/ DESTINATION ${DEST_INCLUDE_DIR}/ThirdParty/SQLite FILES_MATCHING PATTERN *.h)  # Note: the trailing slash is significant
 install_header_files (DIRECTORY src/ DESTINATION ${DEST_INCLUDE_DIR}/ThirdParty/SQLite FILES_MATCHING PATTERN *.h)  # Note: the trailing slash is significant
 
 
 # Setup additional SQLite CLI standalone target (this target can be transfered and executed on an embedded device, such as Raspberry Pi and Android)
 # Setup additional SQLite CLI standalone target (this target can be transfered and executed on an embedded device, such as Raspberry Pi and Android)
-if (NOT IOS AND NOT WEB)
+if (NOT IOS AND NOT TVOS AND NOT WEB)
     # Define target name for SQLite shell
     # Define target name for SQLite shell
     set (TARGET_NAME isql)
     set (TARGET_NAME isql)
 
 

+ 4 - 3
Source/Tools/CMakeLists.txt

@@ -41,9 +41,10 @@ if (CMAKE_CROSSCOMPILING AND URHO3D_PACKAGING)
     check_native_compiler_exist ()
     check_native_compiler_exist ()
     # When cross-compiling, build the host tool as external project
     # When cross-compiling, build the host tool as external project
     include (ExternalProject)
     include (ExternalProject)
-    if (IOS)
-        # For iOS target, ensure the host environment is cleared first; Also workaround a known CMake/Xcode generator bug which prevents it from installing binaries correctly
-        set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND} BUILD_COMMAND bash -c "sed -i '' 's/EFFECTIVE_PLATFORM_NAME//g' CMakeScripts/install_postBuildPhase.make*")
+    if (IOS OR TVOS)
+        # When cross-compiling for iOS/tvOS the host environment has been altered by xcodebuild for the said platform, the following fix is required to reset the host environment before spawning another process to configure/generate project file for external project
+        # Also workaround a known CMake/Xcode generator bug which prevents it from installing native tool binaries correctly
+        set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND} BUILD_COMMAND bash -c "sed -i '' 's/\$$\(EFFECTIVE_PLATFORM_NAME\)//g' CMakeScripts/install_postBuildPhase.make*")
     else ()
     else ()
         set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND})
         set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND})
     endif ()
     endif ()

+ 1 - 1
Source/Tools/Urho3DPlayer/CMakeLists.txt

@@ -40,7 +40,7 @@ if (URHO3D_LUA)
 endif ()
 endif ()
 
 
 # Symlink/copy helper shell scripts or batch files to invoke Urho3DPlayer
 # Symlink/copy helper shell scripts or batch files to invoke Urho3DPlayer
-if (NOT IOS AND NOT ANDROID AND NOT WEB AND NOT CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
+if (NOT IOS AND NOT TVOS AND NOT ANDROID AND NOT WEB AND NOT CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
     # Ensure the output directory exist before creating the symlinks
     # Ensure the output directory exist before creating the symlinks
     file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
     file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
     foreach (FILE Editor NinjaSnowWar PBRDemo)
     foreach (FILE Editor NinjaSnowWar PBRDemo)

+ 20 - 9
Source/Urho3D/CMakeLists.txt

@@ -129,7 +129,7 @@ else ()
         list (APPEND EXCLUDED_SOURCE_DIRS Graphics/Direct3D11)
         list (APPEND EXCLUDED_SOURCE_DIRS Graphics/Direct3D11)
     endif ()
     endif ()
 endif ()
 endif ()
-if (APPLE AND NOT IOS)
+if (APPLE AND NOT IOS AND NOT TVOS)
     set (GLOB_OBJC_PATTERN *.m)     # Should only pick up MacFileWatcher.m for MacOSX platform at the moment
     set (GLOB_OBJC_PATTERN *.m)     # Should only pick up MacFileWatcher.m for MacOSX platform at the moment
 endif ()
 endif ()
 string (REPLACE ";" "/[^;]+;" EXCLUDE_PATTERNS "${EXCLUDED_SOURCE_DIRS};")
 string (REPLACE ";" "/[^;]+;" EXCLUDE_PATTERNS "${EXCLUDED_SOURCE_DIRS};")
@@ -162,9 +162,10 @@ add_custom_command (OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/librevision.h
 if (URHO3D_BINDINGS)
 if (URHO3D_BINDINGS)
     # Build the Clang-tools as external project (even when we are not cross-compiling because it needs C++11 standard on) for auto-binding generation
     # Build the Clang-tools as external project (even when we are not cross-compiling because it needs C++11 standard on) for auto-binding generation
     include (ExternalProject)
     include (ExternalProject)
-    if (IOS)
-        # For iOS target, ensure the host environment is cleared first; Also workaround a known CMake/Xcode generator bug which prevents it from installing binaries correctly
-        set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND} BUILD_COMMAND bash -c "sed -i '' 's/EFFECTIVE_PLATFORM_NAME//g' CMakeScripts/install_postBuildPhase.make*")
+    if (IOS OR TVOS)
+        # When cross-compiling for iOS/tvOS the host environment has been altered by xcodebuild for the said platform, the following fix is required to reset the host environment before spawning another process to configure/generate project file for external project
+        # Also workaround a known CMake/Xcode generator bug which prevents it from installing native tool binaries correctly
+        set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND} BUILD_COMMAND bash -c "sed -i '' 's/\$$\(EFFECTIVE_PLATFORM_NAME\)//g' CMakeScripts/install_postBuildPhase.make*")
     else ()
     else ()
         set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND})
         set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND})
     endif ()
     endif ()
@@ -194,8 +195,8 @@ if (URHO3D_LUA)
         check_native_compiler_exist ()
         check_native_compiler_exist ()
         # When cross-compiling or using LuaJIT, build the tolua++ host tool as external project using normal Lua (there is not much point using LuaJIT for the tool building even when technically it can)
         # When cross-compiling or using LuaJIT, build the tolua++ host tool as external project using normal Lua (there is not much point using LuaJIT for the tool building even when technically it can)
         include (ExternalProject)
         include (ExternalProject)
-        if (IOS)
-            set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND} BUILD_COMMAND bash -c "sed -i '' 's/EFFECTIVE_PLATFORM_NAME//g' CMakeScripts/install_postBuildPhase.make*")
+        if (IOS OR TVOS)
+            set (ALTERNATE_COMMAND CMAKE_COMMAND /usr/bin/env -i PATH=$ENV{PATH} CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND} BUILD_COMMAND bash -c "sed -i '' 's/\$$\(EFFECTIVE_PLATFORM_NAME\)//g' CMakeScripts/install_postBuildPhase.make*")
         else ()
         else ()
             set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND})
             set (ALTERNATE_COMMAND CMAKE_COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} CI=$ENV{CI} ${CMAKE_COMMAND})
         endif ()
         endif ()
@@ -310,7 +311,7 @@ endif ()
 set_output_directories (${OUTPUT_PATH} ARCHIVE LIBRARY)
 set_output_directories (${OUTPUT_PATH} ARCHIVE LIBRARY)
 
 
 # Setup target
 # Setup target
-if (IOS)
+if (IOS OR TVOS)
     set (EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL)
     set (EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL)
 endif ()
 endif ()
 setup_library (${URHO3D_LIB_TYPE} ${EXCLUDE_FROM_ALL})
 setup_library (${URHO3D_LIB_TYPE} ${EXCLUDE_FROM_ALL})
@@ -325,13 +326,23 @@ if (NOT ANDROID AND NOT WEB)
     endif ()
     endif ()
 endif ()
 endif ()
 if (IOS)
 if (IOS)
-    # Add a custom target to build Mach-O universal binary consisting of iphoneos (universal ARM archs including 'arm64' if 64-bit is enabled) and iphonesimulator (i386 arch and also x86_64 arch if 64-bit is enabled)
+    # Add a custom target to build Mach-O universal binary consisting of both iPhoneOS and iPhoneSimulator archs
     add_custom_target (${TARGET_NAME}_universal ALL
     add_custom_target (${TARGET_NAME}_universal ALL
         COMMAND if [ '$(CONFIGURATION)' != 'Debug' ]\; then if lipo -info $<TARGET_FILE:${TARGET_NAME}> 2>/dev/null |egrep -cq 'i386.*armv7|armv7.*i386|x86_64.*arm64|arm64.*x86_64'\; then echo $<TARGET_FILE:${TARGET_NAME}> is already a Mach-O universal binary consisting of both iphoneos and iphonesimulator archs\; else mv $<TARGET_FILE:${TARGET_NAME}>{,.ori} && if lipo -info $<TARGET_FILE:${TARGET_NAME}>.ori 2>/dev/null |egrep -cq 'i386|x86_64'\; then sdk=iphoneos\; else sdk=iphonesimulator\; fi && xcodebuild -target ${TARGET_NAME} -configuration $(CONFIGURATION) -sdk $$sdk 2>&1 && mv $<TARGET_FILE:${TARGET_NAME}>{,.new} && lipo -create -output $<TARGET_FILE:${TARGET_NAME}>{,.ori,.new} && rm $<TARGET_FILE:${TARGET_NAME}>{.ori,.new}\; fi\; fi
         COMMAND if [ '$(CONFIGURATION)' != 'Debug' ]\; then if lipo -info $<TARGET_FILE:${TARGET_NAME}> 2>/dev/null |egrep -cq 'i386.*armv7|armv7.*i386|x86_64.*arm64|arm64.*x86_64'\; then echo $<TARGET_FILE:${TARGET_NAME}> is already a Mach-O universal binary consisting of both iphoneos and iphonesimulator archs\; else mv $<TARGET_FILE:${TARGET_NAME}>{,.ori} && if lipo -info $<TARGET_FILE:${TARGET_NAME}>.ori 2>/dev/null |egrep -cq 'i386|x86_64'\; then sdk=iphoneos\; else sdk=iphonesimulator\; fi && xcodebuild -target ${TARGET_NAME} -configuration $(CONFIGURATION) -sdk $$sdk 2>&1 && mv $<TARGET_FILE:${TARGET_NAME}>{,.new} && lipo -create -output $<TARGET_FILE:${TARGET_NAME}>{,.ori,.new} && rm $<TARGET_FILE:${TARGET_NAME}>{.ori,.new}\; fi\; fi
         DEPENDS ${TARGET_NAME}
         DEPENDS ${TARGET_NAME}
         WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
         WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        COMMENT "Creating Mach-O universal binary library consisting of both iphoneos and iphonesimulator archs")
+        COMMENT "Creating Mach-O universal binary library consisting of both iPhoneOS and iPhoneSimulator archs")
+    install (FILES $<TARGET_FILE:${TARGET_NAME}> DESTINATION ${DEST_LIBRARY_DIR})
+elseif (TVOS)
+    # Add a custom target to build Mach-O universal binary consisting of both AppleTVOS and AppleTVSimulator archs
+    add_custom_target (${TARGET_NAME}_universal ALL
+        COMMAND if [ '$(CONFIGURATION)' != 'Debug' ]\; then if lipo -info $<TARGET_FILE:${TARGET_NAME}> 2>/dev/null |egrep -cq 'x86_64.*arm64|arm64.*x86_64'\; then echo $<TARGET_FILE:${TARGET_NAME}> is already a Mach-O universal binary consisting of both AppleTVOS and AppleTVSimulator archs\; else mv $<TARGET_FILE:${TARGET_NAME}>{,.ori} && if lipo -info $<TARGET_FILE:${TARGET_NAME}>.ori 2>/dev/null |grep -cq x86_64\; then sdk=appletvos\; else sdk=appletvsimulator\; fi && xcodebuild -target ${TARGET_NAME} -configuration $(CONFIGURATION) -sdk $$sdk 2>&1 && mv $<TARGET_FILE:${TARGET_NAME}>{,.new} && lipo -create -output $<TARGET_FILE:${TARGET_NAME}>{,.ori,.new} && rm $<TARGET_FILE:${TARGET_NAME}>{.ori,.new}\; fi\; fi
+        DEPENDS ${TARGET_NAME}
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        COMMENT "Creating Mach-O universal binary library consisting of both AppleTVOS and AppleTVSimulator archs")
     install (FILES $<TARGET_FILE:${TARGET_NAME}> DESTINATION ${DEST_LIBRARY_DIR})
     install (FILES $<TARGET_FILE:${TARGET_NAME}> DESTINATION ${DEST_LIBRARY_DIR})
+    # TODO: Temporary workaround as CMake does not recognize AppleTV platform yet
+    add_dependencies (${TARGET_NAME} APPLETV_POST_CMAKE_FIX)
 elseif (EMSCRIPTEN)
 elseif (EMSCRIPTEN)
     install (TARGETS ${TARGET_NAME} LIBRARY DESTINATION ${DEST_LIBRARY_DIR} PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ARCHIVE DESTINATION ${DEST_LIBRARY_DIR})
     install (TARGETS ${TARGET_NAME} LIBRARY DESTINATION ${DEST_LIBRARY_DIR} PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ARCHIVE DESTINATION ${DEST_LIBRARY_DIR})
 else ()
 else ()

+ 2 - 2
Source/Urho3D/Core/Main.h

@@ -67,8 +67,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, in
     Urho3D::ParseArguments(GetCommandLineW()); \
     Urho3D::ParseArguments(GetCommandLineW()); \
     return function; \
     return function; \
 }
 }
-// Android or iOS: use SDL_main
-#elif defined(__ANDROID__) || defined(IOS)
+// Android or iOS or tvOS: use SDL_main
+#elif defined(__ANDROID__) || defined(IOS) || defined(TVOS)
 #define URHO3D_DEFINE_MAIN(function) \
 #define URHO3D_DEFINE_MAIN(function) \
 extern "C" int SDL_main(int argc, char** argv); \
 extern "C" int SDL_main(int argc, char** argv); \
 int SDL_main(int argc, char** argv) \
 int SDL_main(int argc, char** argv) \

+ 25 - 10
Source/Urho3D/Core/ProcessUtils.cpp

@@ -34,8 +34,9 @@
 #endif
 #endif
 
 
 #if defined(IOS)
 #if defined(IOS)
-#include "../Math/MathDefs.h"
 #include <mach/mach_host.h>
 #include <mach/mach_host.h>
+#elif defined(TVOS)
+extern "C" unsigned SDL_TVOS_GetActiveProcessorCount();
 #elif !defined(__linux__) && !defined(__EMSCRIPTEN__)
 #elif !defined(__linux__) && !defined(__EMSCRIPTEN__)
 #include <LibCpuId/libcpuid.h>
 #include <LibCpuId/libcpuid.h>
 #endif
 #endif
@@ -158,7 +159,7 @@ static void GetCPUData(struct CpuCoreCount* data)
     }
     }
 }
 }
 
 
-#elif !defined(__EMSCRIPTEN__)
+#elif !defined(__EMSCRIPTEN__) && !defined(TVOS)
 static void GetCPUData(struct cpu_id_t* data)
 static void GetCPUData(struct cpu_id_t* data)
 {
 {
     if (cpu_identify(0, data) < 0)
     if (cpu_identify(0, data) < 0)
@@ -215,7 +216,7 @@ void OpenConsoleWindow()
 
 
 void PrintUnicode(const String& str, bool error)
 void PrintUnicode(const String& str, bool error)
 {
 {
-#if !defined(__ANDROID__) && !defined(IOS)
+#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
 #ifdef _WIN32
 #ifdef _WIN32
     // If the output stream has been redirected, use fprintf instead of WriteConsoleW,
     // If the output stream has been redirected, use fprintf instead of WriteConsoleW,
     // though it means that proper Unicode output will not work
     // though it means that proper Unicode output will not work
@@ -244,7 +245,7 @@ void PrintUnicodeLine(const String& str, bool error)
 
 
 void PrintLine(const String& str, bool error)
 void PrintLine(const String& str, bool error)
 {
 {
-#if !defined(__ANDROID__) && !defined(IOS)
+#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
     fprintf(error ? stderr : stdout, "%s\n", str.CString());
     fprintf(error ? stderr : stdout, "%s\n", str.CString());
 #endif
 #endif
 }
 }
@@ -382,7 +383,7 @@ String GetConsoleInput()
             }
             }
         }
         }
     }
     }
-#elif !defined(__ANDROID__) && !defined(IOS)
+#elif !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
     int flags = fcntl(STDIN_FILENO, F_GETFL);
     int flags = fcntl(STDIN_FILENO, F_GETFL);
     fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
     fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
     for (;;)
     for (;;)
@@ -405,10 +406,12 @@ String GetPlatform()
     return "Android";
     return "Android";
 #elif defined(IOS)
 #elif defined(IOS)
     return "iOS";
     return "iOS";
+#elif defined(TVOS)
+    return "tvOS";
+#elif defined(__APPLE__)
+    return "macOS";
 #elif defined(_WIN32)
 #elif defined(_WIN32)
     return "Windows";
     return "Windows";
-#elif defined(__APPLE__)
-    return "Mac OS X";
 #elif defined(RPI)
 #elif defined(RPI)
     return "Raspberry Pi";
     return "Raspberry Pi";
 #elif defined(__EMSCRIPTEN__)
 #elif defined(__EMSCRIPTEN__)
@@ -425,12 +428,18 @@ unsigned GetNumPhysicalCPUs()
 #if defined(IOS)
 #if defined(IOS)
     host_basic_info_data_t data;
     host_basic_info_data_t data;
     GetCPUData(&data);
     GetCPUData(&data);
-#if defined(TARGET_IPHONE_SIMULATOR)
+#if defined(TARGET_OS_SIMULATOR)
     // Hardcoded to dual-core on simulator mode even if the host has more
     // Hardcoded to dual-core on simulator mode even if the host has more
     return Min(2, data.physical_cpu);
     return Min(2, data.physical_cpu);
 #else
 #else
     return data.physical_cpu;
     return data.physical_cpu;
 #endif
 #endif
+#elif defined(TVOS)
+#if defined(TARGET_OS_SIMULATOR)
+    return Min(2, SDL_TVOS_GetActiveProcessorCount());
+#else
+    return SDL_TVOS_GetActiveProcessorCount();
+#endif
 #elif defined(__linux__)
 #elif defined(__linux__)
     struct CpuCoreCount data;
     struct CpuCoreCount data;
     GetCPUData(&data);
     GetCPUData(&data);
@@ -453,11 +462,17 @@ unsigned GetNumLogicalCPUs()
 #if defined(IOS)
 #if defined(IOS)
     host_basic_info_data_t data;
     host_basic_info_data_t data;
     GetCPUData(&data);
     GetCPUData(&data);
-#if defined(TARGET_IPHONE_SIMULATOR)
+#if defined(TARGET_OS_SIMULATOR)
     return Min(2, data.logical_cpu);
     return Min(2, data.logical_cpu);
 #else
 #else
     return data.logical_cpu;
     return data.logical_cpu;
 #endif
 #endif
+#elif defined(TVOS)
+#if defined(TARGET_OS_SIMULATOR)
+    return Min(2, SDL_TVOS_GetActiveProcessorCount());
+#else
+    return SDL_TVOS_GetActiveProcessorCount();
+#endif
 #elif defined(__linux__)
 #elif defined(__linux__)
     struct CpuCoreCount data;
     struct CpuCoreCount data;
     GetCPUData(&data);
     GetCPUData(&data);
@@ -532,7 +547,7 @@ String GetLoginName()
     DWORD len = UNLEN + 1;
     DWORD len = UNLEN + 1;
     if (GetUserName(name, &len))
     if (GetUserName(name, &len))
         return name;
         return name;
-#elif defined(__APPLE__) && !defined(IOS)
+#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
     SCDynamicStoreRef s = SCDynamicStoreCreate(NULL, CFSTR("GetConsoleUser"), NULL, NULL);
     SCDynamicStoreRef s = SCDynamicStoreCreate(NULL, CFSTR("GetConsoleUser"), NULL, NULL);
     if (s != NULL)
     if (s != NULL)
     {
     {

+ 6 - 6
Source/Urho3D/Engine/Application.cpp

@@ -26,7 +26,7 @@
 #include "../IO/IOEvents.h"
 #include "../IO/IOEvents.h"
 #include "../IO/Log.h"
 #include "../IO/Log.h"
 
 
-#ifdef IOS
+#if defined(IOS) || defined(TVOS)
 #include "../Graphics/Graphics.h"
 #include "../Graphics/Graphics.h"
 #include <SDL/SDL.h>
 #include <SDL/SDL.h>
 #endif
 #endif
@@ -36,7 +36,7 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-#if defined(IOS) || defined(__EMSCRIPTEN__)
+#if defined(IOS) || defined(TVOS) || defined(__EMSCRIPTEN__)
 // Code for supporting SDL_iPhoneSetAnimationCallback() and emscripten_set_main_loop_arg()
 // Code for supporting SDL_iPhoneSetAnimationCallback() and emscripten_set_main_loop_arg()
 #if defined(__EMSCRIPTEN__)
 #if defined(__EMSCRIPTEN__)
 #include <emscripten/emscripten.h>
 #include <emscripten/emscripten.h>
@@ -80,16 +80,16 @@ int Application::Run()
         if (exitCode_)
         if (exitCode_)
             return exitCode_;
             return exitCode_;
 
 
-        // Platforms other than iOS and Emscripten run a blocking main loop
-#if !defined(IOS) && !defined(__EMSCRIPTEN__)
+        // Platforms other than iOS/tvOS and Emscripten run a blocking main loop
+#if !defined(IOS) && !defined(TVOS) && !defined(__EMSCRIPTEN__)
         while (!engine_->IsExiting())
         while (!engine_->IsExiting())
             engine_->RunFrame();
             engine_->RunFrame();
 
 
         Stop();
         Stop();
-        // iOS will setup a timer for running animation frames so eg. Game Center can run. In this case we do not
+        // iOS/tvOS will setup a timer for running animation frames so eg. Game Center can run. In this case we do not
         // support calling the Stop() function, as the application will never stop manually
         // support calling the Stop() function, as the application will never stop manually
 #else
 #else
-#if defined(IOS)
+#if defined(IOS) || defined(TVOS)
         SDL_iPhoneSetAnimationCallback(GetSubsystem<Graphics>()->GetWindow(), 1, &RunFrame, engine_);
         SDL_iPhoneSetAnimationCallback(GetSubsystem<Graphics>()->GetWindow(), 1, &RunFrame, engine_);
 #elif defined(__EMSCRIPTEN__)
 #elif defined(__EMSCRIPTEN__)
         emscripten_set_main_loop_arg(RunFrame, engine_, 0, 1);
         emscripten_set_main_loop_arg(RunFrame, engine_, 0, 1);

+ 2 - 2
Source/Urho3D/Engine/Application.h

@@ -69,7 +69,7 @@ protected:
 };
 };
 
 
 // Macro for defining a main function which creates a Context and the application, then runs it
 // Macro for defining a main function which creates a Context and the application, then runs it
-#ifndef IOS
+#if !defined(IOS) && !defined(TVOS)
 #define URHO3D_DEFINE_APPLICATION_MAIN(className) \
 #define URHO3D_DEFINE_APPLICATION_MAIN(className) \
 int RunApplication() \
 int RunApplication() \
 { \
 { \
@@ -79,7 +79,7 @@ int RunApplication() \
 } \
 } \
 URHO3D_DEFINE_MAIN(RunApplication());
 URHO3D_DEFINE_MAIN(RunApplication());
 #else
 #else
-// On iOS we will let this function exit, so do not hold the context and application in SharedPtr's
+// On iOS/tvOS we will let this function exit, so do not hold the context and application in SharedPtr's
 #define URHO3D_DEFINE_APPLICATION_MAIN(className) \
 #define URHO3D_DEFINE_APPLICATION_MAIN(className) \
 int RunApplication() \
 int RunApplication() \
 { \
 { \

+ 4 - 4
Source/Urho3D/Engine/Engine.cpp

@@ -97,7 +97,7 @@ Engine::Engine(Context* context) :
     timeStep_(0.0f),
     timeStep_(0.0f),
     timeStepSmoothing_(2),
     timeStepSmoothing_(2),
     minFps_(10),
     minFps_(10),
-#if defined(IOS) || defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__)
+#if defined(IOS) || defined(TVOS) || defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__)
     maxFps_(60),
     maxFps_(60),
     maxInactiveFps_(10),
     maxInactiveFps_(10),
     pauseMinimized_(true),
     pauseMinimized_(true),
@@ -585,7 +585,7 @@ void Engine::SetPauseMinimized(bool enable)
 void Engine::SetAutoExit(bool enable)
 void Engine::SetAutoExit(bool enable)
 {
 {
     // On mobile platforms exit is mandatory if requested by the platform itself and should not be attempted to be disabled
     // On mobile platforms exit is mandatory if requested by the platform itself and should not be attempted to be disabled
-#if defined(__ANDROID__) || defined(IOS)
+#if defined(__ANDROID__) || defined(IOS) || defined(TVOS)
     enable = true;
     enable = true;
 #endif
 #endif
     autoExit_ = enable;
     autoExit_ = enable;
@@ -598,8 +598,8 @@ void Engine::SetNextTimeStep(float seconds)
 
 
 void Engine::Exit()
 void Engine::Exit()
 {
 {
-#if defined(IOS)
-    // On iOS it's not legal for the application to exit on its own, instead it will be minimized with the home key
+#if defined(IOS) || defined(TVOS)
+    // On iOS/tvOS it's not legal for the application to exit on its own, instead it will be minimized with the home key
 #else
 #else
     DoExit();
     DoExit();
 #endif
 #endif

+ 1 - 1
Source/Urho3D/Graphics/Graphics.cpp

@@ -208,7 +208,7 @@ PODVector<IntVector3> Graphics::GetResolutions(int monitor) const
 
 
 IntVector2 Graphics::GetDesktopResolution(int monitor) const
 IntVector2 Graphics::GetDesktopResolution(int monitor) const
 {
 {
-#if !defined(__ANDROID__) && !defined(IOS)
+#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
     SDL_DisplayMode mode;
     SDL_DisplayMode mode;
     SDL_GetDesktopDisplayMode(monitor, &mode);
     SDL_GetDesktopDisplayMode(monitor, &mode);
     return IntVector2(mode.w, mode.h);
     return IntVector2(mode.w, mode.h);

+ 1 - 1
Source/Urho3D/Graphics/GraphicsDefs.h

@@ -31,7 +31,7 @@ namespace Urho3D
 class Vector3;
 class Vector3;
 
 
 /// Graphics capability support level. Web platform (Emscripten) also uses OpenGL ES, but is considered a desktop platform capability-wise
 /// Graphics capability support level. Web platform (Emscripten) also uses OpenGL ES, but is considered a desktop platform capability-wise
-#if defined(IOS) || defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__)
+#if defined(IOS) || defined(TVOS) || defined(__ANDROID__) || defined(__arm__) || defined(__aarch64__)
 #define MOBILE_GRAPHICS
 #define MOBILE_GRAPHICS
 #else
 #else
 #define DESKTOP_GRAPHICS
 #define DESKTOP_GRAPHICS

+ 9 - 10
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -496,8 +496,8 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     // Set vsync
     // Set vsync
     SDL_GL_SetSwapInterval(vsync ? 1 : 0);
     SDL_GL_SetSwapInterval(vsync ? 1 : 0);
 
 
-    // Store the system FBO on IOS now
-#ifdef IOS
+    // Store the system FBO on iOS/tvOS now
+#if defined(IOS) || defined(TVOS)
     glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFBO_);
     glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFBO_);
 #endif
 #endif
 
 
@@ -2083,8 +2083,8 @@ bool Graphics::GetDither() const
 
 
 bool Graphics::IsDeviceLost() const
 bool Graphics::IsDeviceLost() const
 {
 {
-    // On iOS treat window minimization as device loss, as it is forbidden to access OpenGL when minimized
-#ifdef IOS
+    // On iOS and tvOS treat window minimization as device loss, as it is forbidden to access OpenGL when minimized
+#if defined(IOS) || defined(TVOS)
     if (window_ && (SDL_GetWindowFlags(window_) & SDL_WINDOW_MINIMIZED) != 0)
     if (window_ && (SDL_GetWindowFlags(window_) & SDL_WINDOW_MINIMIZED) != 0)
         return true;
         return true;
 #endif
 #endif
@@ -2414,7 +2414,7 @@ void Graphics::Release(bool clearGPUObjects, bool closeWindow)
     impl_->depthTextures_.Clear();
     impl_->depthTextures_.Clear();
 
 
     // End fullscreen mode first to counteract transition and getting stuck problems on OS X
     // End fullscreen mode first to counteract transition and getting stuck problems on OS X
-#if defined(__APPLE__) && !defined(IOS)
+#if defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
     if (closeWindow && fullscreen_ && !externalWindow_)
     if (closeWindow && fullscreen_ && !externalWindow_)
         SDL_SetWindowFullscreen(window_, 0);
         SDL_SetWindowFullscreen(window_, 0);
 #endif
 #endif
@@ -2475,7 +2475,7 @@ void Graphics::Restore()
         }
         }
 #endif
 #endif
 
 
-#ifdef IOS
+#if defined(IOS) || defined(TVOS)
         glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFBO_);
         glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&impl_->systemFBO_);
 #endif
 #endif
 
 
@@ -2794,7 +2794,7 @@ void Graphics::CheckFeatureSupport()
     if (numSupportedRTs >= 4)
     if (numSupportedRTs >= 4)
         deferredSupport_ = true;
         deferredSupport_ = true;
 
 
-#if defined(__APPLE__) && !defined(IOS)
+#if defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
     // On OS X check for an Intel driver and use shadow map RGBA dummy color textures, because mixing
     // On OS X check for an Intel driver and use shadow map RGBA dummy color textures, because mixing
     // depth-only FBO rendering and backbuffer rendering will bug, resulting in a black screen in full
     // depth-only FBO rendering and backbuffer rendering will bug, resulting in a black screen in full
     // screen mode, and incomplete shadow maps in windowed mode
     // screen mode, and incomplete shadow maps in windowed mode
@@ -2834,9 +2834,8 @@ void Graphics::CheckFeatureSupport()
     }
     }
     else
     else
     {
     {
-        #ifdef IOS
-        // iOS hack: depth renderbuffer seems to fail, so use depth textures for everything
-        // if supported
+#if defined(IOS) || defined(TVOS)
+        // iOS hack: depth renderbuffer seems to fail, so use depth textures for everything if supported
         glesDepthStencilFormat = GL_DEPTH_COMPONENT;
         glesDepthStencilFormat = GL_DEPTH_COMPONENT;
 #endif
 #endif
         shadowMapFormat_ = GL_DEPTH_COMPONENT;
         shadowMapFormat_ = GL_DEPTH_COMPONENT;

+ 2 - 2
Source/Urho3D/Graphics/OpenGL/OGLGraphicsImpl.h

@@ -29,7 +29,7 @@
 #include "../../Graphics/Texture2D.h"
 #include "../../Graphics/Texture2D.h"
 #include "../../Math/Color.h"
 #include "../../Math/Color.h"
 
 
-#if defined(IOS)
+#if defined(IOS) || defined(TVOS)
 #include <OpenGLES/ES2/gl.h>
 #include <OpenGLES/ES2/gl.h>
 #include <OpenGLES/ES2/glext.h>
 #include <OpenGLES/ES2/glext.h>
 #elif defined(__ANDROID__) || defined (__arm__) || defined(__aarch64__) || defined (__EMSCRIPTEN__)
 #elif defined(__ANDROID__) || defined (__arm__) || defined(__aarch64__) || defined (__EMSCRIPTEN__)
@@ -114,7 +114,7 @@ public:
 private:
 private:
     /// SDL OpenGL context.
     /// SDL OpenGL context.
     SDL_GLContext context_;
     SDL_GLContext context_;
-    /// IOS system framebuffer handle.
+    /// iOS/tvOS system framebuffer handle.
     unsigned systemFBO_;
     unsigned systemFBO_;
     /// Active texture unit.
     /// Active texture unit.
     unsigned activeTexture_;
     unsigned activeTexture_;

+ 11 - 3
Source/Urho3D/IO/FileSystem.cpp

@@ -72,7 +72,7 @@ extern "C"
 const char* SDL_Android_GetFilesDir();
 const char* SDL_Android_GetFilesDir();
 char** SDL_Android_GetFileList(const char* path, int* count);
 char** SDL_Android_GetFileList(const char* path, int* count);
 void SDL_Android_FreeFileList(char*** array, int* count);
 void SDL_Android_FreeFileList(char*** array, int* count);
-#elif IOS
+#elif defined(IOS) || defined(TVOS)
 const char* SDL_IOS_GetResourceDir();
 const char* SDL_IOS_GetResourceDir();
 const char* SDL_IOS_GetDocumentsDir();
 const char* SDL_IOS_GetDocumentsDir();
 #endif
 #endif
@@ -85,6 +85,9 @@ namespace Urho3D
 
 
 int DoSystemCommand(const String& commandLine, bool redirectToLog, Context* context)
 int DoSystemCommand(const String& commandLine, bool redirectToLog, Context* context)
 {
 {
+#ifdef TVOS
+    return -1;
+#else
 #if !defined(__EMSCRIPTEN__) && !defined(MINI_URHO)
 #if !defined(__EMSCRIPTEN__) && !defined(MINI_URHO)
     if (!redirectToLog)
     if (!redirectToLog)
 #endif
 #endif
@@ -135,10 +138,14 @@ int DoSystemCommand(const String& commandLine, bool redirectToLog, Context* cont
 
 
     return exitCode;
     return exitCode;
 #endif
 #endif
+#endif
 }
 }
 
 
 int DoSystemRun(const String& fileName, const Vector<String>& arguments)
 int DoSystemRun(const String& fileName, const Vector<String>& arguments)
 {
 {
+#ifdef TVOS
+    return -1;
+#else
     String fixedFileName = GetNativePath(fileName);
     String fixedFileName = GetNativePath(fileName);
 
 
 #ifdef _WIN32
 #ifdef _WIN32
@@ -189,6 +196,7 @@ int DoSystemRun(const String& fileName, const Vector<String>& arguments)
     else
     else
         return -1;
         return -1;
 #endif
 #endif
+#endif
 }
 }
 
 
 /// Base class for async execution requests.
 /// Base class for async execution requests.
@@ -690,7 +698,7 @@ String FileSystem::GetProgramDir() const
     // This is an internal directory specifier pointing to the assets in the .apk
     // This is an internal directory specifier pointing to the assets in the .apk
     // Files from this directory will be opened using special handling
     // Files from this directory will be opened using special handling
     return APK;
     return APK;
-#elif defined(IOS)
+#elif defined(IOS) || defined(TVOS)
     return AddTrailingSlash(SDL_IOS_GetResourceDir());
     return AddTrailingSlash(SDL_IOS_GetResourceDir());
 #elif defined(_WIN32)
 #elif defined(_WIN32)
     wchar_t exeName[MAX_PATH];
     wchar_t exeName[MAX_PATH];
@@ -719,7 +727,7 @@ String FileSystem::GetUserDocumentsDir() const
 {
 {
 #if defined(__ANDROID__)
 #if defined(__ANDROID__)
     return AddTrailingSlash(SDL_Android_GetFilesDir());
     return AddTrailingSlash(SDL_Android_GetFilesDir());
-#elif defined(IOS)
+#elif defined(IOS) || defined(TVOS)
     return AddTrailingSlash(SDL_IOS_GetDocumentsDir());
     return AddTrailingSlash(SDL_IOS_GetDocumentsDir());
 #elif defined(_WIN32)
 #elif defined(_WIN32)
     wchar_t pathName[MAX_PATH];
     wchar_t pathName[MAX_PATH];

+ 6 - 6
Source/Urho3D/IO/FileWatcher.cpp

@@ -36,7 +36,7 @@ extern "C"
 // Need read/close for inotify
 // Need read/close for inotify
 #include "unistd.h"
 #include "unistd.h"
 }
 }
-#elif defined(__APPLE__) && !defined(IOS)
+#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
 extern "C"
 extern "C"
 {
 {
 #include "../IO/MacFileWatcher.h"
 #include "../IO/MacFileWatcher.h"
@@ -58,7 +58,7 @@ FileWatcher::FileWatcher(Context* context) :
 #ifdef URHO3D_FILEWATCHER
 #ifdef URHO3D_FILEWATCHER
 #ifdef __linux__
 #ifdef __linux__
     watchHandle_ = inotify_init();
     watchHandle_ = inotify_init();
-#elif defined(__APPLE__) && !defined(IOS)
+#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
     supported_ = IsFileWatcherSupported();
     supported_ = IsFileWatcherSupported();
 #endif
 #endif
 #endif
 #endif
@@ -156,7 +156,7 @@ bool FileWatcher::StartWatching(const String& pathName, bool watchSubDirs)
         URHO3D_LOGDEBUG("Started watching path " + pathName);
         URHO3D_LOGDEBUG("Started watching path " + pathName);
         return true;
         return true;
     }
     }
-#elif defined(__APPLE__) && !defined(IOS)
+#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
     if (!supported_)
     if (!supported_)
     {
     {
         URHO3D_LOGERROR("Individual file watching not supported by this OS version, can not start watching path " + pathName);
         URHO3D_LOGERROR("Individual file watching not supported by this OS version, can not start watching path " + pathName);
@@ -205,7 +205,7 @@ void FileWatcher::StopWatching()
             fileSystem_->Delete(dummyFileName);
             fileSystem_->Delete(dummyFileName);
 #endif
 #endif
 
 
-#if defined(__APPLE__) && !defined(IOS)
+#if defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
         // Our implementation of file watcher requires the thread to be stopped first before closing the watcher
         // Our implementation of file watcher requires the thread to be stopped first before closing the watcher
         Stop();
         Stop();
 #endif
 #endif
@@ -216,7 +216,7 @@ void FileWatcher::StopWatching()
         for (HashMap<int, String>::Iterator i = dirHandle_.Begin(); i != dirHandle_.End(); ++i)
         for (HashMap<int, String>::Iterator i = dirHandle_.Begin(); i != dirHandle_.End(); ++i)
             inotify_rm_watch(watchHandle_, i->first_);
             inotify_rm_watch(watchHandle_, i->first_);
         dirHandle_.Clear();
         dirHandle_.Clear();
-#elif defined(__APPLE__) && !defined(IOS)
+#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
         CloseFileWatcher(watcher_);
         CloseFileWatcher(watcher_);
 #endif
 #endif
 
 
@@ -306,7 +306,7 @@ void FileWatcher::ThreadFunction()
             i += sizeof(inotify_event) + event->len;
             i += sizeof(inotify_event) + event->len;
         }
         }
     }
     }
-#elif defined(__APPLE__) && !defined(IOS)
+#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
     while (shouldRun_)
     while (shouldRun_)
     {
     {
         Time::Sleep(100);
         Time::Sleep(100);

+ 1 - 1
Source/Urho3D/IO/FileWatcher.h

@@ -90,7 +90,7 @@ private:
     /// Linux inotify needs a handle.
     /// Linux inotify needs a handle.
     int watchHandle_;
     int watchHandle_;
 
 
-#elif defined(__APPLE__) && !defined(IOS)
+#elif defined(__APPLE__) && !defined(IOS) && !defined(TVOS)
     
     
     /// Flag indicating whether the running OS supports individual file watching.
     /// Flag indicating whether the running OS supports individual file watching.
     bool supported_;
     bool supported_;

+ 5 - 5
Source/Urho3D/IO/Log.cpp

@@ -36,7 +36,7 @@
 #ifdef __ANDROID__
 #ifdef __ANDROID__
 #include <android/log.h>
 #include <android/log.h>
 #endif
 #endif
-#ifdef IOS
+#if defined(IOS) || defined(TVOS)
 extern "C" void SDL_IOS_LogMessage(const char* message);
 extern "C" void SDL_IOS_LogMessage(const char* message);
 #endif
 #endif
 
 
@@ -80,7 +80,7 @@ Log::~Log()
 
 
 void Log::Open(const String& fileName)
 void Log::Open(const String& fileName)
 {
 {
-#if !defined(__ANDROID__) && !defined(IOS)
+#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
     if (fileName.Empty())
     if (fileName.Empty())
         return;
         return;
     if (logFile_ && logFile_->IsOpen())
     if (logFile_ && logFile_->IsOpen())
@@ -104,7 +104,7 @@ void Log::Open(const String& fileName)
 
 
 void Log::Close()
 void Log::Close()
 {
 {
-#if !defined(__ANDROID__) && !defined(IOS)
+#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
     if (logFile_ && logFile_->IsOpen())
     if (logFile_ && logFile_->IsOpen())
     {
     {
         logFile_->Close();
         logFile_->Close();
@@ -173,7 +173,7 @@ void Log::Write(int level, const String& message)
 #if defined(__ANDROID__)
 #if defined(__ANDROID__)
     int androidLevel = ANDROID_LOG_DEBUG + level;
     int androidLevel = ANDROID_LOG_DEBUG + level;
     __android_log_print(androidLevel, "Urho3D", "%s", message.CString());
     __android_log_print(androidLevel, "Urho3D", "%s", message.CString());
-#elif defined(IOS)
+#elif defined(IOS) || defined(TVOS)
     SDL_IOS_LogMessage(message.CString());
     SDL_IOS_LogMessage(message.CString());
 #else
 #else
     if (logInstance->quiet_)
     if (logInstance->quiet_)
@@ -232,7 +232,7 @@ void Log::WriteRaw(const String& message, bool error)
     }
     }
     else
     else
         __android_log_print(error ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "Urho3D", "%s", message.CString());
         __android_log_print(error ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "Urho3D", "%s", message.CString());
-#elif defined(IOS)
+#elif defined(IOS) || defined(TVOS)
     SDL_IOS_LogMessage(message.CString());
     SDL_IOS_LogMessage(message.CString());
 #else
 #else
     if (logInstance->quiet_)
     if (logInstance->quiet_)

+ 3 - 4
Source/Urho3D/Input/Input.cpp

@@ -49,8 +49,7 @@
 extern "C" int SDL_AddTouch(SDL_TouchID touchID, const char* name);
 extern "C" int SDL_AddTouch(SDL_TouchID touchID, const char* name);
 
 
 // Use a "click inside window to focus" mechanism on desktop platforms when the mouse cursor is hidden
 // Use a "click inside window to focus" mechanism on desktop platforms when the mouse cursor is hidden
-// TODO: For now, in this particular case only, treat all the ARM on Linux as "desktop" (e.g. RPI, odroid, etc), revisit this again when we support "mobile" ARM on Linux
-#if defined(_WIN32) || (defined(__APPLE__) && !defined(IOS)) || (defined(__linux__) && !defined(__ANDROID__))
+#if defined(_WIN32) || (defined(__APPLE__) && !defined(IOS) && !defined(TVOS)) || (defined(__linux__) && !defined(__ANDROID__))
 #define REQUIRE_CLICK_TO_FOCUS
 #define REQUIRE_CLICK_TO_FOCUS
 #endif
 #endif
 
 
@@ -1158,7 +1157,7 @@ void Input::SetScreenKeyboardVisible(bool enable)
 
 
 void Input::SetTouchEmulation(bool enable)
 void Input::SetTouchEmulation(bool enable)
 {
 {
-#if !defined(__ANDROID__) && !defined(IOS)
+#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
     if (enable != touchEmulation_)
     if (enable != touchEmulation_)
     {
     {
         if (enable)
         if (enable)
@@ -2305,7 +2304,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
 
             case SDL_WINDOWEVENT_MAXIMIZED:
             case SDL_WINDOWEVENT_MAXIMIZED:
             case SDL_WINDOWEVENT_RESTORED:
             case SDL_WINDOWEVENT_RESTORED:
-#if defined(IOS) || defined (__ANDROID__)
+#if defined(IOS) || defined(TVOS) || defined (__ANDROID__)
                 // On iOS we never lose the GL context, but may have done GPU object changes that could not be applied yet. Apply them now
                 // On iOS we never lose the GL context, but may have done GPU object changes that could not be applied yet. Apply them now
                 // On Android the old GL context may be lost already, restore GPU objects to the new GL context
                 // On Android the old GL context may be lost already, restore GPU objects to the new GL context
                 graphics_->Restore();
                 graphics_->Restore();

+ 2 - 2
Source/Urho3D/UI/Cursor.cpp

@@ -53,7 +53,7 @@ static const char* shapeNames[] =
 };
 };
 
 
 /// OS cursor shape lookup table matching cursor shape enumeration
 /// OS cursor shape lookup table matching cursor shape enumeration
-#if !defined(__ANDROID__) && !defined(IOS)
+#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
 static const int osCursorLookup[CS_MAX_SHAPES] =
 static const int osCursorLookup[CS_MAX_SHAPES] =
 {
 {
     SDL_SYSTEM_CURSOR_ARROW,    // CS_NORMAL
     SDL_SYSTEM_CURSOR_ARROW,    // CS_NORMAL
@@ -256,7 +256,7 @@ VariantVector Cursor::GetShapesAttr() const
 void Cursor::ApplyOSCursorShape()
 void Cursor::ApplyOSCursorShape()
 {
 {
     // Mobile platforms do not support applying OS cursor shapes: comment out to avoid log error messages
     // Mobile platforms do not support applying OS cursor shapes: comment out to avoid log error messages
-#if !defined(__ANDROID__) && !defined(IOS)
+#if !defined(__ANDROID__) && !defined(IOS) && !defined(TVOS)
     if (!osShapeDirty_ || !GetSubsystem<Input>()->IsMouseVisible() || GetSubsystem<UI>()->GetCursor() != this)
     if (!osShapeDirty_ || !GetSubsystem<Input>()->IsMouseVisible() || GetSubsystem<UI>()->GetCursor() != this)
         return;
         return;
 
 

+ 1 - 1
Source/Urho3D/UI/UI.cpp

@@ -99,7 +99,7 @@ UI::UI(Context* context) :
     nonFocusedMouseWheel_(true),     // Default Mac OS X and Linux behaviour
     nonFocusedMouseWheel_(true),     // Default Mac OS X and Linux behaviour
 #endif
 #endif
     useSystemClipboard_(false),
     useSystemClipboard_(false),
-#if defined(__ANDROID__) || defined(IOS)
+#if defined(__ANDROID__) || defined(IOS) || defined(TVOS)
     useScreenKeyboard_(true),
     useScreenKeyboard_(true),
 #else
 #else
     useScreenKeyboard_(false),
     useScreenKeyboard_(false),

+ 3 - 0
cmake_generic.sh

@@ -47,6 +47,9 @@ for a in $@; do
         -DIOS=1)
         -DIOS=1)
             IOS=1
             IOS=1
             ;;
             ;;
+        -DTVOS=1)
+            TVOS=1
+            ;;
         -DANDROID=1)
         -DANDROID=1)
             ANDROID=1 && OPTS="-DCMAKE_TOOLCHAIN_FILE=$TOOLCHAINS/Android.cmake"
             ANDROID=1 && OPTS="-DCMAKE_TOOLCHAIN_FILE=$TOOLCHAINS/Android.cmake"
             ;;
             ;;

+ 26 - 0
cmake_tvos.sh

@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2008-2016 the Urho3D project.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+$(dirname $0)/cmake_generic.sh "$@" -G Xcode -DTVOS=1
+
+# vi: set ts=4 sw=4 expandtab: