diff --git a/Apps/CMakeLists.txt b/Apps/CMakeLists.txt index 0e7ade406..d4013e0e7 100644 --- a/Apps/CMakeLists.txt +++ b/Apps/CMakeLists.txt @@ -2,7 +2,7 @@ if(NOT ANDROID) add_subdirectory(Playground) endif() -if((WIN32 AND NOT WINDOWS_STORE) OR (APPLE AND NOT IOS) OR (UNIX AND NOT ANDROID)) +if((WIN32 AND NOT WINDOWS_STORE) OR (APPLE AND NOT IOS AND NOT VISIONOS) OR (UNIX AND NOT ANDROID)) add_subdirectory(UnitTests) endif() diff --git a/Apps/Playground/AppleShared/GestureRecognizer.swift b/Apps/Playground/AppleShared/GestureRecognizer.swift new file mode 100644 index 000000000..f071aa7ad --- /dev/null +++ b/Apps/Playground/AppleShared/GestureRecognizer.swift @@ -0,0 +1,58 @@ +import UIKit + +/** +* A very simple gesture recognizer. All that it does is to emulate the functionality found in other platforms +*/ +class UIBabylonGestureRecognizer: UIGestureRecognizer { + // Callback for touch down events + private let _onTouchDown: (Int32, Int32, Int32)->Void + // Callback for touch movement events + private let _onTouchMove: (Int32, Int32, Int32)->Void + // Callback for touch up events + private let _onTouchUp: (Int32, Int32, Int32)->Void + // Table to track hashes of active touches + private var _activeTouchIds: Array = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] + + public init(target: Any?, onTouchDown: @escaping(Int32, Int32, Int32)->Void, onTouchMove: @escaping(Int32, Int32, Int32)->Void, onTouchUp: @escaping(Int32, Int32, Int32)->Void) { + _onTouchDown = onTouchDown + _onTouchMove = onTouchMove + _onTouchUp = onTouchUp + + super.init(target: target, action: nil) + } + + override func touchesBegan(_ touches: Set, with event: UIEvent) { + super.touchesBegan(touches, with: event) + + for touch in touches { + guard let deviceSlot = _activeTouchIds.firstIndex(of: -1) else { continue } + _activeTouchIds[deviceSlot] = touch.hash + let loc = touch.location(in: view) + + _onTouchDown(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) + } + } + + override func touchesMoved(_ touches: Set, with event: UIEvent) { + super.touchesMoved(touches, with: event) + + for touch in touches { + guard let deviceSlot = _activeTouchIds.firstIndex(of: touch.hash) else { continue } + let loc = touch.location(in: view) + + _onTouchMove(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) + } + } + + override func touchesEnded(_ touches: Set, with event: UIEvent) { + super.touchesEnded(touches, with: event) + + for touch in touches { + guard let deviceSlot = _activeTouchIds.firstIndex(of: touch.hash) else { continue } + let loc = touch.location(in: view) + + _onTouchUp(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) + _activeTouchIds[deviceSlot] = -1 + } + } +} diff --git a/Apps/Playground/CMakeLists.txt b/Apps/Playground/CMakeLists.txt index 26cb8324e..ecf564bf1 100644 --- a/Apps/Playground/CMakeLists.txt +++ b/Apps/Playground/CMakeLists.txt @@ -32,12 +32,27 @@ if(APPLE) "iOS/AppDelegate.swift" "iOS/ViewController.swift" "iOS/LibNativeBridge.h" - "iOS/LibNativeBridge.mm") + "iOS/LibNativeBridge.mm" + "AppleShared/GestureRecognizer.swift") + set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Scripts") + set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "ReferenceImages") + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE NativeCamera) + elseif(VISIONOS) + set(PLIST_FILE + "${CMAKE_CURRENT_LIST_DIR}/visionOS/Info.plist") + set(RESOURCE_FILES ${SCRIPTS}) + set(SOURCES + ${SOURCES} + "visionOS/App.swift" + "visionOS/LibNativeBridge.mm" + "visionOS/LibNativeBridge.h" + "AppleShared/GestureRecognizer.swift") set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Scripts") set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "ReferenceImages") else() set(PLIST_FILE "${CMAKE_CURRENT_LIST_DIR}/macOS/Info.plist") set(STORYBOARD "${CMAKE_CURRENT_LIST_DIR}/macOS/Base.lproj/Main.storyboard") + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE NativeCamera) set(RESOURCE_FILES ${STORYBOARD}) set(SOURCES ${SOURCES} @@ -49,11 +64,12 @@ if(APPLE) set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/Scripts") set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/ReferenceImages") endif() - set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} - PRIVATE ${JAVASCRIPTCORE_LIBRARY} - PRIVATE NativeCamera) + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE ${JAVASCRIPTCORE_LIBRARY}) set(RESOURCE_FILES ${STORYBOARD}) + # Remove -Wall and -Werror from the debug flags to make simulators work. + string(REPLACE "-Wall" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "-Werror" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") elseif(UNIX) set(SOURCES ${SOURCES} @@ -153,16 +169,42 @@ if(APPLE) XCODE_ATTRIBUTE_SWIFT_VERSION "4.0" XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_LIST_DIR}/iOS/LibNativeBridge.h" XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks" + XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks" + XCODE_ATTRIBUTE_ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES YES + + # CMake seems to add a custom flag "-Wno-unknown-pragmas" to the Swift compiler. That flag is used for Clang, + # So we need to make sure we override it with nothing here in order to compile Swift. + XCODE_ATTRIBUTE_OTHER_SWIFT_FLAGS "") + + # Swift support + set(CMAKE_Swift_COMPILER_FORCED TRUE) + set(CMAKE_Swift_LANGUAGE_VERSION 4.0) + enable_language(Swift) + elseif(VISIONOS) + set_target_properties(Playground PROPERTIES + MACOSX_BUNDLE true + MACOSX_BUNDLE_INFO_PLIST "${PLIST_FILE}" + XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES + RESOURCE "${RESOURCE_FILES}" + + XCODE_ATTRIBUTE_XROS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.BabylonNative.Playground.visionOS" + + XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" + XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_LIST_DIR}/visionOS/LibNativeBridge.h" + XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks" + XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks" XCODE_ATTRIBUTE_ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES YES + XCODE_ATTRIBUTE_SWIFT_OBJC_INTEROP_MODE "objcxx" # CMake seems to add a custom flag "-Wno-unknown-pragmas" to the Swift compiler. That flag is used for Clang, # So we need to make sure we override it with nothing here in order to compile Swift. XCODE_ATTRIBUTE_OTHER_SWIFT_FLAGS "") - # Swift support - set(CMAKE_Swift_COMPILER_FORCED TRUE) - set(CMAKE_Swift_LANGUAGE_VERSION 4.0) - enable_language(Swift) + # Swift support + set(CMAKE_Swift_COMPILER_FORCED TRUE) + set(CMAKE_Swift_LANGUAGE_VERSION 5.0) + enable_language(Swift) else() target_link_libraries(Playground PUBLIC "-framework MetalKit") @@ -209,3 +251,5 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SCRIPTS}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES}) set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Playground) +set_property(TARGET Playground PROPERTY XCODE_GENERATE_SCHEME YES) +set_property(TARGET Playground PROPERTY XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED YES) diff --git a/Apps/Playground/iOS/ViewController.swift b/Apps/Playground/iOS/ViewController.swift index d0189e081..2d44facdc 100644 --- a/Apps/Playground/iOS/ViewController.swift +++ b/Apps/Playground/iOS/ViewController.swift @@ -1,63 +1,6 @@ import UIKit import MetalKit -/** - * A very simple gesture recognizer. All that it does is to emulate the functionality found in other platforms - */ -class UIBabylonGestureRecognizer: UIGestureRecognizer { - // Callback for touch down events - private let _onTouchDown: (Int32, Int32, Int32)->Void - // Callback for touch movement events - private let _onTouchMove: (Int32, Int32, Int32)->Void - // Callback for touch up events - private let _onTouchUp: (Int32, Int32, Int32)->Void - // Table to track hashes of active touches - private var _activeTouchIds: Array = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] - - public init(target: Any?, onTouchDown: @escaping(Int32, Int32, Int32)->Void, onTouchMove: @escaping(Int32, Int32, Int32)->Void, onTouchUp: @escaping(Int32, Int32, Int32)->Void) { - _onTouchDown = onTouchDown - _onTouchMove = onTouchMove - _onTouchUp = onTouchUp - - super.init(target: target, action: nil) - } - - override func touchesBegan(_ touches: Set, with event: UIEvent) { - super.touchesBegan(touches, with: event) - - for touch in touches { - guard let deviceSlot = _activeTouchIds.firstIndex(of: -1) else { continue } - _activeTouchIds[deviceSlot] = touch.hash - let loc = touch.location(in: view) - - _onTouchDown(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) - } - } - - override func touchesMoved(_ touches: Set, with event: UIEvent) { - super.touchesMoved(touches, with: event) - - for touch in touches { - guard let deviceSlot = _activeTouchIds.firstIndex(of: touch.hash) else { continue } - let loc = touch.location(in: view) - - _onTouchMove(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) - } - } - - override func touchesEnded(_ touches: Set, with event: UIEvent) { - super.touchesEnded(touches, with: event) - - for touch in touches { - guard let deviceSlot = _activeTouchIds.firstIndex(of: touch.hash) else { continue } - let loc = touch.location(in: view) - - _onTouchUp(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) - _activeTouchIds[deviceSlot] = -1 - } - } -} - class ViewController: UIViewController { var mtkView: MTKView! diff --git a/Apps/Playground/visionOS/App.swift b/Apps/Playground/visionOS/App.swift new file mode 100644 index 000000000..53607edf1 --- /dev/null +++ b/Apps/Playground/visionOS/App.swift @@ -0,0 +1,77 @@ +import SwiftUI + +class MetalView: UIView { + override init(frame: CGRect) { + super.init(frame: frame) + self.backgroundColor = .clear + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupMetalLayer() { + guard let bridge = LibNativeBridge.sharedInstance() else { return } + + if bridge.metalLayer != nil { + return + } + + self.addGestureRecognizer( + UIBabylonGestureRecognizer( + target: self, + onTouchDown: bridge.setTouchDown, + onTouchMove: bridge.setTouchMove, + onTouchUp: bridge.setTouchUp + ) + ) + metalLayer.pixelFormat = .bgra8Unorm + metalLayer.framebufferOnly = true + + bridge.metalLayer = self.metalLayer + + let scale = UITraitCollection.current.displayScale + bridge.initialize(withWidth: Int(self.bounds.width * scale), height: Int(self.bounds.height * scale)) + } + + var metalLayer: CAMetalLayer { + return layer as! CAMetalLayer + } + + override class var layerClass: AnyClass { + return CAMetalLayer.self + } + + override func layoutSubviews() { + super.layoutSubviews() + setupMetalLayer() + updateDrawableSize() + } + + private func updateDrawableSize() { + let scale = UITraitCollection.current.displayScale + LibNativeBridge.sharedInstance().drawableWillChangeSize(withWidth: Int(bounds.width * scale), height: Int(bounds.height * scale)) + metalLayer.drawableSize = CGSize(width: bounds.width * scale, height: bounds.height * scale) + } +} + +struct MetalViewRepresentable: UIViewRepresentable { + typealias UIViewType = MetalView + + func makeUIView(context: Context) -> MetalView { + MetalView(frame: .zero) + } + + func updateUIView(_ uiView: MetalView, context: Context) {} +} + + +@main +struct ExampleApp: App { + var body: some Scene { + WindowGroup { + MetalViewRepresentable() + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } +} diff --git a/Apps/Playground/visionOS/Info.plist b/Apps/Playground/visionOS/Info.plist new file mode 100644 index 000000000..1f9bad276 --- /dev/null +++ b/Apps/Playground/visionOS/Info.plist @@ -0,0 +1,33 @@ + + + + + NSPhotoLibraryAddUsageDescription + Need photo library permission for debug code to save photo captures + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UIApplicationSceneManifest + + UIApplicationPreferredDefaultSceneSessionRole + UIWindowSceneSessionRoleApplication + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + + + diff --git a/Apps/Playground/visionOS/LibNativeBridge.h b/Apps/Playground/visionOS/LibNativeBridge.h new file mode 100644 index 000000000..0489a7068 --- /dev/null +++ b/Apps/Playground/visionOS/LibNativeBridge.h @@ -0,0 +1,24 @@ +#import +#import + +@class CAMetalLayer; + +@interface LibNativeBridge : NSObject + +@property (nonatomic, assign, getter=isInitialized) BOOL initialized; +@property (nonatomic, strong) CAMetalLayer *metalLayer; + ++ (instancetype)sharedInstance; + +- (void)setTouchDown:(int)pointerId x:(int)inX y:(int)inY; +- (void)setTouchMove:(int)pointerId x:(int)inX y:(int)inY; +- (void)setTouchUp:(int)pointerId x:(int)inX y:(int)inY; + +- (void)drawableWillChangeSizeWithWidth:(NSInteger)width height:(NSInteger)height; + +- (bool)initializeWithWidth:(NSInteger)width height:(NSInteger)height; +- (void)shutdown; +- (void)render; + +@end + diff --git a/Apps/Playground/visionOS/LibNativeBridge.mm b/Apps/Playground/visionOS/LibNativeBridge.mm new file mode 100644 index 000000000..bd3043881 --- /dev/null +++ b/Apps/Playground/visionOS/LibNativeBridge.mm @@ -0,0 +1,148 @@ +#import "LibNativeBridge.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +@implementation LibNativeBridge { + std::optional _device; + std::optional _update; + std::optional _runtime; + std::optional _nativeCanvas; + Babylon::Plugins::NativeInput* _nativeInput; + bool _isXrActive; + CADisplayLink *_displayLink; +} + ++ (instancetype)sharedInstance { + static LibNativeBridge *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + +- (bool)initializeWithWidth:(NSInteger)width height:(NSInteger)height { + if (self.initialized) { + return YES; + } + + _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render)]; + [_displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSDefaultRunLoopMode]; + + Babylon::Graphics::Configuration graphicsConfig{}; + graphicsConfig.Window = self.metalLayer; + graphicsConfig.Width = static_cast(width); + graphicsConfig.Height = static_cast(height); + + _device.emplace(graphicsConfig); + _update.emplace(_device->GetUpdate("update")); + + _device->StartRenderingCurrentFrame(); + _update->Start(); + + _runtime.emplace(); + + _runtime->Dispatch([self](Napi::Env env) { + self->_device->AddToJavaScript(env); + + Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) { + NSLog(@"%s", message); + }); + + self->_nativeCanvas.emplace(Babylon::Polyfills::Canvas::Initialize(env)); + + Babylon::Polyfills::Window::Initialize(env); + + Babylon::Polyfills::XMLHttpRequest::Initialize(env); + + Babylon::Plugins::NativeEngine::Initialize(env); + + Babylon::Plugins::NativeOptimizations::Initialize(env); + + _nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env); + }); + + Babylon::ScriptLoader loader{ *_runtime }; + loader.LoadScript("app:///Scripts/ammo.js"); + loader.LoadScript("app:///Scripts/recast.js"); + loader.LoadScript("app:///Scripts/babylon.max.js"); + loader.LoadScript("app:///Scripts/babylonjs.loaders.js"); + loader.LoadScript("app:///Scripts/babylonjs.materials.js"); + loader.LoadScript("app:///Scripts/babylon.gui.js"); + loader.LoadScript("app:///Scripts/experience.js"); + self.initialized = YES; + + return true; +} + +- (void)drawableWillChangeSizeWithWidth:(NSInteger)width height:(NSInteger)height { + if (_device) { + _update->Finish(); + _device->FinishRenderingCurrentFrame(); + + _device->UpdateSize(static_cast(width), static_cast(height)); + + _device->StartRenderingCurrentFrame(); + _update->Start(); + } +} + +- (void)setTouchDown:(int)pointerId x:(int)inX y:(int)inY { + if (_nativeInput) { + _nativeInput->TouchDown(static_cast(pointerId), static_cast(inX), static_cast(inY)); + } +} + +- (void)setTouchMove:(int)pointerId x:(int)inX y:(int)inY { + if (_nativeInput) { + _nativeInput->TouchMove(static_cast(pointerId), static_cast(inX), static_cast(inY)); + } +} + +- (void)setTouchUp:(int)pointerId x:(int)inX y:(int)inY { + if (_nativeInput) { + _nativeInput->TouchUp(static_cast(pointerId), static_cast(inX), static_cast(inY)); + } +} + +- (void)render { + if (_device && self.initialized) { + _update->Finish(); + _device->FinishRenderingCurrentFrame(); + _device->StartRenderingCurrentFrame(); + _update->Start(); + } +} + +- (void)shutdown { + if (!self.initialized) { + return; + } + if (_device) { + _update->Finish(); + _device->FinishRenderingCurrentFrame(); + } + + _nativeInput = nullptr; + _nativeCanvas.reset(); + _runtime.reset(); + _update.reset(); + _device.reset(); + [_displayLink invalidate]; + _displayLink = NULL; + self.initialized = NO; +} + +- (void)dealloc { + [self shutdown]; +} + +@end diff --git a/BUILDING.md b/BUILDING.md index b9840ed6f..b086e7498 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -192,6 +192,44 @@ demo app, click on the project selector and find `Playground` in the list of pos selections. The `Play` button will subsequently allow you to build, run, and debug the selected Babylon Native demo app. +## **Building on macOS, Targeting visionOS** + +_Follow the steps from [All Development Platforms](#all-development-platforms) before proceeding._ + +**Required Tools:** [Xcode 15](https://developer.apple.com/xcode/) or newer, +[Python 3.0](https://www.python.org/) or newer (required by dependencies) + +For macOS development, CMake will generate a Makefile by default. It may be possible +to build Babylon Native for macOS using this approach, but only the Xcode method is +supported at present. To generate an Xcode project using CMake, you must specify the +correct build system generator for CMake to use. Additionally, you must tell CMake +what toolchain to use, which provides additional information about how to generate an +visionOS Xcode project correctly. Run the following command from the repository root: + +``` +cmake -B build/visionOS -G Xcode -D VISIONOS=ON +``` + +To enable bitcode support, add this option to the cmake command line parameters: + +``` +-D ENABLE_BITCODE=ON +``` + +CMake will generate a new `BabylonNative.xcodeproj` file in the specified build folder. +Open the project by double-clicking on it in Finder or by entering the following command: + +``` +open build/visionOS/BabylonNative.xcodeproj +``` + +To select which project to build with Xcode, select the correct project name in the +menu to the right of the greyed-out `Stop` button adjacent to the `Play` button in +the top-left corner of the Xcode window. For example, to build and run the Playground +demo app, click on the project selector and find `Playground` in the list of possible +selections. The `Play` button will subsequently allow you to build, run, and debug +the selected Babylon Native demo app. + ## **Building on Windows, Targeting Android** _Follow the steps from [All Development Platforms](#all-development-platforms) before proceeding._ diff --git a/CMakeLists.txt b/CMakeLists.txt index 8131f7721..6d55648e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ FetchContent_Declare(base-n GIT_TAG 7573e77c0b9b0e8a5fb63d96dbde212c921993b4) FetchContent_Declare(bgfx.cmake GIT_REPOSITORY https://github.com/BabylonJS/bgfx.cmake.git - GIT_TAG 17e2f84510dbb69c87a02b08fb11cecb2c4afc9b) + GIT_TAG 3f6a554a2f24ddb9303873dc64158a18b111f59b) FetchContent_Declare(CMakeExtensions GIT_REPOSITORY https://github.com/BabylonJS/CMakeExtensions.git GIT_TAG ea28b7689530bfdc4905806f27ecf7e8ed4b5419) @@ -51,6 +51,15 @@ FetchContent_Declare(SPIRV-Cross FetchContent_MakeAvailable(CMakeExtensions) + +if(VISIONOS) + FetchContent_MakeAvailable_With_Message(ios-cmake) + set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") + set(PLATFORM "VISIONOSCOMBINED" CACHE STRING "") + set(DEPLOYMENT_TARGET "1.0" CACHE STRING "") + set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") +endif() + if(IOS) FetchContent_MakeAvailable_With_Message(ios-cmake) set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") @@ -59,6 +68,7 @@ if(IOS) set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") endif() + project(BabylonNative) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -98,6 +108,8 @@ if(ANDROID) set(BABYLON_NATIVE_PLATFORM "Android") elseif(IOS) set(BABYLON_NATIVE_PLATFORM "iOS") +elseif (VISIONOS) + set(BABYLON_NATIVE_PLATFORM "visionOS") elseif(APPLE) set(BABYLON_NATIVE_PLATFORM "macOS") elseif(WINDOWS_STORE) diff --git a/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h b/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h new file mode 100644 index 000000000..f64c68e75 --- /dev/null +++ b/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h @@ -0,0 +1,8 @@ +#pragma once + +#import + +namespace Babylon::Graphics +{ + using WindowT = CAMetalLayer*; +} diff --git a/Core/Graphics/Source/DeviceImpl_visionOS.mm b/Core/Graphics/Source/DeviceImpl_visionOS.mm new file mode 100644 index 000000000..0b7ac2837 --- /dev/null +++ b/Core/Graphics/Source/DeviceImpl_visionOS.mm @@ -0,0 +1,21 @@ +#include +#include "DeviceImpl.h" + +namespace Babylon::Graphics +{ + void DeviceImpl::ConfigureBgfxPlatformData(bgfx::PlatformData& pd, WindowT window) + { + pd.nwh = window; + } + + void DeviceImpl::ConfigureBgfxRenderType(bgfx::PlatformData& /*pd*/, bgfx::RendererType::Enum& /*renderType*/) + { + } + + float DeviceImpl::GetDevicePixelRatio(WindowT window) + { + BX_UNUSED(window); + CGFloat displayScale = [UITraitCollection currentTraitCollection].displayScale; + return displayScale; + } +} diff --git a/Dependencies/CMakeLists.txt b/Dependencies/CMakeLists.txt index 47cee4242..20ea6187f 100644 --- a/Dependencies/CMakeLists.txt +++ b/Dependencies/CMakeLists.txt @@ -106,7 +106,7 @@ set_property(TARGET SPIRV PROPERTY FOLDER Dependencies/glslang) # -------------------------------------------------- # googletest # -------------------------------------------------- -if(BABYLON_NATIVE_BUILD_APPS AND (WIN32 OR (APPLE AND NOT IOS) OR (UNIX AND NOT ANDROID))) +if(BABYLON_NATIVE_BUILD_APPS AND (WIN32 OR (APPLE AND NOT IOS AND NOT VISIONOS) OR (UNIX AND NOT ANDROID))) if(WIN32) # For Windows: Prevent overriding the parent project's compiler/linker settings # Default build type for my test projects are /MDd (MultiThreaded DLL) but GTests default to /MTd (MultiTreaded) diff --git a/README.md b/README.md index 253dc54b0..a5c183c79 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Check out the [home page](https://aka.ms/Bnative) for a project overview. - [Building on Windows 10, Targeting HoloLens 2](BUILDING.md#building-on-windows-10-targeting-hololens-2) - [Building on macOS, Targeting macOS](BUILDING.md#building-on-macos-targeting-macos) - [Building on macOS, Targeting iOS](BUILDING.md#building-on-macos-targeting-ios) + - [Building on macOS, Targeting visionOS](BUILDING.md#building-on-macos-targeting-visionos) - [Building on Windows, Targeting Android](BUILDING.md#building-on-windows-targeting-android) - [Building on Ubuntu, Targeting Linux](BUILDING.md#building-on-ubuntu-targeting-linux) - [Selecting the Graphics API](BUILDING.md#selecting-the-graphics-api)