Section 3 - Add Export Features

Add controls to enable the export features of Remodel-AR.

Step 1

Start with the code from “Add a Color Picker”.

//
//  ContentView.swift
//  Painty
//

import RemodelAR
import SwiftUI

struct ContentView: View {
    @ObservedObject var model = ARStateModel()

    @State private var colorIndex = 0
    @State private var showStroke = true

    var body: some View {
        ZStack {
            ZStack(alignment: .bottom, content: {
                arView
                    .edgesIgnoringSafeArea(.all)
                colorPicker
            })
        }
        .onAppear {
            model.pickColor(paint: colorItems[0])
        }
    }
}

private extension ContentView {
    var arView: ARView {
        RemodelARLib.makeARView(model: model, arMethod: .Lidar)
    }

    var colorItems: [WallPaint] {
        let numHues = 20
        var colors = [WallPaint]()
        for i in 0..<numHues {
            let color_8_8 = Color(hue: Double(i)/Double(numHues),
                                  saturation: 0.8,
                                  brightness: 0.8)
            let color_8_6 = Color(hue: Double(i)/Double(numHues),
                                  saturation: 0.8,
                                  brightness: 0.6)
            let color_8_4 = Color(hue: Double(i)/Double(numHues),
                                  saturation: 0.8,
                                  brightness: 0.4)
            let color_8_2 = Color(hue: Double(i)/Double(numHues),
                                  saturation: 0.8,
                                  brightness: 0.2)

            colors.append(WallPaint(id: "\(i * 4 + 1)", color: color_8_8.uiColor()))
            colors.append(WallPaint(id: "\(i * 4 + 2)", color: color_8_6.uiColor()))
            colors.append(WallPaint(id: "\(i * 4 + 3)", color: color_8_4.uiColor()))
            colors.append(WallPaint(id: "\(i * 4 + 4)", color: color_8_2.uiColor()))
        }
        return colors
    }

    var colorPicker: some View {
        ScrollView(.horizontal) {
            HStack {
                ForEach(0..<colorItems.count) { i in
                    Button(action: {
                        showStroke = true
                        colorIndex = i
                        model.pickColor(paint: colorItems[i])
                    }) {
                        RoundedRectangle(cornerRadius: 17)
                            .strokeBorder(lineWidth: (showStroke && i == colorIndex) ? 5 : 0)
                            .foregroundColor(.white)
                            .background(Color(colorItems[i].color))
                            .clipShape(RoundedRectangle(cornerRadius: 17))
                            .frame(width: 74, height: 74)
                            .animation(Animation.interpolatingSpring(stiffness: 60, damping: 15))
                    }
                    .onTapGesture {
                        self.showStroke = true
                    }
                }
            }
            .padding()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Step 2

Add a new extension then create a Save Photo Button view variable to save scene images.

private extension ContentView {
    var savePhotoButton: some View {
        Button(action: {
            model.sharePhoto()
        }, label: {
            Image(systemName: "camera.fill")
                .foregroundColor(.white)
        })
        .padding()
        .background(Color(.sRGB, white: 0, opacity: 0.15))
        .cornerRadius(10)
    }
}

Step 3

Add a Save 3D Model Button view variable to save the 3D model of the scene.

    var save3DModelButton: some View {
        Button(action: {
            model.save3DModel()
        }, label: {
            Image("saveMesh")
                .foregroundColor(.white)
        })
        .padding()
        .background(Color(.sRGB, white: 0, opacity: 0.15))
        .cornerRadius(10)
    }

Step 4

While we’re at it, let’s also add a reset button to reset the painting experience.

    var resetSceneButton: some View {
        Button(action: {
            model.resetScene()
        }, label: {
            Image("reset")
                .foregroundColor(.white)
        })
        .padding()
        .background(Color(.sRGB, white: 0, opacity: 0.15))
        .cornerRadius(10)
    }

Step 5

Add the Save Photo, Save 3D Model, and Reset buttons to an HStack before the colorPicker.

    var body: some View {
        ZStack {
            ZStack(alignment: .bottom, content: {
                arView
                    .edgesIgnoringSafeArea(.all)
                VStack {
                    Spacer()
                    HStack {
                        savePhotoButton
                        save3DModelButton
                        resetSceneButton
                    }
                    colorPicker
                }
            })
        }
        .onAppear {
            model.pickColor(paint: colorItems[0])
        }
    }

Step 6

Navigate to the Project->Painty->Info tab. Add a new entry for the “Privacy - Photo Library Usage Description” key. Give it a description.

Step 7

Build and run your project. You will see your new controls have been added. Touch a wall to paint it. Try saving a picture and a mesh of your room.

If at any point you need help from the Passio team, please reach out to us at support@passiolife.com

Last updated