Helge
Helge

Reputation: 39

RoomPlan‘s RoomCaptureSession and SwiftUI

I’m playing with some example code for the RoomPlan API, trying to combine it with SwiftUI. While I was able to use RoomCaptureView in SwiftUI, I‘m struggling to get the more flexible RoomCaptureSession running together with an arSession. Compiler message says it‘s „missing argument for parameter ‚frame‘ in call“, but I rather guess to have mixed up the delegation.

This is based on an example at it-jim.com.

Some hints would be very appreciated!

The Delegate:

import Foundation
import ARKit
import RealityKit
import RoomPlan

class CustomCaptureView: ARView, RoomCaptureSessionDelegate {
    static var shared = CustomCaptureView()    // here comes „Missing argument for parameter ‚frame‘ in call
    let captureSession: RoomCaptureSession = RoomCaptureSession()
    let roomBuilder: RoomBuilder = RoomBuilder(options: \[.beautifyObjects\])

    var delegate: RoomCaptureSessionDelegate?
    
    required init(frame: CGRect) {
        super.init(frame: frame)
        initSession()
    }
    
    @MainActor required dynamic init?(coder decoder: NSCoder) {
        super.init(coder: decoder)
        initSession()
    }
    
    func initSession() {
        self.cameraMode = .ar
        captureSession.delegate = self
        self.session = captureSession.arSession
    }
    
    func captureSession(_ session: RoomCaptureSession, didUpdate: CapturedRoom) {
        DispatchQueue.main.async {
            self.scene.anchors.removeAll()
            for wall in didUpdate.walls {
                self.drawBox(scene: self.scene, dimensions: wall.dimensions, transform: wall.transform, confidence: wall.confidence)
            }
    
            for object in didUpdate.objects {
                self.drawBox(scene: self.scene, dimensions: object.dimensions, transform: object.transform, confidence: object.confidence)
            }            
        }        
    }
    func drawBox(scene: Scene, dimensions: simd_float3, transform: float4x4, confidence: CapturedRoom.Confidence) {
        // some colored boxes replacing detected objects
    }
    func captureSession(_ session: RoomCaptureSession, didEndWith data: CapturedRoomData, error: (Error)?) {}

}

And the ContentView:

import SwiftUI
import RoomPlan
import ARKit
import RealityKit

struct RoomCaptureViewRep : UIViewRepresentable {
  func makeUIView(context: Context) -> CustomCaptureView {  
    CustomCaptureView.shared.captureSession 
  }
  func updateUIView(_ uiView: UIViewType, context: Context) {}    
  
}

struct ActivityViewControllerRep: UIViewControllerRepresentable { 
  var items: [Any]
  var activities: [UIActivity]? = nil

  func makeUIViewController(context: UIViewControllerRepresentableContext<ActivityViewControllerRep>) -> UIActivityViewController { // Erzeugt einen UIKit View controller im SwiftUI Kontext   
  let controller = UIActivityViewController(activityItems: items, applicationActivities: activities)
  return controller
}

func updateUIViewController(_ uiViewController: UIActivityViewController, context: UIViewControllerRepresentableContext<ActivityViewControllerRep>) { }    
}  

struct ContentView: View { // eigentliche Scan-Ansicht, wird aufgerufen von ContentView
  var body: some View {
    RoomCaptureViewRep()
  }
} 

Upvotes: 3

Views: 677

Answers (1)

MrProgrammer
MrProgrammer

Reputation: 463

Notice how both init in your CustomCaptureView need some parameters to initialise. As far as I can tell, you probably need to use this constructor:

required init(frame: CGRect) {
    super.init(frame: frame)
    initSession()
}

which means you need to provide a frame. So, something like:

static var shared = CustomCaptureView(frame: .zero)

should get your code working.

Upvotes: 0

Related Questions