Controlling spacial video from floating window

I've created a Full Immersive VisionOS project and added a spacial video player in the ImmersiveView swift file. I have a few buttons on a different VideosView swift file on a floating window and i'd like switch the video playing in ImmersiveView when i click on a button in VideosView file.

Video player working great in ImmersiveView:

RealityView { content in
   if let videoEntity = try? await Entity(named: "Video", in: realityKitContentBundle) {

      guard let url = Bundle.main.url(forResource: "video1", withExtension: "mov") else {fatalError("Video was not found!")}

      let asset = AVURLAsset(url: url)
      let playerItem = AVPlayerItem(asset: asset)
      let player = AVPlayer()
                            
      videoEntity.components[VideoPlayerComponent.self] = .init(avPlayer: player)

      content.add(videoEntity)
      player.replaceCurrentItem(with: playerItem)
      player.play()
   }else {
      print("file not found!")
   }
}

Buttons in floating window from VideosView:

struct VideosView: View {
   var body: some View {
      VStack{
         Button(action: {}) {
            Text("video 1").font(.title)
         }
         Button(action: {}) {
            Text("video 2").font(.title)
         }
         Button(action: {}) {
            Text("video 3").font(.title)
         }
      }
   }
}

In general how do I control the video player across views and how do I replace the video when each button is selected. Any help/code/links would be greatly appreciated.

Answered by DTS Engineer in 787995022

Hello @Digitalmaniak,

The scenario you describe involves sharing state between two different scenes (the window, and the immersive space).

Consider the following example from Managing model data in your app:

@main
struct BookReaderApp: App {
    @State private var library = Library()
    
    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environment(library)
        }
    }
}

In your case, you have another scene, but you could have that scene use the same model data, maintaining a single source of truth. Continuing with the example above:

@main
struct BookReaderApp: App {
    @State private var library = Library()
    
    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environment(library)
        }

        ImmersiveSpace(id: "ImmersiveSpace") {
            ImmersiveView()
                .environment(library)
        }
    }
}

Now the data model is accessible in both scenes. In your case, you could set the "current player" in your data model whenever you press a button. Then, you can listen for changes to that property of your data model in the ImmersiveView, by using an onChange. When you get the change, you can update the VideoPlayerComponent of your entity appropriately.

Accepted Answer

Hello @Digitalmaniak,

The scenario you describe involves sharing state between two different scenes (the window, and the immersive space).

Consider the following example from Managing model data in your app:

@main
struct BookReaderApp: App {
    @State private var library = Library()
    
    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environment(library)
        }
    }
}

In your case, you have another scene, but you could have that scene use the same model data, maintaining a single source of truth. Continuing with the example above:

@main
struct BookReaderApp: App {
    @State private var library = Library()
    
    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environment(library)
        }

        ImmersiveSpace(id: "ImmersiveSpace") {
            ImmersiveView()
                .environment(library)
        }
    }
}

Now the data model is accessible in both scenes. In your case, you could set the "current player" in your data model whenever you press a button. Then, you can listen for changes to that property of your data model in the ImmersiveView, by using an onChange. When you get the change, you can update the VideoPlayerComponent of your entity appropriately.

Controlling spacial video from floating window
 
 
Q