├── Example Project ├── Packages │ └── RealityKitContent │ │ ├── README.md │ │ ├── Sources │ │ └── RealityKitContent │ │ │ ├── RealityKitContent.swift │ │ │ └── RealityKitContent.rkassets │ │ │ ├── Scene.usda │ │ │ └── Materials │ │ │ └── GridMaterial.usda │ │ ├── Package.realitycomposerpro │ │ ├── WorkspaceData │ │ │ ├── Settings.rcprojectdata │ │ │ └── SceneMetadataList.json │ │ └── ProjectData │ │ │ └── main.json │ │ └── Package.swift ├── VisionPanesExample │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── AppIcon.solidimagestack │ │ │ ├── Back.solidimagestacklayer │ │ │ ├── Contents.json │ │ │ └── Content.imageset │ │ │ │ └── Contents.json │ │ │ ├── Front.solidimagestacklayer │ │ │ ├── Contents.json │ │ │ └── Content.imageset │ │ │ │ └── Contents.json │ │ │ ├── Middle.solidimagestacklayer │ │ │ ├── Contents.json │ │ │ └── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── Example_ProjectApp.swift │ ├── Tests │ │ └── VisionPanesTests │ │ │ └── VisionPanesTests.swift │ ├── Info.plist │ ├── SameEdge.swift │ └── ContentView.swift └── Example Project.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ ├── xcshareddata │ └── xcschemes │ │ └── Example Project.xcscheme │ └── project.pbxproj ├── .gitignore ├── .swiftpm └── xcode │ ├── package.xcworkspace │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ └── xcschemes │ ├── VisionPanesExample.xcscheme │ └── VisionPanes.xcscheme ├── Package.swift ├── Sources └── VisionPanes │ ├── MultiPaneViewConfiguration.swift │ ├── MultiPaneView.swift │ ├── PaneViewModifier.swift │ └── MultiPaneViewController.swift ├── LICENSE └── README.md /Example Project/Packages/RealityKitContent/README.md: -------------------------------------------------------------------------------- 1 | # RealityKitContent 2 | 3 | A description of this package. -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example Project/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Bundle for the RealityKitContent project 4 | public let realityKitContentBundle = Bundle.module 5 | -------------------------------------------------------------------------------- /Example Project/Example Project.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "vision", 5 | "scale" : "2x" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "vision", 5 | "scale" : "2x" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "vision", 5 | "scale" : "2x" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example Project/Example Project.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Example_ProjectApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Example_ProjectApp.swift 3 | // Example Project 4 | // 5 | // Created by Laksh Chakraborty on 3/5/24. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct Example_ProjectApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | .windowStyle(.plain) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Example Project/Packages/RealityKitContent/Package.realitycomposerpro/WorkspaceData/Settings.rcprojectdata: -------------------------------------------------------------------------------- 1 | { 2 | "cameraPresets" : { 3 | 4 | }, 5 | "secondaryToolbarData" : { 6 | "isGridVisible" : true, 7 | "sceneReverbPreset" : -1 8 | }, 9 | "unitDefaults" : { 10 | "°" : "°", 11 | "kg" : "g", 12 | "m" : "cm", 13 | "m\/s" : "m\/s", 14 | "m\/s²" : "m\/s²", 15 | "s" : "s" 16 | } 17 | } -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Assets.xcassets/AppIcon.solidimagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "layers" : [ 7 | { 8 | "filename" : "Front.solidimagestacklayer" 9 | }, 10 | { 11 | "filename" : "Middle.solidimagestacklayer" 12 | }, 13 | { 14 | "filename" : "Back.solidimagestacklayer" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Tests/VisionPanesTests/VisionPanesTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import VisionPanes 3 | 4 | final class VisionPanesTests: XCTestCase { 5 | func testExample() throws { 6 | // XCTest Documentation 7 | // https://developer.apple.com/documentation/xctest 8 | 9 | // Defining Test Cases and Test Methods 10 | // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationPreferredDefaultSceneSessionRole 8 | UIWindowSceneSessionRoleApplication 9 | UIApplicationSupportsMultipleScenes 10 | 11 | UISceneConfigurations 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.10 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "VisionPanes", 8 | platforms: [ 9 | .visionOS(.v1) 10 | ], 11 | products: [ 12 | // Products define the executables and libraries a package produces, making them visible to other packages. 13 | .library( 14 | name: "VisionPanes", 15 | targets: ["VisionPanes"]), 16 | ], 17 | targets: [ 18 | // Targets are the basic building blocks of a package, defining a module or a test suite. 19 | // Targets can depend on other targets in this package and products from dependencies. 20 | .target( 21 | name: "VisionPanes"), 22 | ] 23 | ) 24 | -------------------------------------------------------------------------------- /Sources/VisionPanes/MultiPaneViewConfiguration.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Laksh Chakraborty on 3/5/24. 6 | // 7 | 8 | import Foundation 9 | 10 | struct MultiPaneViewConfiguration { 11 | var placement: PanePlacement 12 | } 13 | 14 | public enum PanePlacement { 15 | case leading(width: CGFloat = 300, spacing: CGFloat = 16) 16 | case trailing(width: CGFloat = 300, spacing: CGFloat = 16) 17 | case top(height: CGFloat = 200, spacing: CGFloat = 16) 18 | case bottom(height: CGFloat = 200, spacing: CGFloat = 16) 19 | 20 | public static var leading: Self { 21 | return .leading() 22 | } 23 | 24 | public static var trailing: Self { 25 | return .trailing() 26 | } 27 | 28 | public static var top: Self { 29 | return .top() 30 | } 31 | 32 | public static var bottom: Self { 33 | return .bottom() 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Example Project/Packages/RealityKitContent/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.9 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "RealityKitContent", 8 | products: [ 9 | // Products define the executables and libraries a package produces, and make them visible to other packages. 10 | .library( 11 | name: "RealityKitContent", 12 | targets: ["RealityKitContent"]), 13 | ], 14 | dependencies: [ 15 | // Dependencies declare other packages that this package depends on. 16 | // .package(url: /* package url */, from: "1.0.0"), 17 | ], 18 | targets: [ 19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 20 | // Targets can depend on other targets in this package, and on products in packages this package depends on. 21 | .target( 22 | name: "RealityKitContent", 23 | dependencies: []), 24 | ] 25 | ) -------------------------------------------------------------------------------- /Example Project/Packages/RealityKitContent/Package.realitycomposerpro/ProjectData/main.json: -------------------------------------------------------------------------------- 1 | { 2 | "pathsToIds" : { 3 | "\/RealityKitContent\/Sources\/RealityKitContent\/RealityKitContent.rkassets\/GridMaterial.usda" : "440DE5B4-E4E4-459B-AABF-9ACE96319272", 4 | "\/RealityKitContent\/Sources\/RealityKitContent\/RealityKitContent.rkassets\/procedural_sphere_grid.usda" : "34C460AE-CA1B-4348-BD05-621ACBDFFE97", 5 | "\/RealityKitContent\/Sources\/RealityKitContent\/RealityKitContent.rkassets\/Scene.usda" : "0A9B4653-B11E-4D6A-850E-C6FCB621626C", 6 | "\/RealityKitContent\/Sources\/RealityKitContent\/RealityKitContent.rkassets\/Untitled Scene.usda" : "03E02005-EFA6-48D6-8A76-05B2822A74E9", 7 | "RealityKitContent\/Sources\/RealityKitContent\/RealityKitContent.rkassets\/GridMaterial.usda" : "FBD8436F-6B8B-4B82-99B5-995D538B4704", 8 | "RealityKitContent\/Sources\/RealityKitContent\/RealityKitContent.rkassets\/procedural_sphere_grid.usda" : "1CBF3893-ABFD-408C-8B91-045BFD257808", 9 | "RealityKitContent\/Sources\/RealityKitContent\/RealityKitContent.rkassets\/Scene.usda" : "26DBAE76-5DD8-47B6-A085-1B4ADA111097" 10 | } 11 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Laksh Chakraborty 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Sources/VisionPanes/MultiPaneView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIView.swift 3 | // 4 | // 5 | // Created by Laksh Chakraborty on 3/5/24. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct MultiPaneView: UIViewControllerRepresentable where Item: Identifiable, MainView: View, PaneView: View { 11 | var item: Item? 12 | var configuration: MultiPaneViewConfiguration 13 | 14 | @ViewBuilder var mainView: () -> MainView 15 | @ViewBuilder var paneView: () -> PaneView 16 | 17 | func makeUIViewController(context: Context) -> MultiPaneViewController { 18 | let viewController = MultiPaneViewController( 19 | item: item, 20 | configuration: configuration, 21 | mainView: mainView(), 22 | paneView: paneView() 23 | ) 24 | return viewController 25 | } 26 | 27 | func updateUIViewController( 28 | _ uiViewController: MultiPaneViewController, 29 | context: Context 30 | ) { 31 | uiViewController.item = item 32 | uiViewController.configuration = configuration 33 | 34 | // Make sure the item has changed when updating geometry 35 | if uiViewController.item?.id != uiViewController.previousItem?.id { 36 | uiViewController._updateWindowGeometry() 37 | } 38 | 39 | uiViewController.previousItem = item 40 | 41 | uiViewController.paneController?.rootView = paneView() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/SameEdge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SameEdge.swift 3 | // VisionPanesExample 4 | // 5 | // Created by Laksh Chakraborty on 3/6/24. 6 | // 7 | 8 | import SwiftUI 9 | import VisionPanes 10 | 11 | // MARK: - Example view for panes along same edge 12 | struct SameEdge: View { 13 | @State var item: Item? 14 | @State var item2: Item? 15 | 16 | var body: some View { 17 | VStack { 18 | Button("Show Pane 1") { 19 | if item == nil { 20 | item = Item(id: "1", text: "Pane 1") 21 | } else { 22 | item = nil 23 | } 24 | } 25 | 26 | Button("Show Pane 2") { 27 | if item2 == nil { 28 | item2 = Item(id: "1", text: "Pane 2") 29 | } else { 30 | item2 = nil 31 | } 32 | } 33 | } 34 | .frame(maxWidth: .infinity, maxHeight: .infinity) 35 | .glassBackgroundEffect() 36 | .pane(item: item, placement: .trailing) { item in 37 | Text(item.text) 38 | .frame(maxWidth: .infinity, maxHeight: .infinity) 39 | .glassBackgroundEffect() 40 | } 41 | .pane(item: item2, placement: .trailing) { item in 42 | Text(item.text) 43 | .frame(maxWidth: .infinity, maxHeight: .infinity) 44 | .glassBackgroundEffect() 45 | } 46 | } 47 | } 48 | 49 | // MARK: - Previews 50 | #Preview { 51 | SameEdge() 52 | } 53 | -------------------------------------------------------------------------------- /Example Project/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Scene.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | defaultPrim = "Root" 4 | metersPerUnit = 1 5 | upAxis = "Y" 6 | ) 7 | 8 | def Xform "Root" 9 | { 10 | reorder nameChildren = ["GridMaterial", "Sphere"] 11 | rel material:binding = None ( 12 | bindMaterialAs = "weakerThanDescendants" 13 | ) 14 | 15 | def Sphere "Sphere" ( 16 | active = true 17 | prepend apiSchemas = ["MaterialBindingAPI"] 18 | ) 19 | { 20 | rel material:binding = ( 21 | bindMaterialAs = "weakerThanDescendants" 22 | ) 23 | double radius = 0.05 24 | quatf xformOp:orient = (1, 0, 0, 0) 25 | float3 xformOp:scale = (1, 1, 1) 26 | float3 xformOp:translate = (0, 0, 0.0004) 27 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] 28 | 29 | def RealityKitComponent "Collider" 30 | { 31 | uint group = 1 32 | uniform token info:id = "RealityKit.Collider" 33 | uint mask = 4294967295 34 | token type = "Default" 35 | 36 | def RealityKitStruct "Shape" 37 | { 38 | float3 extent = (0.2, 0.2, 0.2) 39 | float radius = 0.05 40 | token shapeType = "Sphere" 41 | } 42 | } 43 | 44 | def RealityKitComponent "InputTarget" 45 | { 46 | uniform token info:id = "RealityKit.InputTarget" 47 | } 48 | } 49 | 50 | def "GridMaterial" ( 51 | active = true 52 | prepend references = @Materials/GridMaterial.usda@ 53 | ) 54 | { 55 | float3 xformOp:scale = (1, 1, 1) 56 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /Sources/VisionPanes/PaneViewModifier.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | private struct PaneViewModifier: ViewModifier where Item: Identifiable & Equatable, PaneContent: View { 4 | var item: Item? 5 | @State var lastItem: Item? = nil 6 | 7 | var placement: PanePlacement 8 | 9 | @ViewBuilder var paneContent: (Item) -> PaneContent 10 | 11 | var opacity: CGFloat { 12 | item == nil ? 0 : 1 13 | } 14 | 15 | var offset: CGFloat { 16 | item == nil ? -64 : 0 17 | } 18 | 19 | func body(content: Content) -> some View { 20 | MultiPaneView(item: item, configuration: MultiPaneViewConfiguration(placement: placement)) { 21 | content 22 | } paneView: { 23 | VStack { 24 | VStack { 25 | if let lastItem { 26 | paneContent(item ?? lastItem) 27 | } 28 | } 29 | .frame(maxWidth: .infinity, maxHeight: .infinity) 30 | .opacity(opacity) 31 | .offset(z: offset) 32 | } 33 | .animation(.spring(duration: 0.3), value: item) 34 | .onChange(of: item) { oldValue, newValue in 35 | if let newValue { 36 | self.lastItem = newValue 37 | } 38 | } 39 | } 40 | 41 | } 42 | } 43 | 44 | extension View { 45 | public func pane( 46 | item: Item?, 47 | placement: PanePlacement = .trailing, 48 | @ViewBuilder paneContent: @escaping (Item) -> PaneContent 49 | ) -> some View where Item: Identifiable & Equatable, PaneContent: View { 50 | modifier( 51 | PaneViewModifier( 52 | item: item, 53 | placement: placement, 54 | paneContent: paneContent 55 | ) 56 | ) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.swiftpm/xcode/xcshareddata/xcschemes/VisionPanesExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Example Project/VisionPanesExample/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Example Project 4 | // 5 | // Created by Laksh Chakraborty on 3/5/24. 6 | // 7 | 8 | import SwiftUI 9 | import VisionPanes 10 | 11 | // MARK: - Example item struct, must be Identifiable and Equatable 12 | struct Item: Identifiable, Equatable { 13 | var id: String 14 | var text: String 15 | } 16 | 17 | // MARK: - Example Simple View 18 | struct ContentView: View { 19 | @State var item: Item? 20 | @State var item2: Item? 21 | @State var item3: Item? 22 | @State var item4: Item? 23 | 24 | var body: some View { 25 | VStack { 26 | Button("Show Leading Pane") { 27 | if item == nil { 28 | item = Item(id: "1", text: "Leading Pane") 29 | } else { 30 | item = nil 31 | } 32 | } 33 | 34 | Button("Show Trailing Pane") { 35 | if item2 == nil { 36 | item2 = Item(id: "1", text: "Leading Pane") 37 | } else { 38 | item2 = nil 39 | } 40 | } 41 | 42 | Button("Show Top Pane") { 43 | if item3 == nil { 44 | item3 = Item(id: "1", text: "Leading Pane") 45 | } else { 46 | item3 = nil 47 | } 48 | } 49 | 50 | Button("Show Bottom Pane") { 51 | if item4 == nil { 52 | item4 = Item(id: "1", text: "Leading Pane") 53 | } else { 54 | item4 = nil 55 | } 56 | } 57 | } 58 | .frame(maxWidth: .infinity, maxHeight: .infinity) 59 | .glassBackgroundEffect() 60 | .pane(item: item, placement: .leading) { item in 61 | Text(item.text) 62 | .frame(maxWidth: .infinity, maxHeight: .infinity) 63 | .glassBackgroundEffect() 64 | } 65 | .pane(item: item2, placement: .trailing) { item in 66 | Text(item.text) 67 | .frame(maxWidth: .infinity, maxHeight: .infinity) 68 | .glassBackgroundEffect() 69 | } 70 | .pane(item: item3, placement: .top) { item in 71 | Text(item.text) 72 | .frame(maxWidth: .infinity, maxHeight: .infinity) 73 | .glassBackgroundEffect() 74 | } 75 | .pane(item: item4, placement: .bottom) { item in 76 | Text(item.text) 77 | .frame(maxWidth: .infinity, maxHeight: .infinity) 78 | .glassBackgroundEffect() 79 | } 80 | } 81 | } 82 | 83 | // MARK: - Previews 84 | #Preview(windowStyle: .automatic) { 85 | ContentView() 86 | } 87 | -------------------------------------------------------------------------------- /.swiftpm/xcode/xcshareddata/xcschemes/VisionPanes.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 35 | 41 | 42 | 43 | 44 | 45 | 55 | 56 | 62 | 63 | 69 | 70 | 71 | 72 | 74 | 75 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /Example Project/Example Project.xcodeproj/xcshareddata/xcschemes/Example Project.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Example Project/Packages/RealityKitContent/Package.realitycomposerpro/WorkspaceData/SceneMetadataList.json: -------------------------------------------------------------------------------- 1 | { 2 | "0A9B4653-B11E-4D6A-850E-C6FCB621626C" : { 3 | "cameraTransform" : [ 4 | 0.9807314, 5 | -1.9820146e-10, 6 | -0.195361, 7 | 0, 8 | -0.10051192, 9 | 0.85749435, 10 | -0.5045798, 11 | 0, 12 | 0.16752096, 13 | 0.51449335, 14 | 0.84097165, 15 | 0, 16 | 0.09084191, 17 | 0.05849296, 18 | 0.13903293, 19 | 1 20 | ], 21 | "objectMetadataList" : [ 22 | [ 23 | "0A9B4653-B11E-4D6A-850E-C6FCB621626C", 24 | "Root" 25 | ], 26 | { 27 | "isExpanded" : true, 28 | "isLocked" : false 29 | }, 30 | [ 31 | "0A9B4653-B11E-4D6A-850E-C6FCB621626C", 32 | "Root", 33 | "GridMaterial" 34 | ], 35 | { 36 | "isExpanded" : true, 37 | "isLocked" : false 38 | }, 39 | [ 40 | "0A9B4653-B11E-4D6A-850E-C6FCB621626C", 41 | "Root", 42 | "Sphere" 43 | ], 44 | { 45 | "isExpanded" : true, 46 | "isLocked" : false 47 | } 48 | ] 49 | }, 50 | "1CBF3893-ABFD-408C-8B91-045BFD257808" : { 51 | "cameraTransform" : [ 52 | 0.99999994, 53 | 0, 54 | -0, 55 | 0, 56 | -0, 57 | 0.8660255, 58 | -0.49999988, 59 | 0, 60 | 0, 61 | 0.49999988, 62 | 0.8660255, 63 | 0, 64 | 0, 65 | 0.27093542, 66 | 0.46927398, 67 | 1 68 | ], 69 | "objectMetadataList" : [ 70 | 71 | ] 72 | }, 73 | "03E02005-EFA6-48D6-8A76-05B2822A74E9" : { 74 | "cameraTransform" : [ 75 | 0.99999994, 76 | 0, 77 | -0, 78 | 0, 79 | -0, 80 | 0.8660254, 81 | -0.49999994, 82 | 0, 83 | 0, 84 | 0.49999994, 85 | 0.8660254, 86 | 0, 87 | 0, 88 | 0.5981957, 89 | 1.0361054, 90 | 1 91 | ], 92 | "objectMetadataList" : [ 93 | 94 | ] 95 | }, 96 | "26DBAE76-5DD8-47B6-A085-1B4ADA111097" : { 97 | "cameraTransform" : [ 98 | 1, 99 | 0, 100 | -0, 101 | 0, 102 | -0, 103 | 0.7071069, 104 | -0.7071067, 105 | 0, 106 | 0, 107 | 0.7071067, 108 | 0.7071069, 109 | 0, 110 | 0, 111 | 0.2681068, 112 | 0.26850593, 113 | 1 114 | ], 115 | "objectMetadataList" : [ 116 | [ 117 | "26DBAE76-5DD8-47B6-A085-1B4ADA111097", 118 | "Root" 119 | ], 120 | { 121 | "isExpanded" : true, 122 | "isLocked" : false 123 | } 124 | ] 125 | }, 126 | "34C460AE-CA1B-4348-BD05-621ACBDFFE97" : { 127 | "cameraTransform" : [ 128 | 0.99999994, 129 | 0, 130 | -0, 131 | 0, 132 | -0, 133 | 0.8660255, 134 | -0.49999988, 135 | 0, 136 | 0, 137 | 0.49999988, 138 | 0.8660255, 139 | 0, 140 | 0, 141 | 0.27093542, 142 | 0.46927398, 143 | 1 144 | ], 145 | "objectMetadataList" : [ 146 | 147 | ] 148 | }, 149 | "440DE5B4-E4E4-459B-AABF-9ACE96319272" : { 150 | "cameraTransform" : [ 151 | 0.99999994, 152 | 0, 153 | -0, 154 | 0, 155 | -0, 156 | 0.8660254, 157 | -0.49999994, 158 | 0, 159 | 0, 160 | 0.49999994, 161 | 0.8660254, 162 | 0, 163 | 0, 164 | 0.5981957, 165 | 1.0361054, 166 | 1 167 | ], 168 | "objectMetadataList" : [ 169 | [ 170 | "440DE5B4-E4E4-459B-AABF-9ACE96319272", 171 | "Root" 172 | ], 173 | { 174 | "isExpanded" : true, 175 | "isLocked" : false 176 | } 177 | ] 178 | }, 179 | "FBD8436F-6B8B-4B82-99B5-995D538B4704" : { 180 | "cameraTransform" : [ 181 | 0.99999994, 182 | 0, 183 | -0, 184 | 0, 185 | -0, 186 | 0.8660254, 187 | -0.49999994, 188 | 0, 189 | 0, 190 | 0.49999994, 191 | 0.8660254, 192 | 0, 193 | 0, 194 | 0.5981957, 195 | 1.0361054, 196 | 1 197 | ], 198 | "objectMetadataList" : [ 199 | [ 200 | "FBD8436F-6B8B-4B82-99B5-995D538B4704", 201 | "Root" 202 | ], 203 | { 204 | "isExpanded" : true, 205 | "isLocked" : false 206 | } 207 | ] 208 | } 209 | } -------------------------------------------------------------------------------- /Sources/VisionPanes/MultiPaneViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Laksh Chakraborty on 3/5/24. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | import SwiftUI 11 | 12 | class MultiPaneViewController: UIViewController where Item: Identifiable, MainView: View, PaneView: View { 13 | var item: Item? 14 | var previousItem: Item? 15 | 16 | var configuration: MultiPaneViewConfiguration 17 | 18 | var mainController: UIHostingController? = nil 19 | var paneController: UIHostingController? = nil 20 | 21 | init(item: Item?, configuration: MultiPaneViewConfiguration, mainView: MainView, paneView: PaneView) { 22 | self.configuration = configuration 23 | super.init(nibName: nil, bundle: nil) 24 | 25 | mainController = UIHostingController(rootView: mainView) 26 | 27 | paneController = UIHostingController(rootView: paneView) 28 | 29 | addChild(mainController!) 30 | view.addSubview(mainController!.view) 31 | 32 | addChild(paneController!) 33 | view.addSubview(paneController!.view) 34 | } 35 | 36 | required init?(coder: NSCoder) { 37 | fatalError("init(coder:) has not been implemented") 38 | } 39 | 40 | // MARK: - Window Geometry 41 | 42 | func _updateWindowGeometry() { 43 | guard let window = view.window else { return } 44 | guard let scene = window.windowScene else { return } 45 | 46 | guard item?.id != previousItem?.id else { return } 47 | 48 | let geo = UIWindowScene.GeometryPreferences.Vision() 49 | 50 | geo.size = window.bounds.size 51 | 52 | switch configuration.placement { 53 | case let .trailing(width: width, spacing: spacing): 54 | if item != nil { 55 | geo.size?.width += width + spacing 56 | } else { 57 | geo.size?.width -= width + spacing 58 | } 59 | 60 | case let .leading(width: width, spacing: spacing): 61 | if item != nil { 62 | geo.size?.width += width + spacing 63 | } else { 64 | geo.size?.width -= width + spacing 65 | } 66 | 67 | case .top(height: let height, spacing: let spacing): 68 | if item != nil { 69 | geo.size?.height += height + spacing 70 | } else { 71 | geo.size?.height -= height + spacing 72 | } 73 | 74 | case .bottom(height: let height, spacing: let spacing): 75 | if item != nil { 76 | geo.size?.height += height + spacing 77 | } else { 78 | geo.size?.height -= height + spacing 79 | } 80 | } 81 | 82 | scene.requestGeometryUpdate(geo) 83 | } 84 | 85 | // MARK: - Layout 86 | 87 | override func viewDidLayoutSubviews() { 88 | switch configuration.placement { 89 | case let .leading(width: width, spacing: spacing): 90 | let division = view.bounds.divided(atDistance: width + spacing, from: .minXEdge) 91 | 92 | mainController?.view.frame = item != nil ? division.remainder : view.bounds 93 | paneController?.view.frame = division.slice.divided(atDistance: spacing, from: .maxXEdge).remainder 94 | 95 | case let .trailing(width: width, spacing: spacing): 96 | let division = view.bounds.divided(atDistance: width + spacing, from: .maxXEdge) 97 | 98 | mainController?.view.frame = item != nil ? division.remainder : view.bounds 99 | paneController?.view.frame = division.slice.divided(atDistance: spacing, from: .minXEdge).remainder 100 | 101 | case let .top(height: height, spacing: spacing): 102 | let division = view.bounds.divided(atDistance: height + spacing, from: .minYEdge) 103 | 104 | mainController?.view.frame = item != nil ? division.remainder : view.bounds 105 | paneController?.view.frame = division.slice.divided(atDistance: spacing, from: .maxYEdge).remainder 106 | 107 | case let .bottom(height: height, spacing: spacing): 108 | let division = view.bounds.divided(atDistance: height + spacing, from: .maxYEdge) 109 | 110 | mainController?.view.frame = item != nil ? division.remainder : view.bounds 111 | paneController?.view.frame = division.slice.divided(atDistance: spacing, from: .minYEdge).remainder 112 | } 113 | } 114 | 115 | override var preferredContainerBackgroundStyle: UIContainerBackgroundStyle { 116 | return .hidden 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vision Panes 2 | 3 | An easy-to-use SwiftUI package for splitting windows into multiple panes with pleasant animations out of the box. 4 | 5 | ## Why 6 | 7 | One of the main UX draws of visionOS that sets it apart from anything we've ever seen before is its infinite canvas. Since windowed apps have the ability to be arbitrarily large, panes that would, on other platforms, have eaten into screen real estate can now simply expand the window's size. 8 | 9 | Apple does this in the Messages app on visionOS. When the user taps on a contact photo within a chat, the contact details show up in a pane on the trailing edge of the main pane. It is a very good use of space, and is an easy way for developers to make apps feel more at home on visionOS. 10 | 11 | Or at least, it would be easy if it weren't difficult to set up. Apple provides no easy way to set panes up. They are, in fact, just subdivisions of a single window, but all the setup is hard to do. Further, there is **no way currently to programmatically change the size of windows in SwiftUI**. To do this, one must drop into UIKit and do all the plumbing from there. 12 | 13 | Vision Panes provides a simple SwiftUI interface to this functionality, with pleasant animations to boot. 14 | 15 | ## Features 16 | - Easy-to-use SwiftUI API that should seem familiar to most SwiftUI creators 17 | - Ability to add multiple panes to each of the four edges of a window 18 | - No need to jump into UIKit 19 | - Pleasant animations 20 | 21 | ## Requirements 22 | - visionOS 1.0 23 | - Swift 5.10 24 | - Xcode 15.2 25 | 26 | ## Installation 27 | ### Swift Package Manager 28 | Install Vision Panes with SPM: 29 | 30 | 1. In Xcode, open your project and navigate to File → Add Packages 31 | 2. Paste the repository URL ([https://github.com/reftonull/VisionPanes](https://github.com/reftonull/VisionPanes)) and click Next. 32 | 3. For Rules, select Up to Next Major Version. 33 | 4. Click Add Package. 34 | 35 | ## Usage 36 | ```swift 37 | @main 38 | struct MyApp: App { 39 | var body: some Scene { 40 | WindowGroup { 41 | ContentView() 42 | } 43 | .windowStyle(.plain) // 1. 44 | } 45 | } 46 | 47 | struct Item: Identifiable, Equatable { // 2. 48 | var id: String 49 | var text: String 50 | } 51 | 52 | struct ContentView: View { 53 | @State var item: Item? 54 | 55 | var body: some View { 56 | VStack { 57 | Button("Show Trailing Pane") { 58 | item = Item(id: "1", text: "This is in the trailing pane") 59 | } 60 | 61 | Text("Main pane") 62 | } 63 | .frame(maxWidth: .infinity, maxHeight: .infinity) 64 | .glassBackgroundEffect() 65 | .pane(item: item, placement: .trailing) { item in // 3. 66 | Text(item.text) 67 | .frame( 68 | maxWidth: .infinity, 69 | maxHeight: .infinity 70 | ) 71 | .glassBackgroundEffect() 72 | } 73 | } 74 | } 75 | ``` 76 | 77 | `// 1` The `windowStyle` property on the WindowGroup must be set to `.plain` so that visionOS doesn’t show the glass background behind the whole window 78 | 79 | `// 2` Model for our pane, which must be `Identifiable` and `Equatable` 80 | 81 | `// 3` The `pane` view modifier looks very much like `sheet`, but doesn’t take in a binding. Pane content goes in the trailing closure. It’s that easy. 82 | 83 | ## Parameters 84 | The `pane` view modifier looks like this: 85 | ```swift 86 | .pane( 87 | item: Item?, 88 | placement: PanePlacement, 89 | content: (Item) -> Content 90 | ) 91 | ``` 92 | `Item` is your model, which must conform to `Identifiable` and `Equatable`. The pane is presented when `item` is non-nil, and is dismissed when `item` becomes nil. 93 | 94 | `PanePlacement` is an enum which has the following cases: 95 | - `.leading(width: CGFloat, spacing: CGFloat)` 96 | - `.trailin(width: CGFloat, spacing: CGFloat)` 97 | - `.top(width: CGFloat, spacing: CGFloat)` 98 | - `.bottom(width: CGFloat, spacing: CGFloat)` 99 | 100 | Sensible defaults are provided. 101 | 102 | The `content` closure takes as input the non-nil version of item, allowing you to drive your UI from there. 103 | 104 | ## Examples 105 | ### Panes along all edges 106 | 107 | https://github.com/reftonull/VisionPanes/assets/66828631/c270ffc4-79c1-42b3-88ed-7987ceb300f9 108 | 109 |
110 | Source Code 111 | 112 | ```swift 113 | struct Item: Identifiable, Equatable { 114 | var id: String 115 | var text: String 116 | } 117 | 118 | struct AllEdges: View { 119 | @State var item: Item? 120 | @State var item2: Item? 121 | @State var item3: Item? 122 | @State var item4: Item? 123 | 124 | var body: some View { 125 | VStack { 126 | Button("Show Leading Pane") { 127 | if item == nil { 128 | item = Item(id: "1", text: "Leading Pane") 129 | } else { 130 | item = nil 131 | } 132 | } 133 | 134 | Button("Show Trailing Pane") { 135 | if item2 == nil { 136 | item2 = Item(id: "1", text: "Leading Pane") 137 | } else { 138 | item2 = nil 139 | } 140 | } 141 | 142 | Button("Show Top Pane") { 143 | if item3 == nil { 144 | item3 = Item(id: "1", text: "Leading Pane") 145 | } else { 146 | item3 = nil 147 | } 148 | } 149 | 150 | Button("Show Bottom Pane") { 151 | if item4 == nil { 152 | item4 = Item(id: "1", text: "Leading Pane") 153 | } else { 154 | item4 = nil 155 | } 156 | } 157 | } 158 | .frame(maxWidth: .infinity, maxHeight: .infinity) 159 | .glassBackgroundEffect() 160 | .pane(item: item, placement: .leading) { item in 161 | Text(item.text) 162 | .frame(maxWidth: .infinity, maxHeight: .infinity) 163 | .glassBackgroundEffect() 164 | } 165 | .pane(item: item2, placement: .trailing) { item in 166 | Text(item.text) 167 | .frame(maxWidth: .infinity, maxHeight: .infinity) 168 | .glassBackgroundEffect() 169 | } 170 | .pane(item: item3, placement: .top) { item in 171 | Text(item.text) 172 | .frame(maxWidth: .infinity, maxHeight: .infinity) 173 | .glassBackgroundEffect() 174 | } 175 | .pane(item: item4, placement: .bottom) { item in 176 | Text(item.text) 177 | .frame(maxWidth: .infinity, maxHeight: .infinity) 178 | .glassBackgroundEffect() 179 | } 180 | } 181 | } 182 | ``` 183 | 184 |
185 | 186 | ### Multiple panes along the same edge 187 | 188 | https://github.com/reftonull/VisionPanes/assets/66828631/51bbe736-2929-4b06-a0eb-77fea6cf32e1 189 | 190 |
191 | Source Code 192 | 193 | ```swift 194 | struct Item: Identifiable, Equatable { 195 | var id: String 196 | var text: String 197 | } 198 | 199 | struct SameEdge: View { 200 | @State var item: Item? 201 | @State var item2: Item? 202 | 203 | var body: some View { 204 | VStack { 205 | Button("Show Pane 1") { 206 | if item == nil { 207 | item = Item(id: "1", text: "Pane 1") 208 | } else { 209 | item = nil 210 | } 211 | } 212 | 213 | Button("Show Pane 2") { 214 | if item2 == nil { 215 | item2 = Item(id: "1", text: "Pane 2") 216 | } else { 217 | item2 = nil 218 | } 219 | } 220 | } 221 | .frame(maxWidth: .infinity, maxHeight: .infinity) 222 | .glassBackgroundEffect() 223 | .pane(item: item, placement: .trailing) { item in 224 | Text(item.text) 225 | .frame(maxWidth: .infinity, maxHeight: .infinity) 226 | .glassBackgroundEffect() 227 | } 228 | .pane(item: item2, placement: .trailing) { item in 229 | Text(item.text) 230 | .frame(maxWidth: .infinity, maxHeight: .infinity) 231 | .glassBackgroundEffect() 232 | } 233 | } 234 | } 235 | ``` 236 | 237 |
238 | 239 | ## Demo Project 240 | The demo project can be found [here](https://github.com/reftonull/VisionPanes/tree/main/Example%20Project). It includes both examples above, and will expand with more use cases in the future. 241 | 242 | ## Contributing 243 | Issues and pull requests are welcome! 244 | 245 | ## Credits 246 | This package is built by [Laksh Chakraborty](https://github.com/reftonull). 247 | 248 | A huge shoutout to [Steve Troughton-Smith](https://github.com/steventroughtonsmith) for his original example code that inspired this package. See his project [here](https://github.com/steventroughtonsmith/VisionMessagesDualPane). 249 | 250 | ## License 251 | This package is available under an MIT License. See the license file [here](https://github.com/reftonull/VisionPanes/blob/main/LICENSE). 252 | 253 | -------------------------------------------------------------------------------- /Example Project/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Materials/GridMaterial.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | defaultPrim = "Root" 4 | metersPerUnit = 1 5 | upAxis = "Y" 6 | ) 7 | 8 | def Xform "Root" 9 | { 10 | def Material "GridMaterial" 11 | { 12 | reorder nameChildren = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "DefaultSurfaceShader", "MaterialXPreviewSurface", "Texcoord", "Add", "Multiply", "Fractional", "LineCounts", "Multiply_1", "Separate2", "Separate2_1", "Ifgreater", "Ifgreater_1", "Max", "Background_Color"] 13 | token outputs:mtlx:surface.connect = 14 | token outputs:realitykit:vertex 15 | token outputs:surface 16 | float2 ui:nodegraph:realitykit:subgraphOutputs:pos = (2222, 300.5) 17 | float2 ui:nodegraph:realitykit:subgraphOutputs:size = (182, 89) 18 | int ui:nodegraph:realitykit:subgraphOutputs:stackingOrder = 749 19 | 20 | def Shader "DefaultSurfaceShader" 21 | { 22 | uniform token info:id = "UsdPreviewSurface" 23 | color3f inputs:diffuseColor = (1, 1, 1) 24 | float inputs:roughness = 0.75 25 | token outputs:surface 26 | } 27 | 28 | def Shader "MaterialXPreviewSurface" 29 | { 30 | uniform token info:id = "ND_UsdPreviewSurface_surfaceshader" 31 | float inputs:clearcoat 32 | float inputs:clearcoatRoughness 33 | color3f inputs:diffuseColor.connect = 34 | color3f inputs:emissiveColor 35 | float inputs:ior 36 | float inputs:metallic = 0.15 37 | float3 inputs:normal 38 | float inputs:occlusion 39 | float inputs:opacity 40 | float inputs:opacityThreshold 41 | float inputs:roughness = 0.5 42 | token outputs:out 43 | float2 ui:nodegraph:node:pos = (1967, 300.5) 44 | float2 ui:nodegraph:node:size = (208, 297) 45 | int ui:nodegraph:node:stackingOrder = 870 46 | string[] ui:nodegraph:realitykit:node:attributesShowingChildren = ["Advanced"] 47 | } 48 | 49 | def Shader "Texcoord" 50 | { 51 | uniform token info:id = "ND_texcoord_vector2" 52 | float2 outputs:out 53 | float2 ui:nodegraph:node:pos = (94.14453, 35.29297) 54 | float2 ui:nodegraph:node:size = (182, 43) 55 | int ui:nodegraph:node:stackingOrder = 1358 56 | } 57 | 58 | def Shader "Multiply" 59 | { 60 | uniform token info:id = "ND_multiply_vector2" 61 | float2 inputs:in1.connect = 62 | float2 inputs:in2 = (32, 15) 63 | float2 inputs:in2.connect = 64 | float2 outputs:out 65 | float2 ui:nodegraph:node:pos = (275.64453, 47.29297) 66 | float2 ui:nodegraph:node:size = (61, 36) 67 | int ui:nodegraph:node:stackingOrder = 1348 68 | string[] ui:nodegraph:realitykit:node:attributesShowingChildren = ["inputs:in2"] 69 | } 70 | 71 | def Shader "Fractional" 72 | { 73 | uniform token info:id = "ND_realitykit_fractional_vector2" 74 | float2 inputs:in.connect = 75 | float2 outputs:out 76 | float2 ui:nodegraph:node:pos = (440.5, 49.5) 77 | float2 ui:nodegraph:node:size = (155, 99) 78 | int ui:nodegraph:node:stackingOrder = 1345 79 | } 80 | 81 | def Shader "BaseColor" 82 | { 83 | uniform token info:id = "ND_constant_color3" 84 | color3f inputs:value = (0.89737034, 0.89737034, 0.89737034) ( 85 | colorSpace = "Input - Texture - sRGB - sRGB" 86 | ) 87 | color3f inputs:value.connect = None 88 | color3f outputs:out 89 | float2 ui:nodegraph:node:pos = (1537.5977, 363.07812) 90 | float2 ui:nodegraph:node:size = (150, 43) 91 | int ui:nodegraph:node:stackingOrder = 1353 92 | } 93 | 94 | def Shader "LineColor" 95 | { 96 | uniform token info:id = "ND_constant_color3" 97 | color3f inputs:value = (0.55945957, 0.55945957, 0.55945957) ( 98 | colorSpace = "Input - Texture - sRGB - sRGB" 99 | ) 100 | color3f inputs:value.connect = None 101 | color3f outputs:out 102 | float2 ui:nodegraph:node:pos = (1536.9844, 287.86328) 103 | float2 ui:nodegraph:node:size = (146, 43) 104 | int ui:nodegraph:node:stackingOrder = 1355 105 | } 106 | 107 | def Shader "LineWidths" 108 | { 109 | uniform token info:id = "ND_combine2_vector2" 110 | float inputs:in1 = 0.1 111 | float inputs:in2 = 0.1 112 | float2 outputs:out 113 | float2 ui:nodegraph:node:pos = (443.64453, 233.79297) 114 | float2 ui:nodegraph:node:size = (151, 43) 115 | int ui:nodegraph:node:stackingOrder = 1361 116 | } 117 | 118 | def Shader "LineCounts" 119 | { 120 | uniform token info:id = "ND_combine2_vector2" 121 | float inputs:in1 = 24 122 | float inputs:in2 = 12 123 | float2 outputs:out 124 | float2 ui:nodegraph:node:pos = (94.14453, 138.29297) 125 | float2 ui:nodegraph:node:size = (153, 43) 126 | int ui:nodegraph:node:stackingOrder = 1359 127 | } 128 | 129 | def Shader "Remap" 130 | { 131 | uniform token info:id = "ND_remap_color3" 132 | color3f inputs:in.connect = 133 | color3f inputs:inhigh.connect = None 134 | color3f inputs:inlow.connect = None 135 | color3f inputs:outhigh.connect = 136 | color3f inputs:outlow.connect = 137 | color3f outputs:out 138 | float2 ui:nodegraph:node:pos = (1755.5, 300.5) 139 | float2 ui:nodegraph:node:size = (95, 171) 140 | int ui:nodegraph:node:stackingOrder = 1282 141 | string[] ui:nodegraph:realitykit:node:attributesShowingChildren = ["inputs:outlow"] 142 | } 143 | 144 | def Shader "Separate2" 145 | { 146 | uniform token info:id = "ND_separate2_vector2" 147 | float2 inputs:in.connect = 148 | float outputs:outx 149 | float outputs:outy 150 | float2 ui:nodegraph:node:pos = (1212.6445, 128.91797) 151 | float2 ui:nodegraph:node:size = (116, 117) 152 | int ui:nodegraph:node:stackingOrder = 1363 153 | } 154 | 155 | def Shader "Combine3" 156 | { 157 | uniform token info:id = "ND_combine3_color3" 158 | float inputs:in1.connect = 159 | float inputs:in2.connect = 160 | float inputs:in3.connect = 161 | color3f outputs:out 162 | float2 ui:nodegraph:node:pos = (1578.1445, 128.91797) 163 | float2 ui:nodegraph:node:size = (146, 54) 164 | int ui:nodegraph:node:stackingOrder = 1348 165 | } 166 | 167 | def Shader "Range" 168 | { 169 | uniform token info:id = "ND_range_vector2" 170 | bool inputs:doclamp = 1 171 | float2 inputs:gamma = (2, 2) 172 | float2 inputs:in.connect = 173 | float2 inputs:inhigh.connect = 174 | float2 inputs:inlow = (0.02, 0.02) 175 | float2 inputs:outhigh 176 | float2 inputs:outlow 177 | float2 outputs:out 178 | float2 ui:nodegraph:node:pos = (990.64453, 128.91797) 179 | float2 ui:nodegraph:node:size = (98, 207) 180 | int ui:nodegraph:node:stackingOrder = 1364 181 | } 182 | 183 | def Shader "Subtract" 184 | { 185 | uniform token info:id = "ND_subtract_vector2" 186 | float2 inputs:in1.connect = 187 | float2 inputs:in2.connect = 188 | float2 outputs:out 189 | float2 ui:nodegraph:node:pos = (612.64453, 87.04297) 190 | float2 ui:nodegraph:node:size = (63, 36) 191 | int ui:nodegraph:node:stackingOrder = 1348 192 | } 193 | 194 | def Shader "Absval" 195 | { 196 | uniform token info:id = "ND_absval_vector2" 197 | float2 inputs:in.connect = 198 | float2 outputs:out 199 | float2 ui:nodegraph:node:pos = (765.64453, 87.04297) 200 | float2 ui:nodegraph:node:size = (123, 43) 201 | int ui:nodegraph:node:stackingOrder = 1348 202 | } 203 | 204 | def Shader "Min" 205 | { 206 | uniform token info:id = "ND_min_float" 207 | float inputs:in1.connect = 208 | float inputs:in2.connect = 209 | float outputs:out 210 | float2 ui:nodegraph:node:pos = (1388.1445, 128.91797) 211 | float2 ui:nodegraph:node:size = (114, 36) 212 | int ui:nodegraph:node:stackingOrder = 1363 213 | } 214 | } 215 | } 216 | 217 | -------------------------------------------------------------------------------- /Example Project/Example Project.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5A9713572B98159A005B65AD /* VisionPanes in Frameworks */ = {isa = PBXBuildFile; productRef = 5A9713562B98159A005B65AD /* VisionPanes */; }; 11 | 5A9713592B983EAC005B65AD /* SameEdge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A9713582B983EAC005B65AD /* SameEdge.swift */; }; 12 | 5ADC1A292B97DDC100D6787F /* Example_ProjectApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5ADC1A282B97DDC100D6787F /* Example_ProjectApp.swift */; }; 13 | 5ADC1A2B2B97DDC100D6787F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5ADC1A2A2B97DDC100D6787F /* ContentView.swift */; }; 14 | 5ADC1A2D2B97DDC200D6787F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5ADC1A2C2B97DDC200D6787F /* Assets.xcassets */; }; 15 | 5ADC1A302B97DDC200D6787F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5ADC1A2F2B97DDC200D6787F /* Preview Assets.xcassets */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 5A19F02D2B9813A2008C1CBF /* VisionPanesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisionPanesTests.swift; sourceTree = ""; }; 20 | 5A9713582B983EAC005B65AD /* SameEdge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SameEdge.swift; sourceTree = ""; }; 21 | 5AD50B2A2B98157B004E8A19 /* VisionPanes */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = VisionPanes; path = ..; sourceTree = ""; }; 22 | 5ADC1A212B97DDC100D6787F /* VisionPanesExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VisionPanesExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 5ADC1A282B97DDC100D6787F /* Example_ProjectApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Example_ProjectApp.swift; sourceTree = ""; }; 24 | 5ADC1A2A2B97DDC100D6787F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 25 | 5ADC1A2C2B97DDC200D6787F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | 5ADC1A2F2B97DDC200D6787F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 27 | 5ADC1A312B97DDC200D6787F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | 5ADC1A382B97E04700D6787F /* VisionPanes */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = VisionPanes; path = ../../..; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | 5ADC1A1E2B97DDC100D6787F /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | 5A9713572B98159A005B65AD /* VisionPanes in Frameworks */, 37 | ); 38 | runOnlyForDeploymentPostprocessing = 0; 39 | }; 40 | /* End PBXFrameworksBuildPhase section */ 41 | 42 | /* Begin PBXGroup section */ 43 | 5A19F0282B97E0E0008C1CBF /* Frameworks */ = { 44 | isa = PBXGroup; 45 | children = ( 46 | ); 47 | name = Frameworks; 48 | sourceTree = ""; 49 | }; 50 | 5A19F02E2B9813A2008C1CBF /* VisionPanesTests */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 5A19F02D2B9813A2008C1CBF /* VisionPanesTests.swift */, 54 | ); 55 | path = VisionPanesTests; 56 | sourceTree = ""; 57 | }; 58 | 5A19F02F2B9813A2008C1CBF /* Tests */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 5A19F02E2B9813A2008C1CBF /* VisionPanesTests */, 62 | ); 63 | path = Tests; 64 | sourceTree = ""; 65 | }; 66 | 5ADC1A182B97DDC100D6787F = { 67 | isa = PBXGroup; 68 | children = ( 69 | 5AD50B2A2B98157B004E8A19 /* VisionPanes */, 70 | 5ADC1A232B97DDC100D6787F /* VisionPanesExample */, 71 | 5ADC1A222B97DDC100D6787F /* Products */, 72 | 5A19F0282B97E0E0008C1CBF /* Frameworks */, 73 | ); 74 | sourceTree = ""; 75 | }; 76 | 5ADC1A222B97DDC100D6787F /* Products */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 5ADC1A212B97DDC100D6787F /* VisionPanesExample.app */, 80 | ); 81 | name = Products; 82 | sourceTree = ""; 83 | }; 84 | 5ADC1A232B97DDC100D6787F /* VisionPanesExample */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 5ADC1A282B97DDC100D6787F /* Example_ProjectApp.swift */, 88 | 5ADC1A2A2B97DDC100D6787F /* ContentView.swift */, 89 | 5A9713582B983EAC005B65AD /* SameEdge.swift */, 90 | 5ADC1A2C2B97DDC200D6787F /* Assets.xcassets */, 91 | 5A19F02F2B9813A2008C1CBF /* Tests */, 92 | 5ADC1A312B97DDC200D6787F /* Info.plist */, 93 | 5ADC1A2E2B97DDC200D6787F /* Preview Content */, 94 | ); 95 | path = VisionPanesExample; 96 | sourceTree = ""; 97 | }; 98 | 5ADC1A2E2B97DDC200D6787F /* Preview Content */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 5ADC1A382B97E04700D6787F /* VisionPanes */, 102 | 5ADC1A2F2B97DDC200D6787F /* Preview Assets.xcassets */, 103 | ); 104 | path = "Preview Content"; 105 | sourceTree = ""; 106 | }; 107 | /* End PBXGroup section */ 108 | 109 | /* Begin PBXNativeTarget section */ 110 | 5ADC1A202B97DDC100D6787F /* VisionPanesExample */ = { 111 | isa = PBXNativeTarget; 112 | buildConfigurationList = 5ADC1A342B97DDC200D6787F /* Build configuration list for PBXNativeTarget "VisionPanesExample" */; 113 | buildPhases = ( 114 | 5ADC1A1D2B97DDC100D6787F /* Sources */, 115 | 5ADC1A1E2B97DDC100D6787F /* Frameworks */, 116 | 5ADC1A1F2B97DDC100D6787F /* Resources */, 117 | ); 118 | buildRules = ( 119 | ); 120 | dependencies = ( 121 | ); 122 | name = VisionPanesExample; 123 | packageProductDependencies = ( 124 | 5A9713562B98159A005B65AD /* VisionPanes */, 125 | ); 126 | productName = "Example Project"; 127 | productReference = 5ADC1A212B97DDC100D6787F /* VisionPanesExample.app */; 128 | productType = "com.apple.product-type.application"; 129 | }; 130 | /* End PBXNativeTarget section */ 131 | 132 | /* Begin PBXProject section */ 133 | 5ADC1A192B97DDC100D6787F /* Project object */ = { 134 | isa = PBXProject; 135 | attributes = { 136 | BuildIndependentTargetsInParallel = 1; 137 | LastSwiftUpdateCheck = 1530; 138 | LastUpgradeCheck = 1530; 139 | TargetAttributes = { 140 | 5ADC1A202B97DDC100D6787F = { 141 | CreatedOnToolsVersion = 15.3; 142 | }; 143 | }; 144 | }; 145 | buildConfigurationList = 5ADC1A1C2B97DDC100D6787F /* Build configuration list for PBXProject "Example Project" */; 146 | compatibilityVersion = "Xcode 14.0"; 147 | developmentRegion = en; 148 | hasScannedForEncodings = 0; 149 | knownRegions = ( 150 | en, 151 | Base, 152 | ); 153 | mainGroup = 5ADC1A182B97DDC100D6787F; 154 | productRefGroup = 5ADC1A222B97DDC100D6787F /* Products */; 155 | projectDirPath = ""; 156 | projectRoot = ""; 157 | targets = ( 158 | 5ADC1A202B97DDC100D6787F /* VisionPanesExample */, 159 | ); 160 | }; 161 | /* End PBXProject section */ 162 | 163 | /* Begin PBXResourcesBuildPhase section */ 164 | 5ADC1A1F2B97DDC100D6787F /* Resources */ = { 165 | isa = PBXResourcesBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | 5ADC1A302B97DDC200D6787F /* Preview Assets.xcassets in Resources */, 169 | 5ADC1A2D2B97DDC200D6787F /* Assets.xcassets in Resources */, 170 | ); 171 | runOnlyForDeploymentPostprocessing = 0; 172 | }; 173 | /* End PBXResourcesBuildPhase section */ 174 | 175 | /* Begin PBXSourcesBuildPhase section */ 176 | 5ADC1A1D2B97DDC100D6787F /* Sources */ = { 177 | isa = PBXSourcesBuildPhase; 178 | buildActionMask = 2147483647; 179 | files = ( 180 | 5ADC1A2B2B97DDC100D6787F /* ContentView.swift in Sources */, 181 | 5A9713592B983EAC005B65AD /* SameEdge.swift in Sources */, 182 | 5ADC1A292B97DDC100D6787F /* Example_ProjectApp.swift in Sources */, 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | }; 186 | /* End PBXSourcesBuildPhase section */ 187 | 188 | /* Begin XCBuildConfiguration section */ 189 | 5ADC1A322B97DDC200D6787F /* Debug */ = { 190 | isa = XCBuildConfiguration; 191 | buildSettings = { 192 | ALWAYS_SEARCH_USER_PATHS = NO; 193 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 194 | CLANG_ANALYZER_NONNULL = YES; 195 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 196 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 197 | CLANG_ENABLE_MODULES = YES; 198 | CLANG_ENABLE_OBJC_ARC = YES; 199 | CLANG_ENABLE_OBJC_WEAK = YES; 200 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 201 | CLANG_WARN_BOOL_CONVERSION = YES; 202 | CLANG_WARN_COMMA = YES; 203 | CLANG_WARN_CONSTANT_CONVERSION = YES; 204 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 205 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 206 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 207 | CLANG_WARN_EMPTY_BODY = YES; 208 | CLANG_WARN_ENUM_CONVERSION = YES; 209 | CLANG_WARN_INFINITE_RECURSION = YES; 210 | CLANG_WARN_INT_CONVERSION = YES; 211 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 212 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 213 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 214 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 215 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 216 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 217 | CLANG_WARN_STRICT_PROTOTYPES = YES; 218 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 219 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 220 | CLANG_WARN_UNREACHABLE_CODE = YES; 221 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 222 | COPY_PHASE_STRIP = NO; 223 | DEBUG_INFORMATION_FORMAT = dwarf; 224 | ENABLE_STRICT_OBJC_MSGSEND = YES; 225 | ENABLE_TESTABILITY = YES; 226 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 227 | GCC_C_LANGUAGE_STANDARD = gnu17; 228 | GCC_DYNAMIC_NO_PIC = NO; 229 | GCC_NO_COMMON_BLOCKS = YES; 230 | GCC_OPTIMIZATION_LEVEL = 0; 231 | GCC_PREPROCESSOR_DEFINITIONS = ( 232 | "DEBUG=1", 233 | "$(inherited)", 234 | ); 235 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 236 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 237 | GCC_WARN_UNDECLARED_SELECTOR = YES; 238 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 239 | GCC_WARN_UNUSED_FUNCTION = YES; 240 | GCC_WARN_UNUSED_VARIABLE = YES; 241 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 242 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 243 | MTL_FAST_MATH = YES; 244 | ONLY_ACTIVE_ARCH = YES; 245 | SDKROOT = xros; 246 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 247 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 248 | XROS_DEPLOYMENT_TARGET = 1.1; 249 | }; 250 | name = Debug; 251 | }; 252 | 5ADC1A332B97DDC200D6787F /* Release */ = { 253 | isa = XCBuildConfiguration; 254 | buildSettings = { 255 | ALWAYS_SEARCH_USER_PATHS = NO; 256 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 257 | CLANG_ANALYZER_NONNULL = YES; 258 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 259 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 260 | CLANG_ENABLE_MODULES = YES; 261 | CLANG_ENABLE_OBJC_ARC = YES; 262 | CLANG_ENABLE_OBJC_WEAK = YES; 263 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 264 | CLANG_WARN_BOOL_CONVERSION = YES; 265 | CLANG_WARN_COMMA = YES; 266 | CLANG_WARN_CONSTANT_CONVERSION = YES; 267 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 268 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 269 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INFINITE_RECURSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 275 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 276 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 278 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 279 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 280 | CLANG_WARN_STRICT_PROTOTYPES = YES; 281 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 282 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 283 | CLANG_WARN_UNREACHABLE_CODE = YES; 284 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 285 | COPY_PHASE_STRIP = NO; 286 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 287 | ENABLE_NS_ASSERTIONS = NO; 288 | ENABLE_STRICT_OBJC_MSGSEND = YES; 289 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 290 | GCC_C_LANGUAGE_STANDARD = gnu17; 291 | GCC_NO_COMMON_BLOCKS = YES; 292 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 293 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 294 | GCC_WARN_UNDECLARED_SELECTOR = YES; 295 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 296 | GCC_WARN_UNUSED_FUNCTION = YES; 297 | GCC_WARN_UNUSED_VARIABLE = YES; 298 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 299 | MTL_ENABLE_DEBUG_INFO = NO; 300 | MTL_FAST_MATH = YES; 301 | SDKROOT = xros; 302 | SWIFT_COMPILATION_MODE = wholemodule; 303 | VALIDATE_PRODUCT = YES; 304 | XROS_DEPLOYMENT_TARGET = 1.1; 305 | }; 306 | name = Release; 307 | }; 308 | 5ADC1A352B97DDC200D6787F /* Debug */ = { 309 | isa = XCBuildConfiguration; 310 | buildSettings = { 311 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 312 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 313 | CODE_SIGN_STYLE = Automatic; 314 | CURRENT_PROJECT_VERSION = 1; 315 | DEVELOPMENT_ASSET_PATHS = "\"VisionPanesExample/Preview Content\""; 316 | DEVELOPMENT_TEAM = 64HCNVFMBW; 317 | ENABLE_PREVIEWS = YES; 318 | GENERATE_INFOPLIST_FILE = YES; 319 | INFOPLIST_FILE = "$(TARGET_NAME)/Info.plist"; 320 | LD_RUNPATH_SEARCH_PATHS = ( 321 | "$(inherited)", 322 | "@executable_path/Frameworks", 323 | ); 324 | MARKETING_VERSION = 1.0; 325 | PRODUCT_BUNDLE_IDENTIFIER = "com.lakshchakraborty.Example-Project"; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | SUPPORTED_PLATFORMS = "xros xrsimulator"; 328 | SWIFT_EMIT_LOC_STRINGS = YES; 329 | SWIFT_VERSION = 5.0; 330 | TARGETED_DEVICE_FAMILY = "1,2,7"; 331 | XROS_DEPLOYMENT_TARGET = 1.0; 332 | }; 333 | name = Debug; 334 | }; 335 | 5ADC1A362B97DDC200D6787F /* Release */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 339 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 340 | CODE_SIGN_STYLE = Automatic; 341 | CURRENT_PROJECT_VERSION = 1; 342 | DEVELOPMENT_ASSET_PATHS = "\"VisionPanesExample/Preview Content\""; 343 | DEVELOPMENT_TEAM = 64HCNVFMBW; 344 | ENABLE_PREVIEWS = YES; 345 | GENERATE_INFOPLIST_FILE = YES; 346 | INFOPLIST_FILE = "$(TARGET_NAME)/Info.plist"; 347 | LD_RUNPATH_SEARCH_PATHS = ( 348 | "$(inherited)", 349 | "@executable_path/Frameworks", 350 | ); 351 | MARKETING_VERSION = 1.0; 352 | PRODUCT_BUNDLE_IDENTIFIER = "com.lakshchakraborty.Example-Project"; 353 | PRODUCT_NAME = "$(TARGET_NAME)"; 354 | SUPPORTED_PLATFORMS = "xros xrsimulator"; 355 | SWIFT_EMIT_LOC_STRINGS = YES; 356 | SWIFT_VERSION = 5.0; 357 | TARGETED_DEVICE_FAMILY = "1,2,7"; 358 | XROS_DEPLOYMENT_TARGET = 1.0; 359 | }; 360 | name = Release; 361 | }; 362 | /* End XCBuildConfiguration section */ 363 | 364 | /* Begin XCConfigurationList section */ 365 | 5ADC1A1C2B97DDC100D6787F /* Build configuration list for PBXProject "Example Project" */ = { 366 | isa = XCConfigurationList; 367 | buildConfigurations = ( 368 | 5ADC1A322B97DDC200D6787F /* Debug */, 369 | 5ADC1A332B97DDC200D6787F /* Release */, 370 | ); 371 | defaultConfigurationIsVisible = 0; 372 | defaultConfigurationName = Release; 373 | }; 374 | 5ADC1A342B97DDC200D6787F /* Build configuration list for PBXNativeTarget "VisionPanesExample" */ = { 375 | isa = XCConfigurationList; 376 | buildConfigurations = ( 377 | 5ADC1A352B97DDC200D6787F /* Debug */, 378 | 5ADC1A362B97DDC200D6787F /* Release */, 379 | ); 380 | defaultConfigurationIsVisible = 0; 381 | defaultConfigurationName = Release; 382 | }; 383 | /* End XCConfigurationList section */ 384 | 385 | /* Begin XCSwiftPackageProductDependency section */ 386 | 5A9713562B98159A005B65AD /* VisionPanes */ = { 387 | isa = XCSwiftPackageProductDependency; 388 | productName = VisionPanes; 389 | }; 390 | /* End XCSwiftPackageProductDependency section */ 391 | }; 392 | rootObject = 5ADC1A192B97DDC100D6787F /* Project object */; 393 | } 394 | --------------------------------------------------------------------------------