1

I am trying to tweak this code I found on github in order to create a button that clears the 3d objects imported in an AR scene.

Here's the code for my Swift views:

ContentView:

import SwiftUI

struct ContentView: View {

    // MARK: - Properties

    @State private var isPlacementEnabled = false
    @State private var selectedModel: Model?
    @State private var modelConfirmedForPlacement: Model?

    private var models: [Model] = {
        let fileManager = FileManager.default
        guard let path = Bundle.main.resourcePath,
              let files = try? fileManager.contentsOfDirectory(atPath: path) else {
            return []
        }
        return files
            .filter { $0.hasSuffix(".usdz") }
            .compactMap { $0.replacingOccurrences(of: ".usdz", with: "") }
            .compactMap { Model(modelName: $0 ) }
    }()

    // MARK: Body

    var body: some View {
        ZStack(alignment: .bottom) {
            ARViewRepresentable(
                modelConfirmedForPlacement: $modelConfirmedForPlacement
            )

            if isPlacementEnabled {
                PlacementButtonView(
                    isPlacementEnabled: $isPlacementEnabled,
                    selectedModel: $selectedModel,
                    modelConfirmedForPlacement: $modelConfirmedForPlacement
                )
            } else {
                ModelPickerView(
                    isPlacementEnabled: $isPlacementEnabled,
                    selectedModel: $selectedModel,
                    models: models
                )
            }
        }
    }
}

// MARK: - Preview

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

CustomARView:

import RealityKit
import ARKit
import FocusEntity

class CustomARView: ARView {

    // MARK: - Properties

    var focusEntity: FocusEntity?

    // MARK: - Lifecycle

    required init(frame frameRect: CGRect) {
        super.init(frame: frameRect)
        setupFocusEntity()
        setupARView()
    }

    required init?(coder decoder: NSCoder) {
        super.init(coder: decoder)
        setupFocusEntity()
        setupARView()
    }
}

// MARK: - Private

private extension CustomARView {

    func setupFocusEntity() {
        focusEntity = FocusEntity(on: self, style: .classic(color: UIColor.red))
        focusEntity?.setAutoUpdate(to: true)
    }

    func setupARView() {

        // Uncomment to user ".nonAR" camera.
        //useNonARCameraSample()

        let config = ARWorldTrackingConfiguration()
        config.planeDetection = [.horizontal, .vertical]
        config.environmentTexturing = .automatic
        if ARWorldTrackingConfiguration.supportsSceneReconstruction(.mesh) {
            config.sceneReconstruction = .mesh
        }
        session.run(config)
    }

    /// From: https://developer.apple.com/forums/thread/122229
    func useNonARCameraSample() {

        // RealityKit now adds and uses a default PerspectiveCamera.
        cameraMode = .nonAR

        // Provide your own PerspectiveCamera.
        // See: https://developer.apple.com/documentation/realitykit/perspectivecamera
        let cameraEntity = PerspectiveCamera()
        cameraEntity.camera.fieldOfViewInDegrees = 140
        let cameraAnchor = AnchorEntity(world: .one)
        cameraAnchor.addChild(cameraEntity)

        scene.addAnchor(cameraAnchor)
    }
}

ARViewRepresentable:

import SwiftUI
import RealityKit
import ARKit

struct ARViewRepresentable: UIViewRepresentable {

    // MARK: - Properties

    @Binding var modelConfirmedForPlacement: Model?

    // MARK: - UIViewRepresentable

    func makeUIView(context: Context) -> ARView {
        CustomARView(frame: .zero)
    }

    func updateUIView(_ uiView: ARView, context: Context) {
        guard let model = modelConfirmedForPlacement else { return }

        if let modelEntity = model.modelEntity {
            print("Adding model to scene: \(model.modelName)")
            let anchorEntity = AnchorEntity(plane: .any)
            anchorEntity.addChild(modelEntity .clone(recursive: true))
            uiView.scene.addAnchor(anchorEntity)
        } else {
            print("Unable to load modelEntity for: \(model.modelName)")
        }

        DispatchQueue.main.async {
            modelConfirmedForPlacement = nil
        }
    }
}

ModelPickerView:

import SwiftUI

struct ModelPickerView: View {
    
    // MARK: - Properties

    @Binding var isPlacementEnabled: Bool
    @Binding var selectedModel: Model?
    
    var models: [Model]
    
    // MARK: Body
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 30) {
                ForEach(models, id: \.self) { model in
                    Button {
                        print("Picked model: \(model.modelName)")
                        selectedModel = model
                        isPlacementEnabled = true
                    } label: {
                        Image(uiImage: model.image)
                            .resizable()
                            .frame(height: 80)
                            .aspectRatio(1/1, contentMode: .fit)
                            .background( Color.white)
                            .cornerRadius(12)
                    }
                    .buttonStyle(PlainButtonStyle())
                }
            }
        }
        .padding(20)
        .background(Color.black.opacity(0.5))
    }
}

PlacementButtonView:

import SwiftUI

struct PlacementButtonView: View {
    
    // MARK: - Properties

    @Binding var isPlacementEnabled: Bool
    @Binding var selectedModel: Model?
    @Binding var modelConfirmedForPlacement: Model?
    
    // MARK: Body
    
    var body: some View {
        HStack {
            Button {
                print("Cancel button tapped")
                resetPlacementParameters()
            } label: {
                Image(systemName: "xmark")
                    .frame(width: 60, height: 60)
                    .font(.title)
                    .background(Color.white.opacity(0.75))
                    .cornerRadius(30)
                    .padding(20)
            }
            
            Button {
                print("Confirm button tapped")
                modelConfirmedForPlacement = selectedModel
                resetPlacementParameters()
            } label: {
                Image(systemName: "checkmark")
                    .frame(width: 60, height: 60)
                    .font(.title)
                    .background(Color.white.opacity(0.75))
                    .cornerRadius(30)
                    .padding(20)
            }
        }
    }
}

// MARK: - Private

private extension PlacementButtonView {

    func resetPlacementParameters() {
        isPlacementEnabled = false
        selectedModel = nil
    }
}

// MARK: - Preview

#if DEBUG
struct PlacementButtonView_Previews: PreviewProvider {
    static var previews: some View {
        PlacementButtonView(
            isPlacementEnabled: .constant(false),
            selectedModel: .constant(nil),
            modelConfirmedForPlacement: .constant(nil)
        )
    }
}
#endif

I tried using the Apple Documentation, but I didn't manage to make anything work :( .

Tavi
  • 11
  • 1

0 Answers0