Skip to content

Commit aa315b2

Browse files
author
Vasilii Muravev
committed
AR-showing-deals
1 parent c0fe8cc commit aa315b2

23 files changed

+147
-22
lines changed

RealDeal.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
4D6958A41EED572A00F7603B /* VirtualObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6958A31EED572A00F7603B /* VirtualObject.swift */; };
1011
4DB74AB51EEC8C8B00DC970D /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB74AB41EEC8C8800DC970D /* Utilities.swift */; };
1112
4DB74AB71EECAC9A00DC970D /* LogoPartsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB74AB61EECAC9A00DC970D /* LogoPartsView.swift */; };
1213
8839F0D61EECF72800B0EC36 /* NetworkClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8839F0D51EECF72800B0EC36 /* NetworkClient.swift */; };
@@ -28,6 +29,7 @@
2829

2930
/* Begin PBXFileReference section */
3031
3DF0CEB4613286AE322CD73D /* Pods-RealDeal.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RealDeal.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RealDeal/Pods-RealDeal.debug.xcconfig"; sourceTree = "<group>"; };
32+
4D6958A31EED572A00F7603B /* VirtualObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VirtualObject.swift; sourceTree = "<group>"; };
3133
4DB74AB41EEC8C8800DC970D /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = "<group>"; };
3234
4DB74AB61EECAC9A00DC970D /* LogoPartsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoPartsView.swift; sourceTree = "<group>"; };
3335
837BC05258B7836F91C99521 /* Pods-RealDeal.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RealDeal.release.xcconfig"; path = "Pods/Target Support Files/Pods-RealDeal/Pods-RealDeal.release.xcconfig"; sourceTree = "<group>"; };
@@ -150,6 +152,7 @@
150152
children = (
151153
88F877631EECE27E003CFD04 /* Merchant.swift */,
152154
8839F0D71EED150300B0EC36 /* Offer.swift */,
155+
4D6958A31EED572A00F7603B /* VirtualObject.swift */,
153156
);
154157
path = EntityModels;
155158
sourceTree = "<group>";
@@ -302,6 +305,7 @@
302305
8839F0DA1EED196500B0EC36 /* OffersManager.swift in Sources */,
303306
88BC26961EEC5078003FC70D /* ViewController.swift in Sources */,
304307
88BC26921EEC5078003FC70D /* AppDelegate.swift in Sources */,
308+
4D6958A41EED572A00F7603B /* VirtualObject.swift in Sources */,
305309
88F877641EECE27E003CFD04 /* Merchant.swift in Sources */,
306310
8839F0D61EECF72800B0EC36 /* NetworkClient.swift in Sources */,
307311
8839F0D81EED150300B0EC36 /* Offer.swift in Sources */,

RealDeal/Controllers/ViewController.swift

