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