├── CoreSimulator ├── module.modulemap └── CoreSimulator.h ├── XRGyroControls.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ ├── XRGyroControlsUI.xcscheme │ │ ├── XRGyroControlsType.xcscheme │ │ └── XRGyroControls.xcscheme └── project.pbxproj ├── README.md ├── SimulatorKit └── SimulatorKit.swift ├── SimulatorSupport.swift ├── example.py ├── SimulatorType ├── profile.plist └── capabilities.plist ├── .gitignore ├── IndigoHID.swift └── UDPServer.swift /CoreSimulator/module.modulemap: -------------------------------------------------------------------------------- 1 | module CoreSimulator { 2 | header "CoreSimulator.h" 3 | export * 4 | 5 | //module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /XRGyroControls.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XRGyroControls.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CoreSimulator/CoreSimulator.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for CoreSimulator. 4 | FOUNDATION_EXPORT double CoreSimulatorVersionNumber; 5 | 6 | //! Project version string for CoreSimulator. 7 | FOUNDATION_EXPORT const unsigned char CoreSimulatorVersionString[]; 8 | 9 | // In this header, you should import all the public headers of your framework using statements like #import 10 | 11 | @interface SimDevice : NSObject 12 | @end 13 | 14 | struct IndigoHIDMessageStruct{ 15 | uint8_t bytes[0xc0]; 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XRGyroControls 2 | This is a replacement for the default controls used in the VisionOS xrOS Simulator. This will allow you to control the simulator camera with an actual VR headset once it is finished. Right now it is in POC stage and can control the simulator, but doesn't actually take input from another headset. 3 | 4 | ## Installation 5 | 1. Disable SIP 6 | 2. Disable library validation (`sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation.plist DisableLibraryValidation -bool true`) 7 | 3. Install the latest Xcode beta, and install the VisionOS Simulator. 8 | 4. Clone the git repo and open it in Xcode 9 | 6. Launch the default schema. It should automatically open the Xcode simulator, you will need to manually select the "XRGyroControlsType" simulator device type and launch it. 10 | 7. You should be able to control the new simulator type over UDP port `9985`. A sample JSON client is in `example.py` for now, it also accepts OpenTrack and @keithahern's messages on the same port (though they are less flexible) 11 | -------------------------------------------------------------------------------- /SimulatorKit/SimulatorKit.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import CoreSimulator 3 | 4 | @objc public protocol SimDeviceUserInterfacePlugin {} 5 | 6 | @objc public class SimDeviceLegacyHIDClient : NSObject { 7 | // The padding is to make sure that the offset aligns with the original, when Swift tries to do tricky optimizations 8 | // I don't completely understand it yet, but this works and I'm not touching it 9 | private var padding001: Int64 = 0 10 | private var padding002: Int64 = 0 11 | private var padding003: Int64 = 0 12 | private var padding004: Int64 = 0 13 | private var padding005: Int64 = 0 14 | private var padding006: Int64 = 0 15 | private func padding07() {} 16 | private func padding08() {} 17 | private func padding09() {} 18 | private func padding10() {} 19 | private func padding11() {} 20 | 21 | @objc public init(device: SimDevice) throws {} 22 | 23 | // Offset: 0x140 24 | @objc public func send(message: UnsafeMutablePointer) {} 25 | 26 | } 27 | -------------------------------------------------------------------------------- /SimulatorSupport.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SimulatorKit 3 | import CoreSimulator 4 | import AppKit 5 | import Spatial 6 | 7 | @objc class SimulatorSupport : NSObject, SimDeviceUserInterfacePlugin { 8 | 9 | private let device: SimDevice 10 | private let hid_client: SimDeviceLegacyHIDClient 11 | private let server: UDPServer 12 | 13 | @objc init(with device: SimDevice) { 14 | self.device = device 15 | print("XRGyroControls: Initialized with device: \(device)") 16 | self.hid_client = try! SimDeviceLegacyHIDClient(device: device) 17 | print("XRGyroControls: Initialized HID client") 18 | 19 | server = try! UDPServer(hid_client, on: 9985) 20 | 21 | super.init() 22 | 23 | // Here's an example using a 4x4 transform matrix, as logged by the simulator 24 | // Should point the pointer at the "Environments" menu item 25 | let fxf = simd_float4x4([[0.9999595, 0.0, -0.008998766, 0.0], [0.0, 1.0, 0.0, 0.0], [0.008998766, 0.0, 0.9999595, 0.0], [0.009089867, 0.0, 0.009959124, 1.0]]) 26 | 27 | let transform = ProjectiveTransform3D(fxf) 28 | 29 | let pose = Pose3D(transform: transform)! 30 | 31 | hid_client.send(message: IndigoHIDMessage.camera(pose).as_struct()) 32 | 33 | hid_client.send(message: IndigoHIDMessage.manipulator(pose: pose, gaze: Ray3D(direction: Vector3D(x: -0.40874016, y: -0.07154943, z: -0.9098418)), pinch: false).as_struct()) 34 | } 35 | 36 | @objc func overlayView() -> NSView { 37 | return NSView() 38 | } 39 | 40 | @objc func toolbar() -> NSToolbar { 41 | return NSToolbar() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | import json 2 | import socket 3 | import time 4 | 5 | import numpy as np 6 | 7 | # Create a UDP socket 8 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 9 | sock.connect(("localhost", 9985)) 10 | 11 | 12 | # Why is this different then on Wikipedia? Had to change which variable is which 13 | def euler_to_quaternion(yaw, pitch, roll): 14 | hy, hr, hp = yaw / 2, roll / 2, pitch / 2 15 | qx = np.sin(hp) * np.cos(hy) * np.cos(hr) - np.cos(hp) * np.sin(hy) * np.sin(hr) 16 | qy = np.cos(hp) * np.sin(hy) * np.cos(hr) + np.sin(hp) * np.cos(hy) * np.sin(hr) 17 | qz = np.cos(hp) * np.cos(hy) * np.sin(hr) - np.sin(hp) * np.sin(hy) * np.cos(hr) 18 | qw = np.cos(hp) * np.cos(hy) * np.cos(hr) + np.sin(hp) * np.sin(hy) * np.sin(hr) 19 | 20 | return [qx, qy, qz, qw] 21 | 22 | 23 | def angles_to_coords(angle, pitch): 24 | x = np.cos(angle) * np.cos(pitch) 25 | z = np.sin(angle) * np.cos(pitch) 26 | y = np.sin(pitch) 27 | return [x, y, z] 28 | 29 | 30 | message = { 31 | "camera": { # Optional, sets the pose of the camera 32 | "position": [0, 0, 0], 33 | "rotation": euler_to_quaternion(np.radians(40), 0, 0), 34 | }, 35 | "manipulator": { # Optional, sets the pose and gaze of the manipulator 36 | "pose": { # Not sure what this effects, tbh. The gaze is absolute, not relative to the pose 37 | "position": [0, 0, 0], 38 | "rotation": euler_to_quaternion(np.radians(40), 0, 0), 39 | }, 40 | "gaze": { # This ray can be visualized if you turn on the "finger" alternative pointer in the simulator a11y settings 41 | "origin": [0, 0, 0], 42 | "direction": angles_to_coords( 43 | np.radians(-114), np.radians(-4) 44 | ), # This is an example, it should be pointing to the environments button. 45 | }, 46 | "pinch": False, # Later, I might make this also accept the other inputs, but for now, it's just a boolean 47 | }, 48 | } 49 | 50 | sock.sendall(json.dumps(message).encode()) 51 | 52 | time.sleep(1) 53 | 54 | del message["camera"] # Don't really need to do this, but it saves a few bytes 55 | message["manipulator"]["pinch"] = True 56 | 57 | sock.sendall(json.dumps(message).encode()) 58 | -------------------------------------------------------------------------------- /SimulatorType/profile.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | createByDefaultForRuntimeVersions 6 | 7 | versionMax 8 | 99.99 9 | versionMin 10 | 1.0 11 | 12 | environment 13 | 14 | SIMULATOR_LEGACY_ASSET_SUFFIX 15 | 16 | 17 | mainScreenHeight 18 | 2048 19 | mainScreenHeightDPI 20 | 264 21 | mainScreenScale 22 | 2 23 | mainScreenWidth 24 | 2732 25 | mainScreenWidthDPI 26 | 264 27 | minRuntimeVersion 28 | 1.0 29 | modelIdentifier 30 | RealityDevice14,1 31 | productClass 32 | N301 33 | springBoardConfigName 34 | iPadSimulatorHiDPI 35 | supportedArchs 36 | 37 | x86_64 38 | arm64 39 | 40 | supportedFeatures 41 | 42 | com.apple.display.integrated 43 | 44 | com.apple.display.supports-external 45 | 46 | com.apple.hid.digital-dial 47 | 48 | com.apple.hid.gamecontroller.capture 49 | 50 | com.apple.hid.hoverboard.95880941 51 | 52 | com.apple.hid.keyboard 53 | 54 | com.apple.hid.touch-screen 55 | 56 | com.apple.pearl-id 57 | 58 | 59 | supportedFeaturesConditionalOnRuntime 60 | 61 | com.apple.CoreSimulator.pairing 62 | 1 63 | com.apple.hid.applepay.authorize 64 | 65 | com.apple.hid.pointer.system 66 | 67 | 68 | supportedProductFamilyIDs 69 | 70 | 7 71 | 2 72 | 1 73 | 74 | userInterfaceIdentifier 75 | dev.jjtech.XRGyroControls.SimDeviceUI 76 | 77 | 78 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, 4 | Objective-C.gitignore & Swift.gitignore 5 | 6 | ## User settings 7 | xcuserdata/ 8 | 9 | ## compatibility with Xcode 8 and earlier (ignoring not required starting 10 | Xcode 9) 11 | *.xcscmblueprint 12 | *.xccheckout 13 | 14 | ## compatibility with Xcode 3 and earlier (ignoring not required starting 15 | Xcode 4) 16 | build/ 17 | DerivedData/ 18 | *.moved-aside 19 | *.pbxuser 20 | !default.pbxuser 21 | *.mode1v3 22 | !default.mode1v3 23 | *.mode2v3 24 | !default.mode2v3 25 | *.perspectivev3 26 | !default.perspectivev3 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | 31 | ## App packaging 32 | *.ipa 33 | *.dSYM.zip 34 | *.dSYM 35 | 36 | ## Playgrounds 37 | timeline.xctimeline 38 | playground.xcworkspace 39 | 40 | # Swift Package Manager 41 | # 42 | # Add this line if you want to avoid checking in source code from Swift 43 | Package Manager dependencies. 44 | # Packages/ 45 | # Package.pins 46 | # Package.resolved 47 | # *.xcodeproj 48 | # 49 | # Xcode automatically generates this directory with a .xcworkspacedata 50 | file and xcuserdata 51 | # hence it is not needed unless you have added a package configuration 52 | file to your project 53 | # .swiftpm 54 | 55 | .build/ 56 | 57 | # CocoaPods 58 | # 59 | # We recommend against adding the Pods directory to your .gitignore. 60 | However 61 | # you should judge for yourself, the pros and cons are mentioned at: 62 | # 63 | https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 64 | # 65 | # Pods/ 66 | # 67 | # Add this line if you want to avoid checking in source code from the 68 | Xcode workspace 69 | # *.xcworkspace 70 | 71 | # Carthage 72 | # 73 | # Add this line if you want to avoid checking in source code from Carthage 74 | dependencies. 75 | # Carthage/Checkouts 76 | 77 | Carthage/Build/ 78 | 79 | # Accio dependency management 80 | Dependencies/ 81 | .accio/ 82 | 83 | # fastlane 84 | # 85 | # It is recommended to not store the screenshots in the git repo. 86 | # Instead, use fastlane to re-generate the screenshots whenever they are 87 | needed. 88 | # For more information about the recommended setup visit: 89 | # 90 | https://docs.fastlane.tools/best-practices/source-control/#source-control 91 | 92 | fastlane/report.xml 93 | fastlane/Preview.html 94 | fastlane/screenshots/**/*.png 95 | fastlane/test_output 96 | 97 | # Code Injection 98 | # 99 | # After new code Injection tools there's a generated folder 100 | /iOSInjectionProject 101 | # https://github.com/johnno1962/injectionforxcode 102 | 103 | iOSInjectionProject/ 104 | -------------------------------------------------------------------------------- /XRGyroControls.xcodeproj/xcshareddata/xcschemes/XRGyroControlsUI.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 42 | 43 | 49 | 50 | 56 | 57 | 58 | 59 | 61 | 62 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /XRGyroControls.xcodeproj/xcshareddata/xcschemes/XRGyroControlsType.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 42 | 43 | 49 | 50 | 56 | 57 | 58 | 59 | 61 | 62 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /XRGyroControls.xcodeproj/xcshareddata/xcschemes/XRGyroControls.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 45 | 46 | 56 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /IndigoHID.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import CoreSimulator 3 | import simd 4 | import Spatial 5 | 6 | // These are probably really inefficient, but whatever they make everything else a ton easier 7 | extension simd_quatf { 8 | // Convert simd_quatd to simd_quatf 9 | init(_ quat: simd_quatd) { 10 | self.init(ix: Float(quat.imag.x), iy: Float(quat.imag.y), iz: Float(quat.imag.z), r: Float(quat.real)) 11 | print("Converting \(quat) to \(self)") 12 | } 13 | } 14 | 15 | extension simd_float4x4 { 16 | // Convert double4x4 to float4x4 17 | init(_ mat: double4x4) { 18 | self.init(columns: (simd_float4(Float(mat.columns.0.x), Float(mat.columns.0.y), Float(mat.columns.0.z), Float(mat.columns.0.w)), 19 | simd_float4(Float(mat.columns.1.x), Float(mat.columns.1.y), Float(mat.columns.1.z), Float(mat.columns.1.w)), 20 | simd_float4(Float(mat.columns.2.x), Float(mat.columns.2.y), Float(mat.columns.2.z), Float(mat.columns.2.w)), 21 | simd_float4(Float(mat.columns.3.x), Float(mat.columns.3.y), Float(mat.columns.3.z), Float(mat.columns.3.w)))) 22 | } 23 | } 24 | 25 | class IndigoHIDMessage { 26 | /// You must NOT change the length to anything other than 0xC0 27 | public var data: [UInt8] = [] 28 | 29 | public func as_struct() -> UnsafeMutablePointer { 30 | // Make sure that the backing data is the correct size 31 | guard data.count == MemoryLayout.size else { 32 | fatalError("IndigoHIDMessage backing data is not the correct size") 33 | } 34 | 35 | // Allocate a new struct and copy the bytes to it 36 | let ptr = UnsafeMutablePointer.allocate(capacity: 1) 37 | ptr.initialize(to: data.withUnsafeBufferPointer { $0.baseAddress!.withMemoryRebound(to: IndigoHIDMessageStruct.self, capacity: 1) { $0.pointee } }) 38 | return ptr 39 | 40 | } 41 | 42 | private func write(_ of: T, at offset: Int) { 43 | let bytes: [UInt8] = withUnsafeBytes(of: of) { Array($0) } 44 | print("Writing \(bytes) to offset \(offset)") 45 | data[offset...size) 51 | 52 | // Set the timestamp to the current time 53 | write(mach_absolute_time(), at: 0x24) 54 | 55 | // Write the constant values 56 | data[0x18] = 0xA0 57 | data[0x1C] = 0x01 58 | data[0x20] = 0x01 59 | } 60 | 61 | public static func camera(_ pose: Pose3D) -> IndigoHIDMessage { 62 | let message = IndigoHIDMessage() 63 | 64 | message.write(300 as Int32, at: 0x30) 65 | 66 | message.write(simd_float3(pose.position.vector), at: 0x54) 67 | message.write(simd_quatf(pose.rotation.quaternion), at: 0x64) 68 | 69 | return message 70 | } 71 | 72 | public static func manipulator(pose: Pose3D, gaze: Ray3D, pinch: Bool) -> IndigoHIDMessage { 73 | let message = IndigoHIDMessage() 74 | 75 | message.write(302, at: 0x30) 76 | 77 | // TODO: Expose pinching, figure out all the different possibilities (what is 'touching' for?) 78 | message.data[0x34] = 3 79 | 80 | message.data[0x38] = 0 // ? 81 | message.data[0x39] = 2 82 | 83 | message.data[0x3A] = 0 // ? 84 | message.data[0x3B] = 3 85 | 86 | message.data[0x3F] = pinch ? 1 : 0 // pinch right 87 | message.data[0x40] = 1 88 | message.data[0x41] = 0 // ? 89 | 90 | message.write(simd_float3(gaze.origin.vector), at: 0x47) 91 | message.write(simd_float3(gaze.direction.vector), at: 0x57) 92 | 93 | message.write(simd_float4x4(pose.matrix), at: 0x67) 94 | 95 | return message 96 | } 97 | 98 | // This doesn't have any observable effects that I can see, but I implemented it for completeness sake. 99 | public static func dial(_ value: Double) -> IndigoHIDMessage { 100 | let message = IndigoHIDMessage() 101 | 102 | message.data[0x20] = 0x06 103 | 104 | message.write(value, at: 0x38) 105 | 106 | message.data[0x4C] = 0xC8 107 | message.data[0x2C] = 0x10 108 | 109 | return message 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /UDPServer.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Spatial 3 | import Network 4 | import SimulatorKit 5 | import simd 6 | 7 | class UDPServer { 8 | let hid_client: SimDeviceLegacyHIDClient 9 | let listener: NWListener 10 | 11 | init(_ hid_client: SimDeviceLegacyHIDClient, on port: NWEndpoint.Port) throws { 12 | self.hid_client = hid_client 13 | 14 | self.listener = try NWListener(using: .udp, on: port) 15 | 16 | listener.stateUpdateHandler = {(newState) in 17 | switch newState { 18 | case .ready: 19 | print("Listener ready") 20 | default: 21 | break 22 | } 23 | } 24 | 25 | listener.newConnectionHandler = {(newConnection) in 26 | newConnection.stateUpdateHandler = {newState in 27 | switch newState { 28 | case .ready: 29 | print("Connection ready, waiting for message") 30 | self.recieveMessage(newConnection) 31 | default: 32 | break 33 | } 34 | } 35 | newConnection.start(queue: .global(qos: .userInitiated)) 36 | } 37 | 38 | listener.start(queue: .global(qos: .background)) 39 | } 40 | 41 | func recieveMessage(_ connection: NWConnection) { 42 | connection.receiveMessage { content, contentContext, isComplete, error in 43 | if let content = content { 44 | for messageHandler in self.MESSAGE_HANDLERS { 45 | // We need to call the handler with ourselves 46 | if (messageHandler(self)(content)) { 47 | // The message was handled, so we can stop 48 | break 49 | } 50 | } 51 | 52 | self.recieveMessage(connection) 53 | } 54 | } 55 | } 56 | 57 | // Define the message handlers that can handle incoming messages 58 | // Return true if the message was handled, false otherwise 59 | // Don't force unwrap, if a message is malformed just return false 60 | let MESSAGE_HANDLERS = [keithHandler, openTrackHandler, jsonHandler] 61 | 62 | func jsonHandler(_ data: Data) -> Bool { 63 | struct jsonMessage: Codable { 64 | struct jsonPose: Codable { 65 | var position: simd_float3 66 | var rotation: simd_float4 67 | } 68 | 69 | struct jsonGaze: Codable { 70 | var origin: simd_float3 71 | var direction: simd_float3 72 | } 73 | 74 | struct jsonManipulator: Codable { 75 | var pose: jsonPose 76 | var gaze: jsonGaze 77 | var pinch: Bool 78 | } 79 | 80 | var camera: jsonPose? 81 | var manipulator: jsonManipulator? 82 | var dial: Double? 83 | } 84 | 85 | guard let message = try? JSONDecoder().decode(jsonMessage.self, from: data) else { return false } 86 | print("Got JSON message: \(message)") 87 | 88 | if let camera = message.camera { 89 | self.hid_client.send(message: IndigoHIDMessage.camera(Pose3D(position: camera.position, rotation: simd_quatf(vector: camera.rotation))).as_struct()) 90 | } 91 | 92 | if let manipulator = message.manipulator { 93 | self.hid_client.send(message: IndigoHIDMessage.manipulator( 94 | pose: Pose3D(position: manipulator.pose.position, rotation: simd_quatf(vector: manipulator.pose.rotation)), 95 | gaze: Ray3D(origin: Point3D(vector: simd_double3(manipulator.gaze.origin)), direction: Vector3D(vector: simd_double3(manipulator.gaze.direction))), 96 | pinch: manipulator.pinch 97 | ).as_struct()) 98 | } 99 | 100 | if let dial = message.dial { 101 | self.hid_client.send(message: IndigoHIDMessage.dial(dial).as_struct()) 102 | } 103 | 104 | return true 105 | } 106 | 107 | func keithHandler(_ data: Data) -> Bool { 108 | guard let string = String(data: data, encoding: .utf8) else { return false } 109 | guard string.hasPrefix("Position") else { return false } 110 | 111 | let components = string.components(separatedBy: ";") 112 | 113 | let positionString = components[0].replacingOccurrences(of: "Position:", with: "") 114 | let rotationString = components[1].replacingOccurrences(of: "Rotation:", with: "") 115 | 116 | let positionComponents = positionString.components(separatedBy: ",") 117 | let rotationComponents = rotationString.components(separatedBy: ",") 118 | 119 | guard positionComponents.count == 3, rotationComponents.count == 4 else { return false } 120 | 121 | 122 | let position = (Float(positionComponents[0]) ?? 0.0, Float(positionComponents[1]) ?? 0.0, Float(positionComponents[2]) ?? 0.0) 123 | let rotation = (Float(rotationComponents[0]) ?? 0.0, Float(rotationComponents[1]) ?? 0.0, Float(rotationComponents[2]) ?? 0.0, Float(rotationComponents[3]) ?? 0.0) 124 | 125 | print("Received position: \(position) and rotation: \(rotation)") 126 | 127 | let point = Point3D(x: position.0, y: position.1, z: position.2) 128 | 129 | let rot = Rotation3D(simd_quatf(ix: rotation.0, iy: rotation.1, iz: rotation.2, r: rotation.3)) 130 | 131 | self.hid_client.send(message: IndigoHIDMessage.camera(Pose3D(position: point, rotation: rot)).as_struct()) 132 | return true 133 | } 134 | 135 | func openTrackHandler(_ data: Data) -> Bool { 136 | print("Trying to decode as OpenTrack data") 137 | guard data.count == 48 else { 138 | return false 139 | } 140 | // Convert it to an array of doubles 141 | let doubles = data.withUnsafeBytes { $0.load(as: [Double].self) } 142 | print("Got doubles: \(doubles)") 143 | guard doubles.count == 6 else { 144 | return false 145 | } 146 | let point = Point3D(x: doubles[0], y: doubles[1], z: doubles[2]) 147 | let euler_angles = EulerAngles(angles: simd_double3(doubles[3], doubles[4], doubles[5]), order: .pitchYawRoll) 148 | let pose = Pose3D(position: point, rotation: Rotation3D(eulerAngles: euler_angles)) 149 | let message = IndigoHIDMessage.camera(pose) 150 | 151 | self.hid_client.send(message: message.as_struct()) 152 | return true 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /SimulatorType/capabilities.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | capabilities 6 | 7 | 720p 8 | 9 | ASTC 10 | 11 | ArtworkTraits 12 | 13 | ArtworkDeviceIdiom 14 | reality 15 | ArtworkDeviceProductDescription 16 | Apple Vision Pro 17 | ArtworkDeviceScaleFactor 18 | 2 19 | ArtworkDeviceSubType 20 | 3648 21 | ArtworkDisplayGamut 22 | P3 23 | ArtworkDynamicDisplayMode 24 | 0 25 | CompatibleDeviceFallback 26 | iPad13,4 27 | DevicePerformanceMemoryClass 28 | 16 29 | GraphicsFeatureSetClass 30 | APPLE8 31 | GraphicsFeatureSetFallbacks 32 | APPLE7:APPLE6:APPLE5:APPLE4:APPLE3:APPLE3v1:APPLE2:APPLE1:GLES2,0 33 | 34 | DeviceCornerRadius 35 | 0.0 36 | DeviceSupports3DImagery 37 | 38 | DeviceSupports3DMaps 39 | 40 | DeviceSupportsAdaptiveMapsUI 41 | 42 | DeviceSupportsAdvancedMapRendering 43 | 44 | DeviceSupportsEnhancedMultitasking 45 | 46 | DeviceSupportsHiResBuildings 47 | 48 | DeviceSupportsSingleDisplayEnhancedMultitasking 49 | 50 | FloatingLiveAppOverlay 51 | 52 | GPSCapability 53 | 54 | HEVCDecoder10bitSupported 55 | 56 | HEVCDecoder12bitSupported 57 | 58 | HEVCDecoder8bitSupported 59 | 60 | HEVCEncodingCapability 61 | 62 | HasThinBezel 63 | 64 | HomeButtonType 65 | 0 66 | MLEHW 67 | 68 | ModelNumber 69 | A2117 70 | PiPOverlay 71 | 72 | PiPPinned 73 | 74 | RegulatoryModelNumber 75 | A2117 76 | ScreenDimensionsCapability 77 | 78 | main-screen-class 79 | 11 80 | main-screen-height 81 | 2732 82 | main-screen-orientation 83 | 0.0 84 | main-screen-pitch 85 | 264 86 | main-screen-scale 87 | 2 88 | main-screen-width 89 | 2048 90 | 91 | SupportsForceTouch 92 | 93 | VGDDUFPWHbX/Ie9RSI0yDQ 94 | 95 | accelerometer 96 | 97 | accessibility 98 | 99 | always-on-time 100 | 101 | applicationInstallation 102 | 103 | arm64 104 | 105 | armv6 106 | 107 | armv7 108 | 109 | armv7s 110 | 111 | bluetooth 112 | 113 | contains-cellular-radio 114 | 115 | device-name 116 | XRGyroControls Vision Pro 117 | displayGamut 118 | P3 119 | displayport 120 | 121 | encrypted-data-partition 122 | 123 | full-6 124 | 125 | gamekit 126 | 127 | gas-gauge-battery 128 | 129 | graphicsClass 130 | 3 131 | graphicsFeatureSetClass 132 | APPLE8 133 | graphicsFeatureSetFallbacks 134 | APPLE7:APPLE6:APPLE5:APPLE4:APPLE3:APPLE3v1:APPLE2:APPLE1:GLES2,0 135 | hide-non-default-apps 136 | 137 | hidpi 138 | 139 | homescreen-wallpaper 140 | 141 | idiom 142 | reality 143 | international-settings 144 | 145 | ipad 146 | 147 | load-thumbnails-while-scrolling 148 | 149 | location-services 150 | 151 | magnetometer 152 | 153 | marketing-name 154 | Apple Vision Pro 155 | memoryClass 156 | 16 157 | metal 158 | 159 | microphone 160 | 161 | modelIdentifier 162 | RealityDevice14,1 163 | multitasking 164 | 165 | opengles-1 166 | 167 | opengles-2 168 | 169 | pearl-id 170 | 171 | peer-peer 172 | 173 | reverse-zoom 174 | 175 | ringer-switch 176 | 177 | screenrecorder 178 | 179 | sms 180 | 181 | software-dimming-alpha 182 | 0 183 | stand-alone-contacts 184 | 185 | subtype 186 | 3648 187 | telephony 188 | 189 | touch-id 190 | 191 | unified-ipod 192 | 193 | watch-companion 194 | 195 | wifi 196 | 197 | 198 | iconState 199 | 200 | buttonBar 201 | 202 | com.apple.mobilesafari 203 | com.apple.mobilemail 204 | com.apple.mobileslideshow 205 | com.apple.Music 206 | 207 | iconLists 208 | 209 | 210 | com.apple.MobileSMS 211 | com.apple.mobilecal 212 | com.apple.mobilenotes 213 | com.apple.reminders 214 | com.apple.Maps 215 | com.apple.youtube 216 | com.apple.videos 217 | com.apple.MobileAddressBook 218 | com.apple.gamecenter 219 | com.apple.MobileStore 220 | com.apple.AppStore 221 | 222 | displayName 223 | Newsstand 224 | iconLists 225 | 226 | 227 | 228 | listType 229 | newsstand 230 | 231 | com.apple.Preferences 232 | 233 | 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /XRGyroControls.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4825CFDE2A48725C0034C938 /* IndigoHID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4825CFDD2A48725C0034C938 /* IndigoHID.swift */; }; 11 | 4842176F2A4F6AD900C5BDA6 /* XRGyroControlsType.simdevicetype in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4842176A2A4F661900C5BDA6 /* XRGyroControlsType.simdevicetype */; }; 12 | 484217722A4F6B4100C5BDA6 /* capabilities.plist in Resources */ = {isa = PBXBuildFile; fileRef = 484217712A4F6B4100C5BDA6 /* capabilities.plist */; }; 13 | 484217742A4F6B6E00C5BDA6 /* profile.plist in Resources */ = {isa = PBXBuildFile; fileRef = 484217732A4F6B6E00C5BDA6 /* profile.plist */; }; 14 | 48B9A8FD2A4CC594000208F4 /* UDPServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48B9A8FC2A4CC594000208F4 /* UDPServer.swift */; }; 15 | 48BBE94A2A44D80A005E4CF8 /* SimulatorSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48BBE9492A44D80A005E4CF8 /* SimulatorSupport.swift */; }; 16 | 48BD02ED2A44DCF6005E818E /* XRGyroControlsUI.simdeviceui in CopyFiles */ = {isa = PBXBuildFile; fileRef = 48BBE9422A44D6CA005E4CF8 /* XRGyroControlsUI.simdeviceui */; }; 17 | 48BDCD6C2A478808009ABEF4 /* CoreSimulator in Frameworks */ = {isa = PBXBuildFile; fileRef = 48BDCD6B2A478808009ABEF4 /* CoreSimulator */; }; 18 | 48BDCD6E2A47882C009ABEF4 /* SimulatorKit in Frameworks */ = {isa = PBXBuildFile; fileRef = 48BDCD6D2A47882C009ABEF4 /* SimulatorKit */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXCopyFilesBuildPhase section */ 22 | 4842176E2A4F6AC900C5BDA6 /* CopyFiles */ = { 23 | isa = PBXCopyFilesBuildPhase; 24 | buildActionMask = 2147483647; 25 | dstPath = "$(SYSTEM_DEVELOPER_DIR)/Platforms/XROS.platform/Library/Developer/CoreSimulator/Profiles/DeviceTypes"; 26 | dstSubfolderSpec = 0; 27 | files = ( 28 | 4842176F2A4F6AD900C5BDA6 /* XRGyroControlsType.simdevicetype in CopyFiles */, 29 | ); 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | 48BD02EC2A44DCED005E818E /* CopyFiles */ = { 33 | isa = PBXCopyFilesBuildPhase; 34 | buildActionMask = 2147483647; 35 | dstPath = "$(SYSTEM_DEVELOPER_DIR)/Platforms/XROS.platform/Library/Developer/CoreSimulator/Profiles/UserInterface"; 36 | dstSubfolderSpec = 0; 37 | files = ( 38 | 48BD02ED2A44DCF6005E818E /* XRGyroControlsUI.simdeviceui in CopyFiles */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXCopyFilesBuildPhase section */ 43 | 44 | /* Begin PBXFileReference section */ 45 | 4825CFDD2A48725C0034C938 /* IndigoHID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndigoHID.swift; sourceTree = ""; }; 46 | 4842176A2A4F661900C5BDA6 /* XRGyroControlsType.simdevicetype */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XRGyroControlsType.simdevicetype; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 484217712A4F6B4100C5BDA6 /* capabilities.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = capabilities.plist; sourceTree = ""; }; 48 | 484217732A4F6B6E00C5BDA6 /* profile.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = profile.plist; sourceTree = ""; }; 49 | 48B9A8FB2A4A1393000208F4 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 50 | 48B9A8FC2A4CC594000208F4 /* UDPServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPServer.swift; sourceTree = ""; }; 51 | 48BBE9422A44D6CA005E4CF8 /* XRGyroControlsUI.simdeviceui */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XRGyroControlsUI.simdeviceui; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 48BBE9492A44D80A005E4CF8 /* SimulatorSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimulatorSupport.swift; sourceTree = ""; }; 53 | 48BDCD6B2A478808009ABEF4 /* CoreSimulator */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = CoreSimulator; path = ../../../../Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/CoreSimulator; sourceTree = ""; }; 54 | 48BDCD6D2A47882C009ABEF4 /* SimulatorKit */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = SimulatorKit; path = "/Applications/Xcode-beta.app/Contents/Developer/Library/PrivateFrameworks/SimulatorKit.framework/Versions/A/SimulatorKit"; sourceTree = ""; }; 55 | 48BDCD702A4799C9009ABEF4 /* SimulatorKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SimulatorKit.swift; path = SimulatorKit/SimulatorKit.swift; sourceTree = ""; }; 56 | 48BDCD722A4799D3009ABEF4 /* CoreSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreSimulator.h; path = CoreSimulator/CoreSimulator.h; sourceTree = ""; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | 484217672A4F661900C5BDA6 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | 48BBE93F2A44D6CA005E4CF8 /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | 48BDCD6E2A47882C009ABEF4 /* SimulatorKit in Frameworks */, 72 | 48BDCD6C2A478808009ABEF4 /* CoreSimulator in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 484217702A4F6B2600C5BDA6 /* SimulatorType */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 484217712A4F6B4100C5BDA6 /* capabilities.plist */, 83 | 484217732A4F6B6E00C5BDA6 /* profile.plist */, 84 | ); 85 | path = SimulatorType; 86 | sourceTree = ""; 87 | }; 88 | 48BBE9392A44D6CA005E4CF8 = { 89 | isa = PBXGroup; 90 | children = ( 91 | 484217702A4F6B2600C5BDA6 /* SimulatorType */, 92 | 48B9A8FC2A4CC594000208F4 /* UDPServer.swift */, 93 | 48B9A8FB2A4A1393000208F4 /* README.md */, 94 | 4825CFDD2A48725C0034C938 /* IndigoHID.swift */, 95 | 48BBE9492A44D80A005E4CF8 /* SimulatorSupport.swift */, 96 | 48BBE9432A44D6CA005E4CF8 /* Products */, 97 | 48BD02EE2A44DF64005E818E /* Frameworks */, 98 | ); 99 | sourceTree = ""; 100 | }; 101 | 48BBE9432A44D6CA005E4CF8 /* Products */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 48BBE9422A44D6CA005E4CF8 /* XRGyroControlsUI.simdeviceui */, 105 | 4842176A2A4F661900C5BDA6 /* XRGyroControlsType.simdevicetype */, 106 | ); 107 | name = Products; 108 | sourceTree = ""; 109 | }; 110 | 48BD02EE2A44DF64005E818E /* Frameworks */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 48BDCD722A4799D3009ABEF4 /* CoreSimulator.h */, 114 | 48BDCD702A4799C9009ABEF4 /* SimulatorKit.swift */, 115 | 48BDCD6D2A47882C009ABEF4 /* SimulatorKit */, 116 | 48BDCD6B2A478808009ABEF4 /* CoreSimulator */, 117 | ); 118 | name = Frameworks; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | 484217692A4F661900C5BDA6 /* XRGyroControlsType */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = 4842176D2A4F661900C5BDA6 /* Build configuration list for PBXNativeTarget "XRGyroControlsType" */; 127 | buildPhases = ( 128 | 484217662A4F661900C5BDA6 /* Sources */, 129 | 484217672A4F661900C5BDA6 /* Frameworks */, 130 | 484217682A4F661900C5BDA6 /* Resources */, 131 | 4842176E2A4F6AC900C5BDA6 /* CopyFiles */, 132 | ); 133 | buildRules = ( 134 | ); 135 | dependencies = ( 136 | ); 137 | name = XRGyroControlsType; 138 | productName = "XRGyroControls Vision Pro"; 139 | productReference = 4842176A2A4F661900C5BDA6 /* XRGyroControlsType.simdevicetype */; 140 | productType = "com.apple.product-type.bundle"; 141 | }; 142 | 48BBE9412A44D6CA005E4CF8 /* XRGyroControlsUI */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 48BBE9462A44D6CA005E4CF8 /* Build configuration list for PBXNativeTarget "XRGyroControlsUI" */; 145 | buildPhases = ( 146 | 48BDCD6F2A47975D009ABEF4 /* ShellScript */, 147 | 48BBE93E2A44D6CA005E4CF8 /* Sources */, 148 | 48BBE93F2A44D6CA005E4CF8 /* Frameworks */, 149 | 48BBE9402A44D6CA005E4CF8 /* Resources */, 150 | 48BD02EC2A44DCED005E818E /* CopyFiles */, 151 | ); 152 | buildRules = ( 153 | ); 154 | dependencies = ( 155 | ); 156 | name = XRGyroControlsUI; 157 | productName = XROS; 158 | productReference = 48BBE9422A44D6CA005E4CF8 /* XRGyroControlsUI.simdeviceui */; 159 | productType = "com.apple.product-type.bundle"; 160 | }; 161 | /* End PBXNativeTarget section */ 162 | 163 | /* Begin PBXProject section */ 164 | 48BBE93A2A44D6CA005E4CF8 /* Project object */ = { 165 | isa = PBXProject; 166 | attributes = { 167 | BuildIndependentTargetsInParallel = 1; 168 | LastUpgradeCheck = 1500; 169 | TargetAttributes = { 170 | 484217692A4F661900C5BDA6 = { 171 | CreatedOnToolsVersion = 15.0; 172 | }; 173 | 48BBE9412A44D6CA005E4CF8 = { 174 | CreatedOnToolsVersion = 15.0; 175 | LastSwiftMigration = 1500; 176 | }; 177 | }; 178 | }; 179 | buildConfigurationList = 48BBE93D2A44D6CA005E4CF8 /* Build configuration list for PBXProject "XRGyroControls" */; 180 | compatibilityVersion = "Xcode 14.0"; 181 | developmentRegion = en; 182 | hasScannedForEncodings = 0; 183 | knownRegions = ( 184 | en, 185 | Base, 186 | ); 187 | mainGroup = 48BBE9392A44D6CA005E4CF8; 188 | productRefGroup = 48BBE9432A44D6CA005E4CF8 /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | 48BBE9412A44D6CA005E4CF8 /* XRGyroControlsUI */, 193 | 484217692A4F661900C5BDA6 /* XRGyroControlsType */, 194 | ); 195 | }; 196 | /* End PBXProject section */ 197 | 198 | /* Begin PBXResourcesBuildPhase section */ 199 | 484217682A4F661900C5BDA6 /* Resources */ = { 200 | isa = PBXResourcesBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | 484217742A4F6B6E00C5BDA6 /* profile.plist in Resources */, 204 | 484217722A4F6B4100C5BDA6 /* capabilities.plist in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | 48BBE9402A44D6CA005E4CF8 /* Resources */ = { 209 | isa = PBXResourcesBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | ); 213 | runOnlyForDeploymentPostprocessing = 0; 214 | }; 215 | /* End PBXResourcesBuildPhase section */ 216 | 217 | /* Begin PBXShellScriptBuildPhase section */ 218 | 48BDCD6F2A47975D009ABEF4 /* ShellScript */ = { 219 | isa = PBXShellScriptBuildPhase; 220 | buildActionMask = 2147483647; 221 | files = ( 222 | ); 223 | inputFileListPaths = ( 224 | ); 225 | inputPaths = ( 226 | "$(SRCROOT)/SimulatorKit/SimulatorKit.swift", 227 | "$(SRCROOT)/CoreSimulator/module.modulemap", 228 | "$(SRCROOT)/CoreSimulator/CoreSimulator.h", 229 | ); 230 | outputFileListPaths = ( 231 | ); 232 | outputPaths = ( 233 | "$(DERIVED_FILE_DIR)/SimulatorKit.swiftmodule", 234 | ); 235 | runOnlyForDeploymentPostprocessing = 0; 236 | shellPath = /bin/sh; 237 | shellScript = "# Compile SimulatorKit module\nswiftc -emit-module $SRCROOT/SimulatorKit/SimulatorKit.swift -module-name SimulatorKit -I $SRCROOT/CoreSimulator -avoid-emit-module-source-info -emit-module-path $DERIVED_FILES_DIR -Onone\n"; 238 | }; 239 | /* End PBXShellScriptBuildPhase section */ 240 | 241 | /* Begin PBXSourcesBuildPhase section */ 242 | 484217662A4F661900C5BDA6 /* Sources */ = { 243 | isa = PBXSourcesBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | ); 247 | runOnlyForDeploymentPostprocessing = 0; 248 | }; 249 | 48BBE93E2A44D6CA005E4CF8 /* Sources */ = { 250 | isa = PBXSourcesBuildPhase; 251 | buildActionMask = 2147483647; 252 | files = ( 253 | 48BBE94A2A44D80A005E4CF8 /* SimulatorSupport.swift in Sources */, 254 | 4825CFDE2A48725C0034C938 /* IndigoHID.swift in Sources */, 255 | 48B9A8FD2A4CC594000208F4 /* UDPServer.swift in Sources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | /* End PBXSourcesBuildPhase section */ 260 | 261 | /* Begin XCBuildConfiguration section */ 262 | 4842176B2A4F661900C5BDA6 /* Debug */ = { 263 | isa = XCBuildConfiguration; 264 | buildSettings = { 265 | CODE_SIGN_STYLE = Automatic; 266 | COMBINE_HIDPI_IMAGES = YES; 267 | CURRENT_PROJECT_VERSION = 1; 268 | GENERATE_INFOPLIST_FILE = YES; 269 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 270 | INFOPLIST_KEY_NSPrincipalClass = ""; 271 | MARKETING_VERSION = 1.0; 272 | PRODUCT_BUNDLE_IDENTIFIER = dev.jjtech.XRGyroControls.SimDeviceType; 273 | PRODUCT_NAME = "$(TARGET_NAME)"; 274 | SKIP_INSTALL = YES; 275 | SWIFT_EMIT_LOC_STRINGS = YES; 276 | WRAPPER_EXTENSION = simdevicetype; 277 | }; 278 | name = Debug; 279 | }; 280 | 4842176C2A4F661900C5BDA6 /* Release */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | CODE_SIGN_STYLE = Automatic; 284 | COMBINE_HIDPI_IMAGES = YES; 285 | CURRENT_PROJECT_VERSION = 1; 286 | GENERATE_INFOPLIST_FILE = YES; 287 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 288 | INFOPLIST_KEY_NSPrincipalClass = ""; 289 | MARKETING_VERSION = 1.0; 290 | PRODUCT_BUNDLE_IDENTIFIER = dev.jjtech.XRGyroControls.SimDeviceType; 291 | PRODUCT_NAME = "$(TARGET_NAME)"; 292 | SKIP_INSTALL = YES; 293 | SWIFT_EMIT_LOC_STRINGS = YES; 294 | WRAPPER_EXTENSION = simdevicetype; 295 | }; 296 | name = Release; 297 | }; 298 | 48BBE9442A44D6CA005E4CF8 /* Debug */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ALWAYS_SEARCH_USER_PATHS = NO; 302 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 303 | CLANG_ANALYZER_NONNULL = YES; 304 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 305 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 306 | CLANG_ENABLE_MODULES = YES; 307 | CLANG_ENABLE_OBJC_ARC = YES; 308 | CLANG_ENABLE_OBJC_WEAK = YES; 309 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 310 | CLANG_WARN_BOOL_CONVERSION = YES; 311 | CLANG_WARN_COMMA = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 314 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 315 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 316 | CLANG_WARN_EMPTY_BODY = YES; 317 | CLANG_WARN_ENUM_CONVERSION = YES; 318 | CLANG_WARN_INFINITE_RECURSION = YES; 319 | CLANG_WARN_INT_CONVERSION = YES; 320 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 321 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 322 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 323 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 324 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 325 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 326 | CLANG_WARN_STRICT_PROTOTYPES = YES; 327 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 328 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 329 | CLANG_WARN_UNREACHABLE_CODE = YES; 330 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 331 | COPY_PHASE_STRIP = NO; 332 | DEBUG_INFORMATION_FORMAT = dwarf; 333 | ENABLE_STRICT_OBJC_MSGSEND = YES; 334 | ENABLE_TESTABILITY = YES; 335 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 336 | GCC_C_LANGUAGE_STANDARD = gnu17; 337 | GCC_DYNAMIC_NO_PIC = NO; 338 | GCC_NO_COMMON_BLOCKS = YES; 339 | GCC_OPTIMIZATION_LEVEL = 0; 340 | GCC_PREPROCESSOR_DEFINITIONS = ( 341 | "DEBUG=1", 342 | "$(inherited)", 343 | ); 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 346 | GCC_WARN_UNDECLARED_SELECTOR = YES; 347 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 348 | GCC_WARN_UNUSED_FUNCTION = YES; 349 | GCC_WARN_UNUSED_VARIABLE = YES; 350 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 351 | MACOSX_DEPLOYMENT_TARGET = 13.4; 352 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 353 | MTL_FAST_MATH = YES; 354 | ONLY_ACTIVE_ARCH = YES; 355 | SDKROOT = macosx; 356 | }; 357 | name = Debug; 358 | }; 359 | 48BBE9452A44D6CA005E4CF8 /* Release */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | ALWAYS_SEARCH_USER_PATHS = NO; 363 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 364 | CLANG_ANALYZER_NONNULL = YES; 365 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 366 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 367 | CLANG_ENABLE_MODULES = YES; 368 | CLANG_ENABLE_OBJC_ARC = YES; 369 | CLANG_ENABLE_OBJC_WEAK = YES; 370 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 371 | CLANG_WARN_BOOL_CONVERSION = YES; 372 | CLANG_WARN_COMMA = YES; 373 | CLANG_WARN_CONSTANT_CONVERSION = YES; 374 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 375 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 376 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 377 | CLANG_WARN_EMPTY_BODY = YES; 378 | CLANG_WARN_ENUM_CONVERSION = YES; 379 | CLANG_WARN_INFINITE_RECURSION = YES; 380 | CLANG_WARN_INT_CONVERSION = YES; 381 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 382 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 383 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 384 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 385 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 386 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 387 | CLANG_WARN_STRICT_PROTOTYPES = YES; 388 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 389 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 390 | CLANG_WARN_UNREACHABLE_CODE = YES; 391 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 392 | COPY_PHASE_STRIP = NO; 393 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 394 | ENABLE_NS_ASSERTIONS = NO; 395 | ENABLE_STRICT_OBJC_MSGSEND = YES; 396 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 397 | GCC_C_LANGUAGE_STANDARD = gnu17; 398 | GCC_NO_COMMON_BLOCKS = YES; 399 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 400 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 401 | GCC_WARN_UNDECLARED_SELECTOR = YES; 402 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 403 | GCC_WARN_UNUSED_FUNCTION = YES; 404 | GCC_WARN_UNUSED_VARIABLE = YES; 405 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 406 | MACOSX_DEPLOYMENT_TARGET = 13.4; 407 | MTL_ENABLE_DEBUG_INFO = NO; 408 | MTL_FAST_MATH = YES; 409 | SDKROOT = macosx; 410 | }; 411 | name = Release; 412 | }; 413 | 48BBE9472A44D6CA005E4CF8 /* Debug */ = { 414 | isa = XCBuildConfiguration; 415 | buildSettings = { 416 | CLANG_ENABLE_MODULES = YES; 417 | COMBINE_HIDPI_IMAGES = YES; 418 | CURRENT_PROJECT_VERSION = 1; 419 | GENERATE_INFOPLIST_FILE = YES; 420 | INFOPLIST_KEY_NSPrincipalClass = XRGyroControlsUI.SimulatorSupport; 421 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 422 | MARKETING_VERSION = 1.0; 423 | PRODUCT_BUNDLE_IDENTIFIER = dev.jjtech.XRGyroControls.SimDeviceUI; 424 | PRODUCT_NAME = "$(TARGET_NAME)"; 425 | SKIP_INSTALL = YES; 426 | SWIFT_EMIT_LOC_STRINGS = YES; 427 | SWIFT_INCLUDE_PATHS = "$(DERIVED_FILE_DIR)"; 428 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 429 | SWIFT_VERSION = 5.0; 430 | WRAPPER_EXTENSION = simdeviceui; 431 | }; 432 | name = Debug; 433 | }; 434 | 48BBE9482A44D6CA005E4CF8 /* Release */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | CLANG_ENABLE_MODULES = YES; 438 | COMBINE_HIDPI_IMAGES = YES; 439 | CURRENT_PROJECT_VERSION = 1; 440 | GENERATE_INFOPLIST_FILE = YES; 441 | INFOPLIST_KEY_NSPrincipalClass = XRGyroControlsUI.SimulatorSupport; 442 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; 443 | MARKETING_VERSION = 1.0; 444 | PRODUCT_BUNDLE_IDENTIFIER = dev.jjtech.XRGyroControls.SimDeviceUI; 445 | PRODUCT_NAME = "$(TARGET_NAME)"; 446 | SKIP_INSTALL = YES; 447 | SWIFT_EMIT_LOC_STRINGS = YES; 448 | SWIFT_INCLUDE_PATHS = "$(DERIVED_FILE_DIR)"; 449 | SWIFT_VERSION = 5.0; 450 | WRAPPER_EXTENSION = simdeviceui; 451 | }; 452 | name = Release; 453 | }; 454 | /* End XCBuildConfiguration section */ 455 | 456 | /* Begin XCConfigurationList section */ 457 | 4842176D2A4F661900C5BDA6 /* Build configuration list for PBXNativeTarget "XRGyroControlsType" */ = { 458 | isa = XCConfigurationList; 459 | buildConfigurations = ( 460 | 4842176B2A4F661900C5BDA6 /* Debug */, 461 | 4842176C2A4F661900C5BDA6 /* Release */, 462 | ); 463 | defaultConfigurationIsVisible = 0; 464 | defaultConfigurationName = Release; 465 | }; 466 | 48BBE93D2A44D6CA005E4CF8 /* Build configuration list for PBXProject "XRGyroControls" */ = { 467 | isa = XCConfigurationList; 468 | buildConfigurations = ( 469 | 48BBE9442A44D6CA005E4CF8 /* Debug */, 470 | 48BBE9452A44D6CA005E4CF8 /* Release */, 471 | ); 472 | defaultConfigurationIsVisible = 0; 473 | defaultConfigurationName = Release; 474 | }; 475 | 48BBE9462A44D6CA005E4CF8 /* Build configuration list for PBXNativeTarget "XRGyroControlsUI" */ = { 476 | isa = XCConfigurationList; 477 | buildConfigurations = ( 478 | 48BBE9472A44D6CA005E4CF8 /* Debug */, 479 | 48BBE9482A44D6CA005E4CF8 /* Release */, 480 | ); 481 | defaultConfigurationIsVisible = 0; 482 | defaultConfigurationName = Release; 483 | }; 484 | /* End XCConfigurationList section */ 485 | }; 486 | rootObject = 48BBE93A2A44D6CA005E4CF8 /* Project object */; 487 | } 488 | --------------------------------------------------------------------------------