+65-22
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ class ViewController: UIViewController, ARSCNViewDelegate {
1818
fileprivate var mainNode: SCNNode!
1919
fileprivate weak var logoView: LogoPartsView?
2020
fileprivate var requestLock = false
21+
fileprivate var checkingFrame: ARFrame?
2122
fileprivate var timer = Timer()
23+
fileprivate var offers = [Offer]()
24+
fileprivate var showedMerchants: [OffersMerchants] = []
2225

2326
override func viewDidLoad() {
2427
super.viewDidLoad()
@@ -34,13 +37,13 @@ class ViewController: UIViewController, ARSCNViewDelegate {
3437
super.viewDidAppear(animated)
3538
setupSession()
3639
// @TODO: Temporary test deals icons
37-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
38-
self.add(.dealfree, position: SCNVector3(-1, 0, -3.8))
39-
self.add(.deal10, position: SCNVector3(0, 0, -4))
40-
self.add(.deal20, position: SCNVector3(1, 0, -3.8))
41-
self.add(.deal30, position: SCNVector3(3, 0, -3))
42-
self.add(.deal40, position: SCNVector3(5, 0, 0))
43-
}
40+
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
41+
// self.add(.dealfree, position: SCNVector3(-1, 0, -3.8))
42+
// self.add(.deal10, position: SCNVector3(0, 0, -4))
43+
// self.add(.deal20, position: SCNVector3(1, 0, -3.8))
44+
// self.add(.deal30, position: SCNVector3(3, 0, -3))
45+
// self.add(.deal40, position: SCNVector3(5, 0, 0))
46+
// }
4447
guard let logoView = logoView else { return }
4548
view.bringSubview(toFront: logoView)
4649
logoView.open(completion: { [weak logoView] (success) in
@@ -52,6 +55,31 @@ class ViewController: UIViewController, ARSCNViewDelegate {
5255
super.viewWillDisappear(animated)
5356
session.pause()
5457
}
58+
59+
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
60+
super.touchesBegan(touches, with: event)
61+
var hitTestOptions = [SCNHitTestOption: Any]()
62+
hitTestOptions[SCNHitTestOption.boundingBoxOnly] = true
63+
let results: [SCNHitTestResult] = sceneView.hitTest(touches.first!.location(in: sceneView), options: hitTestOptions)
64+
for result in results {
65+
var node = result.node
66+
var object1: VirtualObject?
67+
while node.parent != nil {
68+
if let parent = node.parent as? VirtualObject {
69+
object1 = parent
70+
break
71+
}
72+
node = node.parent!
73+
}
74+
guard let object = object1 else { continue }
75+
let wrapperNode = VirtualObject.convert(object)
76+
DispatchQueue.main.async {
77+
object.removeFromParentNode()
78+
self.setNewVirtualObjectPosition(object.position, wrapperNode)
79+
self.mainNode.addChildNode(wrapperNode)
80+
}
81+
}
82+
}
5583
}
5684

5785

@@ -77,7 +105,29 @@ extension ViewController: ARSessionDelegate {
77105
// Send out request and cache the image
78106
let networkClient = NetworkClient()
79107
networkClient.postMerchantIcon(image, success: { (merchants) in
80-
print("\(merchants)")
108+
for merchant in merchants {
109+
print(merchant.name)
110+
guard let offerMerchant = OffersMerchants(rawValue: merchant.name) else { continue }
111+
if self.showedMerchants.contains(offerMerchant) {
112+
continue
113+
}
114+
self.showedMerchants.append(offerMerchant)
115+
let offers = OffersManager.shared.offersForMerchant(merchant.name)
116+
if self.offers.contains(where: { $0.merchants.contains(merchant.name) }) {
117+
// Don't do anything since we already check this merchant
118+
continue
119+
}
120+
self.offers.append(contentsOf: offers)
121+
// Need to add popup to merchant
122+
let angles = frame.camera.eulerAngles
123+
let position = SCNVector3.positionFromTransform(frame.camera.transform)
124+
let defaultDistance: Float = 4
125+
let z1 = position.z - sin(angles.y + Float.pi/2) * defaultDistance
126+
let x1 = position.x + cos(angles.y + Float.pi/2) * defaultDistance
127+
DispatchQueue.main.async {
128+
self.add(.dealfree, position: SCNVector3(x1, -1.3, z1))
129+
}
130+
}
81131
self.requestLock = false
82132
session.delegate = self
83133
}, failure: { (error) in
@@ -96,13 +146,7 @@ fileprivate extension ViewController {
96146
/// Adds SCNNode to the current scene.
97147
func add(_ deal: Deals, position: SCNVector3) {
98148
DispatchQueue.global().async {
99-
let scene = SCNScene(named: "art.scnassets/" + deal.rawValue)!
100-
let wrapperNode = SCNNode()
101-
for child in scene.rootNode.childNodes {
102-
child.geometry?.firstMaterial?.lightingModel = .physicallyBased
103-
child.movabilityHint = .movable
104-
wrapperNode.addChildNode(child)
105-
}
149+
let wrapperNode = VirtualObject(deal)
106150
DispatchQueue.main.async {
107151
self.setNewVirtualObjectPosition(position, wrapperNode)
108152
self.mainNode.addChildNode(wrapperNode)
@@ -131,7 +175,7 @@ fileprivate extension ViewController {
131175

132176
func setupSession() {
133177
let configuration = ARWorldTrackingSessionConfiguration()
134-
// configuration.planeDetection = .horizontal
178+
// configuration.planeDetection = .horizontal
135179
session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
136180
}
137181

@@ -173,10 +217,9 @@ fileprivate extension ViewController {
173217
}
174218
}
175219

176-
enum Deals: String {
177-
case dealfree = "dealfree.scn"
178-
case deal10 = "deal10.scn"
179-
case deal20 = "deal20.scn"
180-
case deal30 = "deal30.scn"
181-
case deal40 = "deal40.scn"
220+
enum OffersMerchants: String {
221+
case walmart = "Walmart"
222+
case bath = "Bath and Body Works"
223+
case target = "Target"
182224
}
225+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//
2+
// VirtualObject.swift
3+
// RealDeal
4+
//
5+
// Created by Vasilii Muravev on 6/11/17.
6+
// Copyright © 2017 SilverLogic. All rights reserved.
7+
//
8+
9+
import ARKit
10+
11+
class VirtualObject: SCNNode {
12+
13+
let smallOne: Bool
14+
let deal: Deals
15+
16+
init(_ deal: Deals) {
17+
self.deal = deal
18+
switch deal {
19+
case .deal10, .deal20, .deal30, .deal40, .dealfree:
20+
smallOne = true
21+
default:
22+
smallOne = false
23+
}
24+
super.init()
25+
let scene = SCNScene(named: "art.scnassets/" + deal.rawValue)!
26+
for child in scene.rootNode.childNodes {
27+
child.geometry?.firstMaterial?.lightingModel = .physicallyBased
28+
child.movabilityHint = .movable
29+
addChildNode(child)
30+
}
31+
}
32+
33+
required init?(coder aDecoder: NSCoder) {
34+
fatalError("init(coder:) has not been implemented")
35+
}
36+
37+
class func convert(_ object: VirtualObject) -> VirtualObject {
38+
return VirtualObject(object.deal.nextOne())
39+
}
40+
}
41+
42+
enum Deals: String {
43+
case dealfree = "dealfree.scn"
44+
case deal10 = "deal10.scn"
45+
case deal20 = "deal20.scn"
46+
case deal30 = "deal30.scn"
47+
case deal40 = "deal40.scn"
48+
case dealfreeL = "dealfreeL.scn"
49+
case deal10L = "deal10L.scn"
50+
case deal20L = "deal20L.scn"
51+
case deal30L = "deal30L.scn"
52+
case deal40L = "deal40L.scn"
53+
54+
func nextOne() -> Deals {
55+
switch self {
56+
case .deal10:
57+
return .deal10L
58+
case .deal20:
59+
return .deal20L
60+
case .deal30:
61+
return .deal30L
62+
case .deal40:
63+
return .deal40L
64+
case .dealfree:
65+
return .dealfreeL
66+
case .deal10L:
67+
return .deal10
68+
case .deal20L:
69+
return .deal20
70+
case .deal30L:
71+
return .deal30
72+
case .deal40L:
73+
return .deal40
74+
case .dealfreeL:
75+
return .dealfree
76+
}
77+
}
78+
}

RealDeal/art.scnassets/deal10.png

-22.8 KB
Loading

RealDeal/art.scnassets/deal10.scn

183 Bytes
Binary file not shown.

RealDeal/art.scnassets/deal10L.png

31.5 KB
Loading

RealDeal/art.scnassets/deal10L.scn

9.5 KB
Binary file not shown.

RealDeal/art.scnassets/deal20.png

-32 KB
Loading

RealDeal/art.scnassets/deal20.scn

183 Bytes
Binary file not shown.

RealDeal/art.scnassets/deal20L.png

41.1 KB
Loading

RealDeal/art.scnassets/deal20L.scn

9.5 KB
Binary file not shown.

RealDeal/art.scnassets/deal30.png

-32.2 KB
Loading

RealDeal/art.scnassets/deal30.scn

183 Bytes
Binary file not shown.

RealDeal/art.scnassets/deal30L.png

41.6 KB
Loading

RealDeal/art.scnassets/deal30L.scn

9.51 KB
Binary file not shown.

RealDeal/art.scnassets/deal40.png

-31.8 KB
Loading

RealDeal/art.scnassets/deal40.scn

-189 Bytes
Binary file not shown.

RealDeal/art.scnassets/deal40L.png

40.7 KB
Loading

RealDeal/art.scnassets/deal40L.scn

9.33 KB
Binary file not shown.

RealDeal/art.scnassets/dealfree.png

-21.9 KB
Loading

RealDeal/art.scnassets/dealfree.scn

-183 Bytes
Binary file not shown.

RealDeal/art.scnassets/dealfreeL.png

28.7 KB
Loading

RealDeal/art.scnassets/dealfreeL.scn

9.32 KB
Binary file not shown.

0 commit comments

Comments
 (0)