diff --git a/.github/PULL_REQUEST_TEMPLATE.MD b/.github/PULL_REQUEST_TEMPLATE.MD new file mode 100644 index 00000000..bbd8b8a0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.MD @@ -0,0 +1,22 @@ +### Background + +Describe the purpose of this pull request. + +### Breaking Changes +Describe any breaking changes that this pull request will introduce. + +### Meta +- Tied to Version Release(s): + +### Checklist + +- [ ] Appropriate label has been added to this PR (i.e., Bug, Enhancement, etc.). +- [ ] Documentation has been added to all `open`, and `public` scoped methods and properties. +- [ ] Changelog has been updated +- [ ] Tests have have been added to all new features. (not a requirement, but helpful) +- [ ] Image/GIFs have been added for all UI related changed. + + + + +### Screenshots diff --git a/.swift-version b/.swift-version deleted file mode 100644 index 5186d070..00000000 --- a/.swift-version +++ /dev/null @@ -1 +0,0 @@ -4.0 diff --git a/.swiftlint.yml b/.swiftlint.yml index 0cbb415e..acb8a583 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,7 +1,10 @@ +line_length: 130 + disabled_rules: - - file_length - - identifier_name - - line_length - - shorthand_operator - - type_body_length -function_body_length: 70 \ No newline at end of file + - variable_name + - todo + - valid_docs + +excluded: # paths to ignore during linting. Takes precedence over `included`. + - Carthage + - Pods diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..ce6b9f5a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: objective-c +osx_image: xcode10.1 + +script: + - pod lib lint + +notifications: + email: false diff --git a/ARCL.podspec b/ARCL.podspec index 4dddc457..fd2691c6 100644 --- a/ARCL.podspec +++ b/ARCL.podspec @@ -7,8 +7,9 @@ Pod::Spec.new do |s| s.license = { :type => 'MIT', :file => 'LICENSE' } s.source = { :git => "https://ProjectDent@github.com/ProjectDent/ARKit-CoreLocation.git", :tag => s.version.to_s, :submodules => false } s.platform = :ios, '9.0' + s.swift_version = "4.2" s.requires_arc = true - s.source_files = 'ARCL/Source/*.swift' + s.source_files = 'ARCL/Source/**/*.{swift}' s.frameworks = 'Foundation', 'UIKit', 'ARKit', 'CoreLocation', 'MapKit', 'SceneKit' s.ios.deployment_target = '9.0' end diff --git a/ARCL/Source/CLLocation+Extensions.swift b/ARCL/Source/CLLocation+Extensions.swift deleted file mode 100644 index 5f90672a..00000000 --- a/ARCL/Source/CLLocation+Extensions.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// CLLocation+Extensions.swift -// ARKit+CoreLocation -// -// Created by Andrew Hart on 02/07/2017. -// Copyright © 2017 Project Dent. All rights reserved. -// - -import Foundation -import CoreLocation - -let EARTH_RADIUS = 6371000.0 - -///Translation in meters between 2 locations -public struct LocationTranslation { - public var latitudeTranslation: Double - public var longitudeTranslation: Double - public var altitudeTranslation: Double - - public init(latitudeTranslation: Double, longitudeTranslation: Double, altitudeTranslation: Double) { - self.latitudeTranslation = latitudeTranslation - self.longitudeTranslation = longitudeTranslation - self.altitudeTranslation = altitudeTranslation - } -} - -public extension CLLocation { - public convenience init(coordinate: CLLocationCoordinate2D, altitude: CLLocationDistance) { - self.init(coordinate: coordinate, altitude: altitude, horizontalAccuracy: 0, verticalAccuracy: 0, timestamp: Date()) - } - - ///Translates distance in meters between two locations. - ///Returns the result as the distance in latitude and distance in longitude. - public func translation(toLocation location: CLLocation) -> LocationTranslation { - let inbetweenLocation = CLLocation(latitude: self.coordinate.latitude, longitude: location.coordinate.longitude) - - let distanceLatitude = location.distance(from: inbetweenLocation) - - let latitudeTranslation: Double - - if location.coordinate.latitude > inbetweenLocation.coordinate.latitude { - latitudeTranslation = distanceLatitude - } else { - latitudeTranslation = 0 - distanceLatitude - } - - let distanceLongitude = self.distance(from: inbetweenLocation) - - let longitudeTranslation: Double - - if self.coordinate.longitude > inbetweenLocation.coordinate.longitude { - longitudeTranslation = 0 - distanceLongitude - } else { - longitudeTranslation = distanceLongitude - } - - let altitudeTranslation = location.altitude - self.altitude - - return LocationTranslation( - latitudeTranslation: latitudeTranslation, - longitudeTranslation: longitudeTranslation, - altitudeTranslation: altitudeTranslation) - } - - public func translatedLocation(with translation: LocationTranslation) -> CLLocation { - let latitudeCoordinate = self.coordinate.coordinateWithBearing(bearing: 0, distanceMeters: translation.latitudeTranslation) - - let longitudeCoordinate = self.coordinate.coordinateWithBearing(bearing: 90, distanceMeters: translation.longitudeTranslation) - - let coordinate = CLLocationCoordinate2D( - latitude: latitudeCoordinate.latitude, - longitude: longitudeCoordinate.longitude) - - let altitude = self.altitude + translation.altitudeTranslation - - return CLLocation(coordinate: coordinate, altitude: altitude, horizontalAccuracy: self.horizontalAccuracy, verticalAccuracy: self.verticalAccuracy, timestamp: self.timestamp) - } -} - -public extension CLLocationCoordinate2D { - public func coordinateWithBearing(bearing: Double, distanceMeters: Double) -> CLLocationCoordinate2D { - // formula by http://www.movable-type.co.uk/scripts/latlong.html - let lat1 = self.latitude * Double.pi / 180 - let lon1 = self.longitude * Double.pi / 180 - - let distance = distanceMeters / EARTH_RADIUS - let angularBearing = bearing * Double.pi / 180 - - var lat2 = lat1 + distance * cos(angularBearing) - let dLat = lat2 - lat1 - let dPhi = log(tan(lat2 / 2 + Double.pi/4) / tan(lat1 / 2 + Double.pi/4)) - let q = (dPhi != 0) ? dLat/dPhi : cos(lat1) // E-W line gives dPhi=0 - let dLon = distance * sin(angularBearing) / q - - // check for some daft bugger going past the pole - if fabs(lat2) > Double.pi/2 { - lat2 = lat2 > 0 ? Double.pi - lat2 : -(Double.pi - lat2) - } - var lon2 = lon1 + dLon + 3 * Double.pi - while lon2 > 2 * Double.pi { - lon2 -= 2 * Double.pi - } - lon2 -= Double.pi - - return CLLocationCoordinate2D(latitude: lat2 * 180 / Double.pi, longitude: lon2 * 180 / Double.pi) - } -} diff --git a/ARCL/Source/Extensions/BaseTypes+Extensions.swift b/ARCL/Source/Extensions/BaseTypes+Extensions.swift new file mode 100644 index 00000000..9553a998 --- /dev/null +++ b/ARCL/Source/Extensions/BaseTypes+Extensions.swift @@ -0,0 +1,29 @@ +// +// BaseTypes+Extensions.swift +// ARKit+CoreLocation +// +// Created by Ilya Seliverstov on 08/08/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// + +import Foundation + +public extension Double { + + var metersToLatitude: Double { + return self / (6_360_500.0) + } + + var metersToLongitude: Double { + return self / (5_602_900.0) + } +} + +public extension Float { + var short: String { return String(format: "%.2f", self) } +} + +public extension Int { + var short: String { return String(format: "%02d", self) } + var short3: String { return String(format: "%03d", self / 1_000_000) } +} diff --git a/ARCL/Source/CGPoint+Extensions.swift b/ARCL/Source/Extensions/CGPoint+Extensions.swift similarity index 100% rename from ARCL/Source/CGPoint+Extensions.swift rename to ARCL/Source/Extensions/CGPoint+Extensions.swift diff --git a/ARCL/Source/Extensions/CLLocation+Extensions.swift b/ARCL/Source/Extensions/CLLocation+Extensions.swift new file mode 100644 index 00000000..ada29632 --- /dev/null +++ b/ARCL/Source/Extensions/CLLocation+Extensions.swift @@ -0,0 +1,102 @@ +// +// CLLocation+Extensions.swift +// ARKit+CoreLocation +// +// Created by Andrew Hart on 02/07/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// + +import Foundation +import CoreLocation + +///Translation in meters between 2 locations +public struct LocationTranslation { + public var latitudeTranslation: Double + public var longitudeTranslation: Double + public var altitudeTranslation: Double +} + +public extension CLLocation { + public convenience init(coordinate: CLLocationCoordinate2D, altitude: CLLocationDistance) { + self.init(coordinate: coordinate, altitude: altitude, horizontalAccuracy: 0, verticalAccuracy: 0, timestamp: Date()) + } + + ///Translates distance in meters between two locations. + ///Returns the result as the distance in latitude and distance in longitude. + public func translation(toLocation location: CLLocation) -> LocationTranslation { + let inbetweenLocation = CLLocation(latitude: self.coordinate.latitude, longitude: location.coordinate.longitude) + + let distanceLatitude = location.distance(from: inbetweenLocation) + + let latitudeTranslation = location.coordinate.latitude > inbetweenLocation.coordinate.latitude ? distanceLatitude + : -distanceLatitude + + let distanceLongitude = distance(from: inbetweenLocation) + + let longitudeTranslation = coordinate.longitude > inbetweenLocation.coordinate.longitude ? -distanceLongitude + : distanceLongitude + + let altitudeTranslation = location.altitude - self.altitude + + return LocationTranslation( latitudeTranslation: latitudeTranslation, + longitudeTranslation: longitudeTranslation, + altitudeTranslation: altitudeTranslation) + } + + public func translatedLocation(with translation: LocationTranslation) -> CLLocation { + let latitudeCoordinate = self.coordinate.coordinateWithBearing(bearing: 0, + distanceMeters: translation.latitudeTranslation) + + let longitudeCoordinate = self.coordinate.coordinateWithBearing(bearing: 90, + distanceMeters: translation.longitudeTranslation) + + let coordinate = CLLocationCoordinate2D( latitude: latitudeCoordinate.latitude, longitude: longitudeCoordinate.longitude) + + let altitude = self.altitude + translation.altitudeTranslation + + return CLLocation(coordinate: coordinate, + altitude: altitude, + horizontalAccuracy: self.horizontalAccuracy, + verticalAccuracy: self.verticalAccuracy, + timestamp: self.timestamp) + } + + func bearing(between point: CLLocation) -> Double { + let lat1 = self.coordinate.latitude.degreesToRadians + let lon1 = self.coordinate.longitude.degreesToRadians + + let lat2 = point.coordinate.latitude.degreesToRadians + let lon2 = point.coordinate.longitude.degreesToRadians + + let dLon = lon2 - lon1 + + let y = sin(dLon) * cos(lat2) + let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon) + return atan2(y, x).radiansToDegrees + } +} + +public extension CLLocation { + var debugLog: String { + return "location: \(self.coordinate), accuracy: \(self.horizontalAccuracy), date: \(self.timestamp)" + } +} + +public extension CLLocationCoordinate2D { + + func coordinateWithBearing(bearing: Double, distanceMeters: Double) -> CLLocationCoordinate2D { + //The numbers for earth radius may be _off_ here + //but this gives a reasonably accurate result.. + //Any correction here is welcome. + let distRadiansLat = distanceMeters.metersToLatitude // earth radius in meters latitude + let distRadiansLong = distanceMeters.metersToLongitude // earth radius in meters longitude + + let lat1 = self.latitude * Double.pi / 180 + let lon1 = self.longitude * Double.pi / 180 + + let lat2 = asin(sin(lat1) * cos(distRadiansLat) + cos(lat1) * sin(distRadiansLat) * cos(bearing)) + let lon2 = lon1 + atan2(sin(bearing) * sin(distRadiansLong) * cos(lat1), cos(distRadiansLong) - sin(lat1) * sin(lat2)) + + return CLLocationCoordinate2D(latitude: lat2 * 180 / Double.pi, longitude: lon2 * 180 / Double.pi) + } +} diff --git a/ARCL/Source/FloatingPoint+Radians.swift b/ARCL/Source/Extensions/FloatingPoint+Radians.swift similarity index 100% rename from ARCL/Source/FloatingPoint+Radians.swift rename to ARCL/Source/Extensions/FloatingPoint+Radians.swift diff --git a/ARCL/Source/SCNNode+Extensions.swift b/ARCL/Source/Extensions/SCNNode+Extensions.swift similarity index 64% rename from ARCL/Source/SCNNode+Extensions.swift rename to ARCL/Source/Extensions/SCNNode+Extensions.swift index 8f843c85..f0111358 100644 --- a/ARCL/Source/SCNNode+Extensions.swift +++ b/ARCL/Source/Extensions/SCNNode+Extensions.swift @@ -13,17 +13,26 @@ extension SCNNode { let quiverThickness = (quiverLength / 50.0) * quiverThickness let chamferRadius = quiverThickness / 2.0 - let xQuiverBox = SCNBox(width: quiverLength, height: quiverThickness, length: quiverThickness, chamferRadius: chamferRadius) + let xQuiverBox = SCNBox(width: quiverLength, + height: quiverThickness, + length: quiverThickness, + chamferRadius: chamferRadius) xQuiverBox.firstMaterial?.diffuse.contents = UIColor.red let xQuiverNode = SCNNode(geometry: xQuiverBox) xQuiverNode.position = SCNVector3Make(Float(quiverLength / 2.0), 0.0, 0.0) - let yQuiverBox = SCNBox(width: quiverThickness, height: quiverLength, length: quiverThickness, chamferRadius: chamferRadius) + let yQuiverBox = SCNBox(width: quiverThickness, + height: quiverLength, + length: quiverThickness, + chamferRadius: chamferRadius) yQuiverBox.firstMaterial?.diffuse.contents = UIColor.green let yQuiverNode = SCNNode(geometry: yQuiverBox) yQuiverNode.position = SCNVector3Make(0.0, Float(quiverLength / 2.0), 0.0) - let zQuiverBox = SCNBox(width: quiverThickness, height: quiverThickness, length: quiverLength, chamferRadius: chamferRadius) + let zQuiverBox = SCNBox(width: quiverThickness, + height: quiverThickness, + length: quiverLength, + chamferRadius: chamferRadius) zQuiverBox.firstMaterial?.diffuse.contents = UIColor.blue let zQuiverNode = SCNNode(geometry: zQuiverBox) zQuiverNode.position = SCNVector3Make(0.0, 0.0, Float(quiverLength / 2.0)) diff --git a/ARCL/Source/SCNVector3+Extensions.swift b/ARCL/Source/Extensions/SCNVector3+Extensions.swift similarity index 93% rename from ARCL/Source/SCNVector3+Extensions.swift rename to ARCL/Source/Extensions/SCNVector3+Extensions.swift index 44de0b83..f7b2fedb 100644 --- a/ARCL/Source/SCNVector3+Extensions.swift +++ b/ARCL/Source/Extensions/SCNVector3+Extensions.swift @@ -8,7 +8,7 @@ import SceneKit -extension SCNVector3 { +public extension SCNVector3 { ///Calculates distance between vectors ///Doesn't include the y axis, matches functionality of CLLocation 'distance' function. func distance(to anotherVector: SCNVector3) -> Float { diff --git a/ARCL/Source/LocationManager.swift b/ARCL/Source/Location Manager/LocationManager.swift similarity index 54% rename from ARCL/Source/LocationManager.swift rename to ARCL/Source/Location Manager/LocationManager.swift index 3851df29..c9fbe4ad 100644 --- a/ARCL/Source/LocationManager.swift +++ b/ARCL/Source/Location Manager/LocationManager.swift @@ -10,13 +10,25 @@ import Foundation import CoreLocation protocol LocationManagerDelegate: class { - func locationManagerDidUpdateLocation(_ locationManager: LocationManager, location: CLLocation) - func locationManagerDidUpdateHeading(_ locationManager: LocationManager, heading: CLLocationDirection, accuracy: CLLocationDirection) + func locationManagerDidUpdateLocation(_ locationManager: LocationManager, + location: CLLocation) + func locationManagerDidUpdateHeading(_ locationManager: LocationManager, + heading: CLLocationDirection, + accuracy: CLLocationDirection) } -///Handles retrieving the location and heading from CoreLocation -///Does not contain anything related to ARKit or advanced location -public class LocationManager: NSObject, CLLocationManagerDelegate { +extension LocationManagerDelegate { + func locationManagerDidUpdateLocation(_ locationManager: LocationManager, + location: CLLocation) { } + + func locationManagerDidUpdateHeading(_ locationManager: LocationManager, + heading: CLLocationDirection, + accuracy: CLLocationDirection) { } +} + +/// Handles retrieving the location and heading from CoreLocation +/// Does not contain anything related to ARKit or advanced location +public class LocationManager: NSObject { weak var delegate: LocationManagerDelegate? private var locationManager: CLLocationManager? @@ -44,43 +56,41 @@ public class LocationManager: NSObject, CLLocationManagerDelegate { } func requestAuthorization() { - if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways || - CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse { + if CLLocationManager.authorizationStatus() == .authorizedAlways || + CLLocationManager.authorizationStatus() == .authorizedWhenInUse { return } - if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.denied || - CLLocationManager.authorizationStatus() == CLAuthorizationStatus.restricted { + if CLLocationManager.authorizationStatus() == .denied || + CLLocationManager.authorizationStatus() == .restricted { return } - self.locationManager?.requestWhenInUseAuthorization() + locationManager?.requestWhenInUseAuthorization() } +} - // MARK: - CLLocationManagerDelegate +// MARK: - CLLocationManagerDelegate + +extension LocationManager: CLLocationManagerDelegate { public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { } public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { - for location in locations { - self.delegate?.locationManagerDidUpdateLocation(self, location: location) + locations.forEach { + delegate?.locationManagerDidUpdateLocation(self, location: $0) } self.currentLocation = manager.location } public func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) { - if newHeading.headingAccuracy >= 0 { - self.heading = newHeading.trueHeading - } else { - self.heading = newHeading.magneticHeading - } - - self.headingAccuracy = newHeading.headingAccuracy + heading = newHeading.headingAccuracy >= 0 ? newHeading.trueHeading : newHeading.magneticHeading + headingAccuracy = newHeading.headingAccuracy - self.delegate?.locationManagerDidUpdateHeading(self, heading: self.heading!, accuracy: newHeading.headingAccuracy) + delegate?.locationManagerDidUpdateHeading(self, heading: heading!, accuracy: newHeading.headingAccuracy) } public func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool { diff --git a/ARCL/Source/SceneLocationEstimate+Extensions.swift b/ARCL/Source/Location Manager/SceneLocationEstimate+Extensions.swift similarity index 100% rename from ARCL/Source/SceneLocationEstimate+Extensions.swift rename to ARCL/Source/Location Manager/SceneLocationEstimate+Extensions.swift diff --git a/ARCL/Source/SceneLocationEstimate.swift b/ARCL/Source/Location Manager/SceneLocationEstimate.swift similarity index 100% rename from ARCL/Source/SceneLocationEstimate.swift rename to ARCL/Source/Location Manager/SceneLocationEstimate.swift diff --git a/ARCL/Source/Location Manager/SceneLocationManager.swift b/ARCL/Source/Location Manager/SceneLocationManager.swift new file mode 100644 index 00000000..5f87e7c1 --- /dev/null +++ b/ARCL/Source/Location Manager/SceneLocationManager.swift @@ -0,0 +1,145 @@ +// +// SceneLocationManager.swift +// ARKit+CoreLocation +// +// Created by Ilya Seliverstov on 10/08/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// + +import Foundation +import ARKit +import CoreLocation +import MapKit + +///Different methods which can be used when determining locations (such as the user's location). +public enum LocationEstimateMethod { + ///Only uses core location data. + ///Not suitable for adding nodes using current position, which requires more precision. + case coreLocationDataOnly + + ///Combines knowledge about movement through the AR world with + ///the most relevant Core Location estimate (based on accuracy and time). + case mostRelevantEstimate +} + +protocol SceneLocationManagerDelegate: class { + var scenePosition: SCNVector3? { get } + + func confirmLocationOfDistantLocationNodes() + func updatePositionAndScaleOfLocationNodes() + + func didAddSceneLocationEstimate(position: SCNVector3, location: CLLocation) + func didRemoveSceneLocationEstimate(position: SCNVector3, location: CLLocation) +} + +public final class SceneLocationManager { + weak var sceneLocationDelegate: SceneLocationManagerDelegate? + + public var locationEstimateMethod: LocationEstimateMethod = .mostRelevantEstimate + public let locationManager = LocationManager() + + var sceneLocationEstimates = [SceneLocationEstimate]() + + var updateEstimatesTimer: Timer? + + /// The best estimation of location that has been taken + /// This takes into account horizontal accuracy, and the time at which the estimation was taken + /// favouring the most accurate, and then the most recent result. + /// This doesn't indicate where the user currently is. + public var bestLocationEstimate: SceneLocationEstimate? { + let sortedLocationEstimates = sceneLocationEstimates.sorted(by: { + if $0.location.horizontalAccuracy == $1.location.horizontalAccuracy { + return $0.location.timestamp > $1.location.timestamp + } + + return $0.location.horizontalAccuracy < $1.location.horizontalAccuracy + }) + + return sortedLocationEstimates.first + } + + public var currentLocation: CLLocation? { + if locationEstimateMethod == .coreLocationDataOnly { return locationManager.currentLocation } + + guard let bestEstimate = bestLocationEstimate, + let position = sceneLocationDelegate?.scenePosition else { return nil } + + return bestEstimate.translatedLocation(to: position) + } + + init() { + locationManager.delegate = self + } + + deinit { + pause() + } + + @objc + func updateLocationData() { + removeOldLocationEstimates() + + sceneLocationDelegate?.confirmLocationOfDistantLocationNodes() + sceneLocationDelegate?.updatePositionAndScaleOfLocationNodes() + } + + ///Adds a scene location estimate based on current time, camera position and location from location manager + func addSceneLocationEstimate(location: CLLocation) { + guard let position = sceneLocationDelegate?.scenePosition else { return } + + sceneLocationEstimates.append(SceneLocationEstimate(location: location, position: position)) + + sceneLocationDelegate?.didAddSceneLocationEstimate(position: position, location: location) + } + + func removeOldLocationEstimates() { + guard let currentScenePosition = sceneLocationDelegate?.scenePosition else { return } + removeOldLocationEstimates(currentScenePosition: currentScenePosition) + } + + func removeOldLocationEstimates(currentScenePosition: SCNVector3) { + let currentPoint = CGPoint.pointWithVector(vector: currentScenePosition) + + sceneLocationEstimates = sceneLocationEstimates.filter { + if #available(iOS 11.0, *) { + let radiusContainsPoint = currentPoint.radiusContainsPoint( + radius: CGFloat(SceneLocationView.sceneLimit), + point: CGPoint.pointWithVector(vector: $0.position)) + + if !radiusContainsPoint { + sceneLocationDelegate?.didRemoveSceneLocationEstimate(position: $0.position, location: $0.location) + } + + return radiusContainsPoint + } else { + return false + } + } + } + +} + +extension SceneLocationManager { + func run() { + pause() + updateEstimatesTimer = Timer.scheduledTimer( + timeInterval: 0.1, + target: self, + selector: #selector(SceneLocationManager.updateLocationData), + userInfo: nil, + repeats: true) + } + + func pause() { + updateEstimatesTimer?.invalidate() + updateEstimatesTimer = nil + } +} + +extension SceneLocationManager: LocationManagerDelegate { + + func locationManagerDidUpdateLocation(_ locationManager: LocationManager, + location: CLLocation) { + addSceneLocationEstimate(location: location) + } +} diff --git a/ARCL/Source/LocationNode.swift b/ARCL/Source/LocationNode.swift deleted file mode 100644 index af221e5a..00000000 --- a/ARCL/Source/LocationNode.swift +++ /dev/null @@ -1,129 +0,0 @@ -// -// LocationNode.swift -// ARKit+CoreLocation -// -// Created by Andrew Hart on 02/07/2017. -// Copyright © 2017 Project Dent. All rights reserved. -// - -import Foundation -import SceneKit -import CoreLocation - -/// This node type enables the client to have access to the view or image that was used to initialize the `LocationAnnotationNode`. -open class AnnotationNode: SCNNode { - public var view: UIView? - public var image: UIImage? - - public init(view: UIView?, image: UIImage?) { - super.init() - self.view = view - self.image = image - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -/// A location node can be added to a scene using a coordinate. -/// -/// Its scale and position should not be adjusted, as these are used for scene layout purposes -/// To adjust the scale and position of items within a node, you can add them to a child node and adjust them there -open class LocationNode: SCNNode { - /// Location can be changed and confirmed later by SceneLocationView. - public var location: CLLocation! - - /// A general purpose tag that can be used to find nodes already added to a SceneLocationView - public var tag: String? - - /// Whether the location of the node has been confirmed. - /// This is automatically set to true when you create a node using a location. - /// Otherwise, this is false, and becomes true once the user moves 100m away from the node, - /// except when the locationEstimateMethod is set to use Core Location data only, - /// as then it becomes true immediately. - public var locationConfirmed = false - - /// Whether a node's position should be adjusted on an ongoing basis - /// based on its' given location. - /// This only occurs when a node's location is within 100m of the user. - /// Adjustment doesn't apply to nodes without a confirmed location. - /// When this is set to false, the result is a smoother appearance. - /// When this is set to true, this means a node may appear to jump around - /// as the user's location estimates update, - /// but the position is generally more accurate. - /// Defaults to true. - public var continuallyAdjustNodePositionWhenWithinRange = true - - /// Whether a node's position and scale should be updated automatically on a continual basis. - /// This should only be set to false if you plan to manually update position and scale - /// at regular intervals. You can do this with `SceneLocationView`'s `updatePositionOfLocationNode`. - public var continuallyUpdatePositionAndScale = true - - public init(location: CLLocation?) { - self.location = location - self.locationConfirmed = location != nil - super.init() - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -open class LocationAnnotationNode: LocationNode { - /// Subnodes and adjustments should be applied to this subnode - /// Required to allow scaling at the same time as having a 2D 'billboard' appearance - public let annotationNode: AnnotationNode - - /// Whether the node should be scaled relative to its distance from the camera - /// Default value (false) scales it to visually appear at the same size no matter the distance - /// Setting to true causes annotation nodes to scale like a regular node - /// Scaling relative to distance may be useful with local navigation-based uses - /// For landmarks in the distance, the default is correct - public var scaleRelativeToDistance = false - - public init(location: CLLocation?, image: UIImage) { - let plane = SCNPlane(width: image.size.width / 100, height: image.size.height / 100) - plane.firstMaterial!.diffuse.contents = image - plane.firstMaterial!.lightingModel = .constant - - annotationNode = AnnotationNode(view: nil, image: image) - annotationNode.geometry = plane - - super.init(location: location) - - let billboardConstraint = SCNBillboardConstraint() - billboardConstraint.freeAxes = SCNBillboardAxis.Y - constraints = [billboardConstraint] - - addChildNode(annotationNode) - } - - /// Use this constructor to add a UIView as an annotation - /// UIView is more configurable then a UIImage, allowing you to add background image, labels, etc. - /// - /// - Parameters: - /// - location: The location of the node in the world. - /// - view: The view to display at the specified location. - public init(location: CLLocation?, view: UIView) { - let plane = SCNPlane(width: view.frame.size.width / 100, height: view.frame.size.height / 100) - plane.firstMaterial!.diffuse.contents = view - plane.firstMaterial!.lightingModel = .constant - - annotationNode = AnnotationNode(view: view, image: nil) - annotationNode.geometry = plane - - super.init(location: location) - - let billboardConstraint = SCNBillboardConstraint() - billboardConstraint.freeAxes = SCNBillboardAxis.Y - constraints = [billboardConstraint] - - addChildNode(annotationNode) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/ARCL/Source/Nodes/LocationAnnotationNode.swift b/ARCL/Source/Nodes/LocationAnnotationNode.swift new file mode 100644 index 00000000..0196dfc5 --- /dev/null +++ b/ARCL/Source/Nodes/LocationAnnotationNode.swift @@ -0,0 +1,103 @@ +// +// LocationNode.swift +// ARKit+CoreLocation +// +// Created by Andrew Hart on 02/07/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// +import Foundation +import SceneKit +import CoreLocation + +open class LocationAnnotationNode: LocationNode { + /// Subnodes and adjustments should be applied to this subnode + /// Required to allow scaling at the same time as having a 2D 'billboard' appearance + public let annotationNode: AnnotationNode + + /// Whether the node should be scaled relative to its distance from the camera + /// Default value (false) scales it to visually appear at the same size no matter the distance + /// Setting to true causes annotation nodes to scale like a regular node + /// Scaling relative to distance may be useful with local navigation-based uses + /// For landmarks in the distance, the default is correct + public var scaleRelativeToDistance = false + + public init(location: CLLocation?, image: UIImage) { + let plane = SCNPlane(width: image.size.width / 100, height: image.size.height / 100) + plane.firstMaterial!.diffuse.contents = image + plane.firstMaterial!.lightingModel = .constant + + annotationNode = AnnotationNode(view: nil, image: image) + annotationNode.geometry = plane + + super.init(location: location) + + let billboardConstraint = SCNBillboardConstraint() + billboardConstraint.freeAxes = SCNBillboardAxis.Y + constraints = [billboardConstraint] + + addChildNode(annotationNode) + } + + /// Use this constructor to add a UIView as an annotation + /// UIView is more configurable then a UIImage, allowing you to add background image, labels, etc. + /// + /// - Parameters: + /// - location: The location of the node in the world. + /// - view: The view to display at the specified location. + public init(location: CLLocation?, view: UIView) { + let plane = SCNPlane(width: view.frame.size.width / 100, height: view.frame.size.height / 100) + plane.firstMaterial!.diffuse.contents = view + plane.firstMaterial!.lightingModel = .constant + + annotationNode = AnnotationNode(view: view, image: nil) + annotationNode.geometry = plane + + super.init(location: location) + + let billboardConstraint = SCNBillboardConstraint() + billboardConstraint.freeAxes = SCNBillboardAxis.Y + constraints = [billboardConstraint] + + addChildNode(annotationNode) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func updatePositionAndScale(setup: Bool = false, scenePosition: SCNVector3?, + locationManager: SceneLocationManager, onCompletion: (() -> Void)) { + guard let position = scenePosition, let location = locationManager.currentLocation else { return } + + SCNTransaction.begin() + SCNTransaction.animationDuration = setup ? 0.0 : 0.1 + + let distance = self.location(locationManager.bestLocationEstimate).distance(from: location) + + let adjustedDistance = self.adjustedDistance(setup: setup, position: position, locationManager: locationManager) + + //The scale of a node with a billboard constraint applied is ignored + //The annotation subnode itself, as a subnode, has the scale applied to it + let appliedScale = self.scale + self.scale = SCNVector3(x: 1, y: 1, z: 1) + + var scale: Float + + if scaleRelativeToDistance { + scale = appliedScale.y + annotationNode.scale = appliedScale + } else { + //Scale it to be an appropriate size so that it can be seen + scale = Float(adjustedDistance) * 0.181 + if distance > 3_000 { scale *= 0.75 } + + annotationNode.scale = SCNVector3(x: scale, y: scale, z: scale) + } + + self.pivot = SCNMatrix4MakeTranslation(0, -1.1 * scale, 0) + + SCNTransaction.commit() + + onCompletion() + } +} diff --git a/ARCL/Source/Nodes/LocationNode.swift b/ARCL/Source/Nodes/LocationNode.swift new file mode 100644 index 00000000..3fa25119 --- /dev/null +++ b/ARCL/Source/Nodes/LocationNode.swift @@ -0,0 +1,145 @@ +//// +//// SceneAnnotation.swift +//// ARKit+CoreLocation +//// +//// Created by Andrew Hart on 02/07/2017. +//// Copyright © 2017 Project Dent. All rights reserved. +//// + +import Foundation +import SceneKit +import CoreLocation + +/// This node type enables the client to have access to the view or image that +/// was used to initialize the `LocationAnnotationNode`. +open class AnnotationNode: SCNNode { + public var view: UIView? + public var image: UIImage? + + public init(view: UIView?, image: UIImage?) { + super.init() + self.view = view + self.image = image + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +/// A location node can be added to a scene using a coordinate. +/// +/// Its scale and position should not be adjusted, as these are used for scene +/// layout purposes. To adjust the scale and position of items within a node, +/// you can add them to a child node and adjust them there +open class LocationNode: SCNNode { + var locationEstimateMethod: LocationEstimateMethod = .mostRelevantEstimate + + /// Location can be changed and confirmed later by SceneLocationView. + public var location: CLLocation! + + /// A general purpose tag that can be used to find nodes already added to a SceneLocationView + public var tag: String? + + /// Whether the location of the node has been confirmed. + /// This is automatically set to true when you create a node using a location. + /// Otherwise, this is false, and becomes true once the user moves 100m away from the node, + /// except when the locationEstimateMethod is set to use Core Location data only, + /// as then it becomes true immediately. + public var locationConfirmed: Bool { + return location != nil + } + + /// Whether a node's position should be adjusted on an ongoing basis + /// based on its' given location. + /// This only occurs when a node's location is within 100m of the user. + /// Adjustment doesn't apply to nodes without a confirmed location. + /// When this is set to false, the result is a smoother appearance. + /// When this is set to true, this means a node may appear to jump around + /// as the user's location estimates update, + /// but the position is generally more accurate. + /// Defaults to true. + public var continuallyAdjustNodePositionWhenWithinRange = true + + /// Whether a node's position and scale should be updated automatically on a continual basis. + /// This should only be set to false if you plan to manually update position and scale + /// at regular intervals. You can do this with `SceneLocationView`'s `updatePositionOfLocationNode`. + public var continuallyUpdatePositionAndScale = true + + public init(location: CLLocation?) { + self.location = location + super.init() + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + internal func location(_ bestLocationEstimate: SceneLocationEstimate?) -> CLLocation { + if locationConfirmed || locationEstimateMethod == .coreLocationDataOnly { + return location! + } + + if let bestLocationEstimate = bestLocationEstimate, + location == nil || bestLocationEstimate.location.horizontalAccuracy < location!.horizontalAccuracy { + return bestLocationEstimate.translatedLocation(to: position) + } else { + return location! + } + } + + internal func adjustedDistance(setup: Bool, position: SCNVector3, + locationManager: SceneLocationManager) -> CLLocationDistance { + guard let location = locationManager.currentLocation else { return 0.0 } + + //Position is set to a position coordinated via the current position + let distance = self.location(locationManager.bestLocationEstimate).distance(from: location) + + let adjustedDistance: CLLocationDistance + if locationConfirmed && (distance > 100 || continuallyAdjustNodePositionWhenWithinRange || setup) { + let locationTranslation = location.translation(toLocation: self.location(locationManager.bestLocationEstimate)) + + if distance > 100 { + //If the item is too far away, bring it closer and scale it down + let scale = 100 / Float(distance) + + adjustedDistance = distance * Double(scale) + + let adjustedTranslation = SCNVector3( x: Float(locationTranslation.longitudeTranslation) * scale, + y: Float(locationTranslation.altitudeTranslation) * scale, + z: Float(locationTranslation.latitudeTranslation) * scale) + self.position = SCNVector3( x: position.x + adjustedTranslation.x, + y: position.y + adjustedTranslation.y, + z: position.z - adjustedTranslation.z) + self.scale = SCNVector3(x: scale, y: scale, z: scale) + } else { + adjustedDistance = distance + self.position = SCNVector3( x: position.x + Float(locationTranslation.longitudeTranslation), + y: position.y + Float(locationTranslation.altitudeTranslation), + z: position.z - Float(locationTranslation.latitudeTranslation)) + self.scale = SCNVector3(x: 1, y: 1, z: 1) + } + } else { + //Calculates distance based on the distance within the scene, as the location isn't yet confirmed + adjustedDistance = Double(position.distance(to: position)) + + scale = SCNVector3(x: 1, y: 1, z: 1) + } + + return adjustedDistance + } + + func updatePositionAndScale(setup: Bool = false, scenePosition: SCNVector3?, + locationManager: SceneLocationManager, onCompletion: (() -> Void)) { + guard let position = scenePosition, locationManager.currentLocation != nil else { return } + + SCNTransaction.begin() + SCNTransaction.animationDuration = setup ? 0.0 : 0.1 + + _ = self.adjustedDistance(setup: setup, position: position, locationManager: locationManager) + + SCNTransaction.commit() + + onCompletion() + } +} diff --git a/ARCL/Source/Nodes/PolylineNode.swift b/ARCL/Source/Nodes/PolylineNode.swift new file mode 100644 index 00000000..2c476f2f --- /dev/null +++ b/ARCL/Source/Nodes/PolylineNode.swift @@ -0,0 +1,85 @@ +// +// PolylineNode.swift +// ARKit+CoreLocation +// +// Created by Ilya Seliverstov on 11/08/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// + +import Foundation +import SceneKit +import MapKit + +public class PolylineNode { + public private(set) var locationNodes = [LocationNode]() + + public let polyline: MKPolyline + public let altitude: CLLocationDistance + + private let lightNode: SCNNode = { + let node = SCNNode() + node.light = SCNLight() + node.light!.type = .ambient + if #available(iOS 10.0, *) { + node.light!.intensity = 25 + } + node.light!.attenuationStartDistance = 100 + node.light!.attenuationEndDistance = 100 + node.position = SCNVector3(x: 0, y: 10, z: 0) + node.castsShadow = false + node.light!.categoryBitMask = 3 + return node + }() + + private let lightNode3: SCNNode = { + let node = SCNNode() + node.light = SCNLight() + node.light!.type = .omni + if #available(iOS 10.0, *) { + node.light!.intensity = 100 + } + node.light!.attenuationStartDistance = 100 + node.light!.attenuationEndDistance = 100 + node.light!.castsShadow = true + node.position = SCNVector3(x: -10, y: 10, z: -10) + node.castsShadow = false + node.light!.categoryBitMask = 3 + return node + }() + + public init(polyline: MKPolyline, altitude: CLLocationDistance) { + self.polyline = polyline + self.altitude = altitude + + contructNodes() + } + + fileprivate func contructNodes() { + let points = polyline.points() + + for i in 0 ..< polyline.pointCount - 1 { + let currentLocation = CLLocation(coordinate: points[i].coordinate, altitude: altitude) + let nextLocation = CLLocation(coordinate: points[i + 1].coordinate, altitude: altitude) + + let distance = currentLocation.distance(from: nextLocation) + + let box = SCNBox(width: 1, height: 0.2, length: CGFloat(distance), chamferRadius: 0) + box.firstMaterial?.diffuse.contents = UIColor(red: 47.0/255.0, green: 125.0/255.0, blue: 255.0/255.0, alpha: 1.0) + + let bearing = -currentLocation.bearing(between: nextLocation) + + let boxNode = SCNNode(geometry: box) + boxNode.pivot = SCNMatrix4MakeTranslation(0, 0, 0.5 * Float(distance)) + boxNode.eulerAngles.y = Float(bearing).degreesToRadians + boxNode.categoryBitMask = 3 + boxNode.addChildNode(lightNode) + boxNode.addChildNode(lightNode3) + + let locationNode = LocationNode(location: currentLocation) + locationNode.addChildNode(boxNode) + + locationNodes.append(locationNode) + } + + } +} diff --git a/ARCL/Source/SceneLocationView+Extensions.swift b/ARCL/Source/SceneLocationView+Extensions.swift new file mode 100644 index 00000000..7b2011ba --- /dev/null +++ b/ARCL/Source/SceneLocationView+Extensions.swift @@ -0,0 +1,67 @@ +// +// SceneLocationView+Extensions.swift +// ARKit+CoreLocation +// +// Created by Ilya Seliverstov on 08/08/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// + +import Foundation +import ARKit +import CoreLocation +import MapKit + +@available(iOS 11.0, *) +extension SceneLocationView: ARSCNViewDelegate { + + @objc + public func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) { + if sceneNode == nil { + sceneNode = SCNNode() + scene.rootNode.addChildNode(sceneNode!) + + if showAxesNode { + let axesNode = SCNNode.axesNode(quiverLength: 0.1, quiverThickness: 0.5) + sceneNode?.addChildNode(axesNode) + } + } + + if !didFetchInitialLocation { + //Current frame and current location are required for this to be successful + if session.currentFrame != nil, + let currentLocation = sceneLocationManager.currentLocation { + didFetchInitialLocation = true + sceneLocationManager.addSceneLocationEstimate(location: currentLocation) + } + } + } + + public func sessionWasInterrupted(_ session: ARSession) { + print("session was interrupted") + } + + public func sessionInterruptionEnded(_ session: ARSession) { + print("session interruption ended") + } + + public func session(_ session: ARSession, didFailWithError error: Error) { + print("session did fail with error: \(error)") + } + + public func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) { + switch camera.trackingState { + case .limited(.insufficientFeatures): + print("camera did change tracking state: limited, insufficient features") + case .limited(.excessiveMotion): + print("camera did change tracking state: limited, excessive motion") + case .limited(.initializing): + print("camera did change tracking state: limited, initializing") + case .normal: + print("camera did change tracking state: normal") + case .notAvailable: + print("camera did change tracking state: not available") + case .limited(.relocalizing): + print("camera did change tracking state: limited, relocalizing") + } + } +} diff --git a/ARCL/Source/SceneLocationView.swift b/ARCL/Source/SceneLocationView.swift index 841d7750..a87d3f2e 100644 --- a/ARCL/Source/SceneLocationView.swift +++ b/ARCL/Source/SceneLocationView.swift @@ -11,90 +11,74 @@ import ARKit import CoreLocation import MapKit -@available(iOS 11.0, *) -public protocol SceneLocationViewDelegate: class { - func sceneLocationViewDidAddSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) - func sceneLocationViewDidRemoveSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) - - ///After a node's location is initially set based on current location, - ///it is later confirmed once the user moves far enough away from it. - ///This update uses location data collected since the node was placed to give a more accurate location. - func sceneLocationViewDidConfirmLocationOfNode(sceneLocationView: SceneLocationView, node: LocationNode) - - func sceneLocationViewDidSetupSceneNode(sceneLocationView: SceneLocationView, sceneNode: SCNNode) - - func sceneLocationViewDidUpdateLocationAndScaleOfLocationNode(sceneLocationView: SceneLocationView, locationNode: LocationNode) -} - -// Delegate for touch events on LocationNode -public protocol LNTouchDelegate: class { - func locationNodeTouched(node: AnnotationNode) -} - -///Different methods which can be used when determining locations (such as the user's location). -public enum LocationEstimateMethod { - ///Only uses core location data. - ///Not suitable for adding nodes using current position, which requires more precision. - case coreLocationDataOnly - - ///Combines knowledge about movement through the AR world with - ///the most relevant Core Location estimate (based on accuracy and time). - case mostRelevantEstimate -} - //Should conform to delegate here, add in future commit @available(iOS 11.0, *) -public class SceneLocationView: ARSCNView, ARSCNViewDelegate { - ///The limit to the scene, in terms of what data is considered reasonably accurate. - ///Measured in meters. - private static let sceneLimit = 100.0 +public class SceneLocationView: ARSCNView { + /// The limit to the scene, in terms of what data is considered reasonably accurate. + /// Measured in meters. + static let sceneLimit = 100.0 - public weak var locationDelegate: SceneLocationViewDelegate? + public weak var locationViewDelegate: SceneLocationViewDelegate? + public weak var locationEstimateDelegate: SceneLocationViewEstimateDelegate? - ///The method to use for determining locations. - ///Not advisable to change this as the scene is ongoing. - public var locationEstimateMethod: LocationEstimateMethod = .mostRelevantEstimate + public let sceneLocationManager = SceneLocationManager() - public let locationManager = LocationManager() - ///When set to true, displays an axes node at the start of the scene - public var showAxesNode = false + /// The method to use for determining locations. + /// Not advisable to change this as the scene is ongoing. + public var locationEstimateMethod: LocationEstimateMethod { + get { + return sceneLocationManager.locationEstimateMethod + } + set { + sceneLocationManager.locationEstimateMethod = newValue - public private(set) var locationNodes = [LocationNode]() + locationNodes.forEach { $0.locationEstimateMethod = newValue } + } + } - private var sceneLocationEstimates = [SceneLocationEstimate]() + /// When set to true, displays an axes node at the start of the scene + public var showAxesNode = false - public private(set) var sceneNode: SCNNode? { + public internal(set) var sceneNode: SCNNode? { didSet { - if sceneNode != nil { - for locationNode in locationNodes { - sceneNode!.addChildNode(locationNode) - } + guard sceneNode != nil else { return } - locationDelegate?.sceneLocationViewDidSetupSceneNode(sceneLocationView: self, sceneNode: sceneNode!) - } + locationNodes.forEach { sceneNode?.addChildNode($0) } + + locationViewDelegate?.didSetupSceneNode(sceneLocationView: self, sceneNode: sceneNode!) } } - private var updateEstimatesTimer: Timer? - - private var didFetchInitialLocation = false + /// Only to be overrided if you plan on manually setting True North. + /// When true, sets up the scene to face what the device considers to be True North. + /// This can be inaccurate, hence the option to override it. + /// The functions for altering True North can be used irrespective of this value, + /// but if the scene is oriented to true north, it will update without warning, + /// thus affecting your alterations. + /// The initial value of this property is respected. + public var orientToTrueNorth = true - ///Whether debugging feature points should be displayed. - ///Defaults to false + /// Whether debugging feature points should be displayed. + /// Defaults to false public var showFeaturePoints = false - ///Only to be overrided if you plan on manually setting True North. - ///When true, sets up the scene to face what the device considers to be True North. - ///This can be inaccurate, hence the option to override it. - ///The functions for altering True North can be used irrespective of this value, - ///but if the scene is oriented to true north, it will update without warning, - ///thus affecting your alterations. - ///The initial value of this property is respected. - public var orientToTrueNorth = true + // MARK: Scene location estimates + public var currentScenePosition: SCNVector3? { + guard let pointOfView = pointOfView else { return nil } + return scene.rootNode.convertPosition(pointOfView.position, to: sceneNode) + } + + public var currentEulerAngles: SCNVector3? { return pointOfView?.eulerAngles } + + public internal(set) var locationNodes = [LocationNode]() + public internal(set) var polylineNodes = [PolylineNode]() - // MARK: - Setup + // MARK: Internal desclarations + internal var didFetchInitialLocation = false + + // MARK: Setup public convenience init() { - self.init(frame: CGRect.zero, options: nil) + self.init(frame: .zero, options: nil) } public override init(frame: CGRect, options: [String: Any]? = nil) { @@ -108,202 +92,128 @@ public class SceneLocationView: ARSCNView, ARSCNViewDelegate { } private func finishInitialization() { - locationManager.delegate = self + sceneLocationManager.sceneLocationDelegate = self delegate = self // Show statistics such as fps and timing information showsStatistics = false - if showFeaturePoints { - debugOptions = [ARSCNDebugOptions.showFeaturePoints] - } - - let touchGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(sceneLocationViewTouched(sender:))) - self.addGestureRecognizer(touchGestureRecognizer) + debugOptions = showFeaturePoints ? [ARSCNDebugOptions.showFeaturePoints] : debugOptions } override public func layoutSubviews() { super.layoutSubviews() } - public func run() { - // Create a session configuration - let configuration = ARWorldTrackingConfiguration() - configuration.planeDetection = .horizontal - - if orientToTrueNorth { - configuration.worldAlignment = .gravityAndHeading - } else { - configuration.worldAlignment = .gravity - } - - // Run the view's session - session.run(configuration) - - updateEstimatesTimer?.invalidate() - updateEstimatesTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(SceneLocationView.updateLocationData), userInfo: nil, repeats: true) - } - - public func pause() { - session.pause() - updateEstimatesTimer?.invalidate() - updateEstimatesTimer = nil - } - - @objc private func updateLocationData() { - removeOldLocationEstimates() - confirmLocationOfDistantLocationNodes() - updatePositionAndScaleOfLocationNodes() - } - - // MARK: - True North - ///iOS can be inaccurate when setting true north - ///The scene is oriented to true north, and will update its heading when it gets a more accurate reading - ///You can disable this through setting the - ///These functions provide manual overriding of the scene heading, - /// if you have a more precise idea of where True North is - ///The goal is for the True North orientation problems to be resolved - ///At which point these functions would no longer be useful - - ///Moves the scene heading clockwise by 1 degree - ///Intended for correctional purposes - public func moveSceneHeadingClockwise() { - sceneNode?.eulerAngles.y -= Float(1).degreesToRadians - } - - ///Moves the scene heading anti-clockwise by 1 degree - ///Intended for correctional purposes - public func moveSceneHeadingAntiClockwise() { - sceneNode?.eulerAngles.y += Float(1).degreesToRadians - } - - ///Resets the scene heading to 0 + /// Resets the scene heading to 0 func resetSceneHeading() { sceneNode?.eulerAngles.y = 0 } - // MARK: - Scene location estimates - - public func currentScenePosition() -> SCNVector3? { - guard let pointOfView = pointOfView else { - return nil - } - - return scene.rootNode.convertPosition(pointOfView.position, to: sceneNode) - } - - public func currentEulerAngles() -> SCNVector3? { - return pointOfView?.eulerAngles + func confirmLocationOfLocationNode(_ locationNode: LocationNode) { + locationNode.location = locationOfLocationNode(locationNode) + locationViewDelegate?.didConfirmLocationOfNode(sceneLocationView: self, node: locationNode) } - ///Adds a scene location estimate based on current time, camera position and location from location manager - fileprivate func addSceneLocationEstimate(location: CLLocation) { - if let position = currentScenePosition() { - let sceneLocationEstimate = SceneLocationEstimate(location: location, position: position) - self.sceneLocationEstimates.append(sceneLocationEstimate) - if self.sceneLocationEstimates.count > 30 { - self.sceneLocationEstimates.remove(at: 0) - } - - locationDelegate?.sceneLocationViewDidAddSceneLocationEstimate(sceneLocationView: self, position: position, location: location) + /// Gives the best estimate of the location of a node + func locationOfLocationNode(_ locationNode: LocationNode) -> CLLocation { + if locationNode.locationConfirmed || locationEstimateMethod == .coreLocationDataOnly { + return locationNode.location! } - } - private func removeOldLocationEstimates() { - if let currentScenePosition = currentScenePosition() { - self.removeOldLocationEstimates(currentScenePosition: currentScenePosition) + if let bestLocationEstimate = sceneLocationManager.bestLocationEstimate, + locationNode.location == nil + || bestLocationEstimate.location.horizontalAccuracy < locationNode.location!.horizontalAccuracy { + return bestLocationEstimate.translatedLocation(to: locationNode.position) + } else { + return locationNode.location! } } +} - private func removeOldLocationEstimates(currentScenePosition: SCNVector3) { - let currentPoint = CGPoint.pointWithVector(vector: currentScenePosition) - - sceneLocationEstimates = sceneLocationEstimates.filter({ - let point = CGPoint.pointWithVector(vector: $0.position) - - let radiusContainsPoint = currentPoint.radiusContainsPoint(radius: CGFloat(SceneLocationView.sceneLimit), point: point) +@available(iOS 11.0, *) +public extension SceneLocationView { - if !radiusContainsPoint { - locationDelegate?.sceneLocationViewDidRemoveSceneLocationEstimate(sceneLocationView: self, position: $0.position, location: $0.location) - } + func run() { + // Create a session configuration + let configuration = ARWorldTrackingConfiguration() + configuration.planeDetection = .horizontal + configuration.worldAlignment = orientToTrueNorth ? .gravityAndHeading : .gravity - return radiusContainsPoint - }) + // Run the view's session + session.run(configuration) + sceneLocationManager.run() } - ///The best estimation of location that has been taken - ///This takes into account horizontal accuracy, and the time at which the estimation was taken - ///favouring the most accurate, and then the most recent result. - ///This doesn't indicate where the user currently is. - public func bestLocationEstimate() -> SceneLocationEstimate? { - let sortedLocationEstimates = sceneLocationEstimates.sorted(by: { - if $0.location.horizontalAccuracy == $1.location.horizontalAccuracy { - return $0.location.timestamp > $1.location.timestamp - } - - return $0.location.horizontalAccuracy < $1.location.horizontalAccuracy - }) - - return sortedLocationEstimates.first + func pause() { + session.pause() + sceneLocationManager.pause() } - public func currentLocation() -> CLLocation? { - if locationEstimateMethod == .coreLocationDataOnly { - return locationManager.currentLocation - } - - guard let bestEstimate = self.bestLocationEstimate(), - let position = currentScenePosition() else { - return nil - } + // MARK: True North - return bestEstimate.translatedLocation(to: position) + /// iOS can be inaccurate when setting true north + /// The scene is oriented to true north, and will update its heading when it gets a more accurate reading + /// You can disable this through setting the + /// These functions provide manual overriding of the scene heading, + /// if you have a more precise idea of where True North is + /// The goal is for the True North orientation problems to be resolved + /// At which point these functions would no longer be useful + /// Moves the scene heading clockwise by 1 degree + /// Intended for correctional purposes + func moveSceneHeadingClockwise() { + sceneNode?.eulerAngles.y -= Float(1).degreesToRadians } - // MARK: - LocationNodes - ///upon being added, a node's location, locationConfirmed and position may be modified and should not be changed externally. + /// Moves the scene heading anti-clockwise by 1 degree + /// Intended for correctional purposes + func moveSceneHeadingAntiClockwise() { + sceneNode?.eulerAngles.y += Float(1).degreesToRadians + } - //A delegate for calling the touch event on a LocationAnnotationNode - public weak var locationNodeTouchDelegate: LNTouchDelegate? + // MARK: LocationNodes - public func addLocationNodeForCurrentPosition(locationNode: LocationNode) { - guard let currentPosition = currentScenePosition(), - let currentLocation = currentLocation(), - let sceneNode = self.sceneNode else { - return - } + /// upon being added, a node's location, locationConfirmed and position may be modified and should not be changed externally. + func addLocationNodeForCurrentPosition(locationNode: LocationNode) { + guard let currentPosition = currentScenePosition, + let currentLocation = sceneLocationManager.currentLocation, + let sceneNode = sceneNode else { return } locationNode.location = currentLocation - - ///Location is not changed after being added when using core location data only for location estimates - if locationEstimateMethod == .coreLocationDataOnly { - locationNode.locationConfirmed = true - } else { - locationNode.locationConfirmed = false - } - locationNode.position = currentPosition locationNodes.append(locationNode) sceneNode.addChildNode(locationNode) } - ///location not being nil, and locationConfirmed being true are required - ///Upon being added, a node's position will be modified and should not be changed externally. - ///location will not be modified, but taken as accurate. - public func addLocationNodeWithConfirmedLocation(locationNode: LocationNode) { - if locationNode.location == nil || locationNode.locationConfirmed == false { - return - } + func addLocationNodesForCurrentPosition(locationNodes: [LocationNode]) { + locationNodes.forEach { addLocationNodeForCurrentPosition(locationNode: $0) } + } - updatePositionAndScaleOfLocationNode(locationNode: locationNode, initialSetup: true, animated: false) + /// location not being nil, and locationConfirmed being true are required + /// Upon being added, a node's position will be modified and should not be changed externally. + /// location will not be modified, but taken as accurate. + func addLocationNodeWithConfirmedLocation(locationNode: LocationNode) { + if locationNode.location == nil || locationNode.locationConfirmed == false { return } + + locationNode.updatePositionAndScale(setup: true, + scenePosition: currentScenePosition, + locationManager: sceneLocationManager) { + self.locationViewDelegate? + .didUpdateLocationAndScaleOfLocationNode(sceneLocationView: self, + locationNode: locationNode) + } locationNodes.append(locationNode) sceneNode?.addChildNode(locationNode) } - public func removeAllNodes() { + func addLocationNodesWithConfirmedLocation(locationNodes: [LocationNode]) { + locationNodes.forEach { addLocationNodeWithConfirmedLocation(locationNode: $0) } + } + + func removeAllNodes() { locationNodes.removeAll() guard let childNodes = sceneNode?.childNodes else { return } for node in childNodes { @@ -315,7 +225,7 @@ public class SceneLocationView: ARSCNView, ARSCNViewDelegate { /// /// - Parameter tag: tag text /// - Returns: true if a LocationNode with the tag exists; false otherwise - public func sceneContainsNodeWithTag(_ tag: String) -> Bool { + func sceneContainsNodeWithTag(_ tag: String) -> Bool { return findNodes(tagged: tag).count > 0 } @@ -323,7 +233,7 @@ public class SceneLocationView: ARSCNView, ARSCNViewDelegate { /// /// - Parameter tag: The tag text for which to search nodes. /// - Returns: A list of all matching tags - public func findNodes(tagged tag: String) -> [LocationNode] { + func findNodes(tagged tag: String) -> [LocationNode] { guard tag.count > 0 else { return [] } @@ -331,7 +241,7 @@ public class SceneLocationView: ARSCNView, ARSCNViewDelegate { return locationNodes.filter { $0.tag == tag } } - public func removeLocationNode(locationNode: LocationNode) { + func removeLocationNode(locationNode: LocationNode) { if let index = locationNodes.index(of: locationNode) { locationNodes.remove(at: index) } @@ -339,221 +249,74 @@ public class SceneLocationView: ARSCNView, ARSCNViewDelegate { locationNode.removeFromParentNode() } - private func confirmLocationOfDistantLocationNodes() { - guard let currentPosition = currentScenePosition() else { - return - } - - for locationNode in locationNodes where !locationNode.locationConfirmed { - let currentPoint = CGPoint.pointWithVector(vector: currentPosition) - let locationNodePoint = CGPoint.pointWithVector(vector: locationNode.position) - - if !currentPoint.radiusContainsPoint(radius: CGFloat(SceneLocationView.sceneLimit), point: locationNodePoint) { - confirmLocationOfLocationNode(locationNode) - } - } + func removeLocationNodes(locationNodes: [LocationNode]) { + locationNodes.forEach { removeLocationNode(locationNode: $0) } } +} - ///Gives the best estimate of the location of a node - func locationOfLocationNode(_ locationNode: LocationNode) -> CLLocation { - if locationNode.locationConfirmed || locationEstimateMethod == .coreLocationDataOnly { - return locationNode.location! - } - - if let bestLocationEstimate = bestLocationEstimate(), - locationNode.location == nil || - bestLocationEstimate.location.horizontalAccuracy < locationNode.location!.horizontalAccuracy { - let translatedLocation = bestLocationEstimate.translatedLocation(to: locationNode.position) - - return translatedLocation - } else { - return locationNode.location! - } - } - - private func confirmLocationOfLocationNode(_ locationNode: LocationNode) { - locationNode.location = locationOfLocationNode(locationNode) - - locationNode.locationConfirmed = true - - locationDelegate?.sceneLocationViewDidConfirmLocationOfNode(sceneLocationView: self, node: locationNode) - } - - func updatePositionAndScaleOfLocationNodes() { - for locationNode in locationNodes where locationNode.continuallyUpdatePositionAndScale { - updatePositionAndScaleOfLocationNode(locationNode: locationNode, animated: true) - } - } - - public func updatePositionAndScaleOfLocationNode(locationNode: LocationNode, initialSetup: Bool = false, animated: Bool = false, duration: TimeInterval = 0.1) { - guard let currentPosition = currentScenePosition(), - let currentLocation = currentLocation() else { - return - } - - SCNTransaction.begin() - - SCNTransaction.animationDuration = animated ? duration : 0 - - let locationNodeLocation = locationOfLocationNode(locationNode) - - // Position is set to a position coordinated via the current position - let locationTranslation = currentLocation.translation(toLocation: locationNodeLocation) - let adjustedDistance: CLLocationDistance - let distance = locationNodeLocation.distance(from: currentLocation) - - if locationNode.locationConfirmed && - (distance > 100 || locationNode.continuallyAdjustNodePositionWhenWithinRange || initialSetup) { - if distance > 100 { - //If the item is too far away, bring it closer and scale it down - let scale = 100 / Float(distance) - - adjustedDistance = distance * Double(scale) - - let adjustedTranslation = SCNVector3( - x: Float(locationTranslation.longitudeTranslation) * scale, - y: Float(locationTranslation.altitudeTranslation) * scale, - z: Float(locationTranslation.latitudeTranslation) * scale) - - let position = SCNVector3( - x: currentPosition.x + adjustedTranslation.x, - y: currentPosition.y + adjustedTranslation.y, - z: currentPosition.z - adjustedTranslation.z) - - locationNode.position = position - - locationNode.scale = SCNVector3(x: scale, y: scale, z: scale) - } else { - adjustedDistance = distance - let position = SCNVector3( - x: currentPosition.x + Float(locationTranslation.longitudeTranslation), - y: currentPosition.y + Float(locationTranslation.altitudeTranslation), - z: currentPosition.z - Float(locationTranslation.latitudeTranslation)) - - locationNode.position = position - locationNode.scale = SCNVector3(x: 1, y: 1, z: 1) - } - } else { - //Calculates distance based on the distance within the scene, as the location isn't yet confirmed - adjustedDistance = Double(currentPosition.distance(to: locationNode.position)) +@available(iOS 11.0, *) +public extension SceneLocationView { - locationNode.scale = SCNVector3(x: 1, y: 1, z: 1) + func addRoutes(routes: [MKRoute]) { + guard let altitude = sceneLocationManager.currentLocation?.altitude else { + return assertionFailure("we don't have an elevation") } - - if let annotationNode = locationNode as? LocationAnnotationNode { - //The scale of a node with a billboard constraint applied is ignored - //The annotation subnode itself, as a subnode, has the scale applied to it - let appliedScale = locationNode.scale - locationNode.scale = SCNVector3(x: 1, y: 1, z: 1) - - var scale: Float - - if annotationNode.scaleRelativeToDistance { - scale = appliedScale.y - annotationNode.annotationNode.scale = appliedScale - } else { - //Scale it to be an appropriate size so that it can be seen - scale = Float(adjustedDistance) * 0.181 - - if distance > 3000 { - scale = scale * 0.75 - } - - annotationNode.annotationNode.scale = SCNVector3(x: scale, y: scale, z: scale) + let polyNodes = routes.map { PolylineNode(polyline: $0.polyline, altitude: altitude - 2.0) } + + polylineNodes.append(contentsOf: polyNodes) + polyNodes.forEach { + $0.locationNodes.forEach { + $0.updatePositionAndScale(setup: true, + scenePosition: currentScenePosition, + locationManager: sceneLocationManager, + onCompletion: {}) + sceneNode?.addChildNode($0) } - - annotationNode.pivot = SCNMatrix4MakeTranslation(0, -1.1 * scale, 0) } - - SCNTransaction.commit() - - locationDelegate?.sceneLocationViewDidUpdateLocationAndScaleOfLocationNode(sceneLocationView: self, locationNode: locationNode) } - @objc func sceneLocationViewTouched(sender: UITapGestureRecognizer) { - guard let touchedView = sender.view as? SCNView else { - return - } - - let coordinates = sender.location(in: touchedView) - let hitTest = touchedView.hitTest(coordinates) - - if !hitTest.isEmpty, - let firstHitTest = hitTest.first, - let touchedNode = firstHitTest.node as? AnnotationNode { - self.locationNodeTouchDelegate?.locationNodeTouched(node: touchedNode) + func removeRoutes(routes: [MKRoute]) { + routes.forEach { route in + if let index = polylineNodes.index(where: { $0.polyline == route.polyline }) { + polylineNodes.remove(at: index) + } } } +} - // MARK: - ARSCNViewDelegate +@available(iOS 11.0, *) +extension SceneLocationView: SceneLocationManagerDelegate { + var scenePosition: SCNVector3? { return currentScenePosition } - public func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) { - if sceneNode == nil { - sceneNode = SCNNode() - scene.rootNode.addChildNode(sceneNode!) + func confirmLocationOfDistantLocationNodes() { + guard let currentPosition = currentScenePosition else { return } - if showAxesNode { - let axesNode = SCNNode.axesNode(quiverLength: 0.1, quiverThickness: 0.5) - sceneNode?.addChildNode(axesNode) - } - } - - if !didFetchInitialLocation { - //Current frame and current location are required for this to be successful - if session.currentFrame != nil, - let currentLocation = self.locationManager.currentLocation { - didFetchInitialLocation = true + locationNodes.filter { !$0.locationConfirmed }.forEach { + let currentPoint = CGPoint.pointWithVector(vector: currentPosition) + let locationNodePoint = CGPoint.pointWithVector(vector: $0.position) - self.addSceneLocationEstimate(location: currentLocation) + if !currentPoint.radiusContainsPoint(radius: CGFloat(SceneLocationView.sceneLimit), point: locationNodePoint) { + confirmLocationOfLocationNode($0) } } } - public func sessionWasInterrupted(_ session: ARSession) { - print("session was interrupted") - } - - public func sessionInterruptionEnded(_ session: ARSession) { - print("session interruption ended") - } - - public func session(_ session: ARSession, didFailWithError error: Error) { - print("session did fail with error: \(error)") - } - - public func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) { - switch camera.trackingState { - case .limited(.insufficientFeatures): - print("camera did change tracking state: limited, insufficient features") - case .limited(.excessiveMotion): - print("camera did change tracking state: limited, excessive motion") - case .limited(.initializing): - print("camera did change tracking state: limited, initializing") - case .normal: - print("camera did change tracking state: normal") - case .notAvailable: - print("camera did change tracking state: not available") - case .limited(.relocalizing): - print("camera did change tracking state: limited, relocalizing") + func updatePositionAndScaleOfLocationNodes() { + locationNodes.filter { $0.continuallyUpdatePositionAndScale }.forEach { node in + node.updatePositionAndScale(scenePosition: currentScenePosition, + locationManager: sceneLocationManager) { + self.locationViewDelegate? + .didUpdateLocationAndScaleOfLocationNode(sceneLocationView: self, + locationNode: node) + } } } -} -// MARK: - LocationManager -@available(iOS 11.0, *) -extension SceneLocationView: LocationManagerDelegate { - func locationManagerDidUpdateLocation(_ locationManager: LocationManager, location: CLLocation) { - addSceneLocationEstimate(location: location) + func didAddSceneLocationEstimate(position: SCNVector3, location: CLLocation) { + locationEstimateDelegate?.didAddSceneLocationEstimate(sceneLocationView: self, position: position, location: location) } - func locationManagerDidUpdateHeading(_ locationManager: LocationManager, heading: CLLocationDirection, accuracy: CLLocationAccuracy) { - // negative value means the heading will equal the `magneticHeading`, and we're interested in the `trueHeading` - if accuracy < 0 { - return - } - // heading of 0º means its pointing to the geographic North - if heading == 0 { - resetSceneHeading() - } + func didRemoveSceneLocationEstimate(position: SCNVector3, location: CLLocation) { + locationEstimateDelegate?.didRemoveSceneLocationEstimate(sceneLocationView: self, position: position, location: location) } } diff --git a/ARCL/Source/SceneLocationViewEstimateDelegate.swift b/ARCL/Source/SceneLocationViewEstimateDelegate.swift new file mode 100644 index 00000000..094a0f9b --- /dev/null +++ b/ARCL/Source/SceneLocationViewEstimateDelegate.swift @@ -0,0 +1,61 @@ +// +// SceneLocationViewDelegate.swift +// ARKit+CoreLocation +// +// Created by Ilya Seliverstov on 09/08/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// + +import Foundation +import ARKit +import CoreLocation +import MapKit + +@available(iOS 11.0, *) +public protocol SceneLocationViewEstimateDelegate: class { + func didAddSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) + func didRemoveSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) +} + +@available(iOS 11.0, *) +public extension SceneLocationViewEstimateDelegate { + func didAddSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) { + // + } + func didRemoveSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) { + // + } +} + +@available(iOS 11.0, *) +public protocol SceneLocationViewDelegate: class { + ///After a node's location is initially set based on current location, + ///it is later confirmed once the user moves far enough away from it. + ///This update uses location data collected since the node was placed to give a more accurate location. + func didConfirmLocationOfNode(sceneLocationView: SceneLocationView, node: LocationNode) + + func didSetupSceneNode(sceneLocationView: SceneLocationView, sceneNode: SCNNode) + + func didUpdateLocationAndScaleOfLocationNode(sceneLocationView: SceneLocationView, locationNode: LocationNode) +} + +@available(iOS 11.0, *) +public extension SceneLocationViewDelegate { + func didAddSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) { + // + } + func didRemoveSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) { + // + } + + func didConfirmLocationOfNode(sceneLocationView: SceneLocationView, node: LocationNode) { + // + } + func didSetupSceneNode(sceneLocationView: SceneLocationView, sceneNode: SCNNode) { + // + } + + func didUpdateLocationAndScaleOfLocationNode(sceneLocationView: SceneLocationView, locationNode: LocationNode) { + // + } +} diff --git a/ARKit+CoreLocation.xcodeproj/project.pbxproj b/ARKit+CoreLocation.xcodeproj/project.pbxproj index a7c2fc69..0cffe558 100644 --- a/ARKit+CoreLocation.xcodeproj/project.pbxproj +++ b/ARKit+CoreLocation.xcodeproj/project.pbxproj @@ -7,26 +7,20 @@ objects = { /* Begin PBXBuildFile section */ + 12318E3B1F3B444400ACAD16 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 12318E391F3B444400ACAD16 /* Main.storyboard */; }; + 12318E3D1F3B457200ACAD16 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12318E3C1F3B457200ACAD16 /* Utils.swift */; }; + 34D7563D99636C75B885A566 /* Pods_ARKit_CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C10523EF85AA6B7CDF962AD /* Pods_ARKit_CoreLocation.framework */; }; + 3643DAEB221E30C6002BEAFC /* UIButton+Designable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3643DAEA221E30C6002BEAFC /* UIButton+Designable.swift */; }; + 3643DAED221E3390002BEAFC /* OpenARCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3643DAEC221E3390002BEAFC /* OpenARCell.swift */; }; + 3643DAEF221E3840002BEAFC /* LocationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3643DAEE221E3840002BEAFC /* LocationCell.swift */; }; + 369336F3221B4B730097D8FA /* NotSupportedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8C205D01F5B197200675E6E /* NotSupportedViewController.swift */; }; + 36B3F34B221D077700745096 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36B3F34A221D077700745096 /* SettingsViewController.swift */; }; 49A3FBDC1F09988100AA59C8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FBDB1F09988100AA59C8 /* AppDelegate.swift */; }; - 49A3FBE01F09988100AA59C8 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FBDF1F09988100AA59C8 /* ViewController.swift */; }; + 49A3FBE01F09988100AA59C8 /* ARCLViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FBDF1F09988100AA59C8 /* ARCLViewController.swift */; }; 49A3FBE51F09988100AA59C8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 49A3FBE41F09988100AA59C8 /* Assets.xcassets */; }; 49A3FBE81F09988100AA59C8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 49A3FBE61F09988100AA59C8 /* LaunchScreen.storyboard */; }; 932EF22B20BE7E6E0052210C /* ARCL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932EF22220BE7E6D0052210C /* ARCL.framework */; }; 932EF23220BE7E6E0052210C /* ARCLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 932EF23120BE7E6E0052210C /* ARCLTests.swift */; }; - 932EF23420BE7E6E0052210C /* ARCL.h in Headers */ = {isa = PBXBuildFile; fileRef = 932EF22420BE7E6D0052210C /* ARCL.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 932EF23720BE7E6E0052210C /* ARCL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932EF22220BE7E6D0052210C /* ARCL.framework */; }; - 932EF23820BE7E6E0052210C /* ARCL.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 932EF22220BE7E6D0052210C /* ARCL.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 932EF26120BE83A80052210C /* SceneLocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FBF61F099C8100AA59C8 /* SceneLocationView.swift */; }; - 932EF26220BE83A80052210C /* LocationNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FBFE1F09B1D200AA59C8 /* LocationNode.swift */; }; - 932EF26320BE83A80052210C /* SceneLocationEstimate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FC001F09B9CF00AA59C8 /* SceneLocationEstimate.swift */; }; - 932EF26420BE83A80052210C /* SceneLocationEstimate+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4901EF041F1B7D560067870D /* SceneLocationEstimate+Extensions.swift */; }; - 932EF26520BE83A80052210C /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FBF41F099A5F00AA59C8 /* LocationManager.swift */; }; - 932EF26620BE83A80052210C /* CLLocation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FBFC1F09B00400AA59C8 /* CLLocation+Extensions.swift */; }; - 932EF26720BE83A80052210C /* SCNVector3+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49099E381F24BAE5007B76FD /* SCNVector3+Extensions.swift */; }; - 932EF26820BE83A80052210C /* FloatingPoint+Radians.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FC021F09BADB00AA59C8 /* FloatingPoint+Radians.swift */; }; - 932EF26920BE83A80052210C /* CGPoint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49A3FC041F0A423800AA59C8 /* CGPoint+Extensions.swift */; }; - 932EF26A20BE83A80052210C /* SCNNode+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49D206F21F124BDD00D7D622 /* SCNNode+Extensions.swift */; }; - D8C205D11F5B197200675E6E /* NotSupportedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8C205D01F5B197200675E6E /* NotSupportedViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -44,53 +38,30 @@ remoteGlobalIDString = 49A3FBD71F09988100AA59C8; remoteInfo = "ARKit+CoreLocation"; }; - 932EF23520BE7E6E0052210C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 49A3FBD01F09988100AA59C8 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 932EF22120BE7E6D0052210C; - remoteInfo = ARCL; - }; /* End PBXContainerItemProxy section */ -/* Begin PBXCopyFilesBuildPhase section */ - 932EF23E20BE7E6E0052210C /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 932EF23820BE7E6E0052210C /* ARCL.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - /* Begin PBXFileReference section */ - 4901EF041F1B7D560067870D /* SceneLocationEstimate+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SceneLocationEstimate+Extensions.swift"; sourceTree = ""; }; - 49099E381F24BAE5007B76FD /* SCNVector3+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SCNVector3+Extensions.swift"; sourceTree = ""; }; + 12318E3A1F3B444400ACAD16 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 12318E3C1F3B457200ACAD16 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; + 3643DAEA221E30C6002BEAFC /* UIButton+Designable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Designable.swift"; sourceTree = ""; }; + 3643DAEC221E3390002BEAFC /* OpenARCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenARCell.swift; sourceTree = ""; }; + 3643DAEE221E3840002BEAFC /* LocationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationCell.swift; sourceTree = ""; }; + 36B3F34A221D077700745096 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; 49A3FBD81F09988100AA59C8 /* ARKit+CoreLocation.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ARKit+CoreLocation.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 49A3FBDB1F09988100AA59C8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 49A3FBDF1F09988100AA59C8 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 49A3FBDF1F09988100AA59C8 /* ARCLViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ARCLViewController.swift; sourceTree = ""; }; 49A3FBE41F09988100AA59C8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 49A3FBE71F09988100AA59C8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 49A3FBE91F09988100AA59C8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 49A3FBF41F099A5F00AA59C8 /* LocationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = ""; }; - 49A3FBF61F099C8100AA59C8 /* SceneLocationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneLocationView.swift; sourceTree = ""; }; - 49A3FBFC1F09B00400AA59C8 /* CLLocation+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CLLocation+Extensions.swift"; sourceTree = ""; }; - 49A3FBFE1F09B1D200AA59C8 /* LocationNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationNode.swift; sourceTree = ""; }; - 49A3FC001F09B9CF00AA59C8 /* SceneLocationEstimate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneLocationEstimate.swift; sourceTree = ""; }; - 49A3FC021F09BADB00AA59C8 /* FloatingPoint+Radians.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FloatingPoint+Radians.swift"; sourceTree = ""; }; - 49A3FC041F0A423800AA59C8 /* CGPoint+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGPoint+Extensions.swift"; sourceTree = ""; }; - 49D206F21F124BDD00D7D622 /* SCNNode+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SCNNode+Extensions.swift"; sourceTree = ""; }; 6C10523EF85AA6B7CDF962AD /* Pods_ARKit_CoreLocation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ARKit_CoreLocation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C31ACA439BC114F28F96BDD /* Pods-ARKit+CoreLocation.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ARKit+CoreLocation.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.debug.xcconfig"; sourceTree = ""; }; 932EF22220BE7E6D0052210C /* ARCL.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ARCL.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 932EF22420BE7E6D0052210C /* ARCL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ARCL.h; sourceTree = ""; }; - 932EF22520BE7E6D0052210C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 932EF22A20BE7E6E0052210C /* ARCLTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ARCLTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 932EF23120BE7E6E0052210C /* ARCLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ARCLTests.swift; sourceTree = ""; }; 932EF23320BE7E6E0052210C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 994C280456570735FF51D68E /* Pods-ARKit+CoreLocation.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ARKit+CoreLocation.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.debug.xcconfig"; sourceTree = ""; }; + 9F567B68B145F555A5EF8F47 /* Pods-ARKit+CoreLocation.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ARKit+CoreLocation.release.xcconfig"; path = "Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.release.xcconfig"; sourceTree = ""; }; + CED01C5C93D16CD7C03711E5 /* Pods-ARKit+CoreLocation.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ARKit+CoreLocation.release.xcconfig"; path = "Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.release.xcconfig"; sourceTree = ""; }; D8C205D01F5B197200675E6E /* NotSupportedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotSupportedViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -99,7 +70,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 932EF23720BE7E6E0052210C /* ARCL.framework in Frameworks */, + 34D7563D99636C75B885A566 /* Pods_ARKit_CoreLocation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -121,14 +92,33 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 324DB17D55194FA55BEFF5AB /* Pods */ = { + isa = PBXGroup; + children = ( + 994C280456570735FF51D68E /* Pods-ARKit+CoreLocation.debug.xcconfig */, + 9F567B68B145F555A5EF8F47 /* Pods-ARKit+CoreLocation.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 363E3C45221B335500938BFB /* Recovered References */ = { + isa = PBXGroup; + children = ( + 8C31ACA439BC114F28F96BDD /* Pods-ARKit+CoreLocation.debug.xcconfig */, + CED01C5C93D16CD7C03711E5 /* Pods-ARKit+CoreLocation.release.xcconfig */, + ); + name = "Recovered References"; + sourceTree = ""; + }; 49A3FBCF1F09988100AA59C8 = { isa = PBXGroup; children = ( - 932EF22320BE7E6D0052210C /* ARCL */, 49A3FBDA1F09988100AA59C8 /* ARKit+CoreLocation */, 932EF23020BE7E6E0052210C /* ARCLTests */, 49A3FBD91F09988100AA59C8 /* Products */, F2E2E005FD78BDD52B0F8A94 /* Frameworks */, + 363E3C45221B335500938BFB /* Recovered References */, + 324DB17D55194FA55BEFF5AB /* Pods */, ); sourceTree = ""; }; @@ -146,42 +136,21 @@ isa = PBXGroup; children = ( 49A3FBDB1F09988100AA59C8 /* AppDelegate.swift */, - 49A3FBDF1F09988100AA59C8 /* ViewController.swift */, + 12318E3C1F3B457200ACAD16 /* Utils.swift */, + 49A3FBDF1F09988100AA59C8 /* ARCLViewController.swift */, D8C205D01F5B197200675E6E /* NotSupportedViewController.swift */, 49A3FBE41F09988100AA59C8 /* Assets.xcassets */, 49A3FBE61F09988100AA59C8 /* LaunchScreen.storyboard */, + 12318E391F3B444400ACAD16 /* Main.storyboard */, 49A3FBE91F09988100AA59C8 /* Info.plist */, + 36B3F34A221D077700745096 /* SettingsViewController.swift */, + 3643DAEA221E30C6002BEAFC /* UIButton+Designable.swift */, + 3643DAEC221E3390002BEAFC /* OpenARCell.swift */, + 3643DAEE221E3840002BEAFC /* LocationCell.swift */, ); path = "ARKit+CoreLocation"; sourceTree = ""; }; - 49A3FBF31F099A4A00AA59C8 /* Source */ = { - isa = PBXGroup; - children = ( - 49A3FBF61F099C8100AA59C8 /* SceneLocationView.swift */, - 49A3FBFE1F09B1D200AA59C8 /* LocationNode.swift */, - 49A3FC001F09B9CF00AA59C8 /* SceneLocationEstimate.swift */, - 4901EF041F1B7D560067870D /* SceneLocationEstimate+Extensions.swift */, - 49A3FBF41F099A5F00AA59C8 /* LocationManager.swift */, - 49A3FBFC1F09B00400AA59C8 /* CLLocation+Extensions.swift */, - 49099E381F24BAE5007B76FD /* SCNVector3+Extensions.swift */, - 49A3FC021F09BADB00AA59C8 /* FloatingPoint+Radians.swift */, - 49A3FC041F0A423800AA59C8 /* CGPoint+Extensions.swift */, - 49D206F21F124BDD00D7D622 /* SCNNode+Extensions.swift */, - ); - path = Source; - sourceTree = ""; - }; - 932EF22320BE7E6D0052210C /* ARCL */ = { - isa = PBXGroup; - children = ( - 49A3FBF31F099A4A00AA59C8 /* Source */, - 932EF22420BE7E6D0052210C /* ARCL.h */, - 932EF22520BE7E6D0052210C /* Info.plist */, - ); - path = ARCL; - sourceTree = ""; - }; 932EF23020BE7E6E0052210C /* ARCLTests */ = { isa = PBXGroup; children = ( @@ -206,7 +175,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 932EF23420BE7E6E0052210C /* ARCL.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -217,16 +185,18 @@ isa = PBXNativeTarget; buildConfigurationList = 49A3FBEC1F09988100AA59C8 /* Build configuration list for PBXNativeTarget "ARKit+CoreLocation" */; buildPhases = ( + F3C651027697D46CB173FF94 /* [CP] Check Pods Manifest.lock */, 49A3FBD41F09988100AA59C8 /* Sources */, 49A3FBD51F09988100AA59C8 /* Frameworks */, 49A3FBD61F09988100AA59C8 /* Resources */, - 935FB3C020BD304200F6A081 /* Swiftlint */, - 932EF23E20BE7E6E0052210C /* Embed Frameworks */, + B912B23DE2753A7230AC73FF /* Swiftlint */, + 3B65648ABF0CBE46120C6ABF /* [CP] Copy Pods Resources */, + 128F729F1F39B73C00AC6E4C /* SwiftLint */, + 9CE3F8FA71585F7964C43538 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( - 932EF23620BE7E6E0052210C /* PBXTargetDependency */, ); name = "ARKit+CoreLocation"; productName = "ARKit+CoreLocation"; @@ -322,6 +292,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 12318E3B1F3B444400ACAD16 /* Main.storyboard in Resources */, 49A3FBE81F09988100AA59C8 /* LaunchScreen.storyboard in Resources */, 49A3FBE51F09988100AA59C8 /* Assets.xcassets in Resources */, ); @@ -344,20 +315,96 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 935FB3C020BD304200F6A081 /* Swiftlint */ = { + 128F729F1F39B73C00AC6E4C /* SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = SwiftLint; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; + 3B65648ABF0CBE46120C6ABF /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9CE3F8FA71585F7964C43538 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/ARCL/ARCL.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ARCL.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + B912B23DE2753A7230AC73FF /* Swiftlint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework", + ); name = Swiftlint; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; }; + F3C651027697D46CB173FF94 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ARKit+CoreLocation-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -365,9 +412,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D8C205D11F5B197200675E6E /* NotSupportedViewController.swift in Sources */, - 49A3FBE01F09988100AA59C8 /* ViewController.swift in Sources */, + 12318E3D1F3B457200ACAD16 /* Utils.swift in Sources */, + 49A3FBE01F09988100AA59C8 /* ARCLViewController.swift in Sources */, + 369336F3221B4B730097D8FA /* NotSupportedViewController.swift in Sources */, + 36B3F34B221D077700745096 /* SettingsViewController.swift in Sources */, 49A3FBDC1F09988100AA59C8 /* AppDelegate.swift in Sources */, + 3643DAED221E3390002BEAFC /* OpenARCell.swift in Sources */, + 3643DAEF221E3840002BEAFC /* LocationCell.swift in Sources */, + 3643DAEB221E30C6002BEAFC /* UIButton+Designable.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -375,16 +427,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 932EF26320BE83A80052210C /* SceneLocationEstimate.swift in Sources */, - 932EF26820BE83A80052210C /* FloatingPoint+Radians.swift in Sources */, - 932EF26620BE83A80052210C /* CLLocation+Extensions.swift in Sources */, - 932EF26220BE83A80052210C /* LocationNode.swift in Sources */, - 932EF26920BE83A80052210C /* CGPoint+Extensions.swift in Sources */, - 932EF26520BE83A80052210C /* LocationManager.swift in Sources */, - 932EF26120BE83A80052210C /* SceneLocationView.swift in Sources */, - 932EF26420BE83A80052210C /* SceneLocationEstimate+Extensions.swift in Sources */, - 932EF26A20BE83A80052210C /* SCNNode+Extensions.swift in Sources */, - 932EF26720BE83A80052210C /* SCNVector3+Extensions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -409,14 +451,17 @@ target = 49A3FBD71F09988100AA59C8 /* ARKit+CoreLocation */; targetProxy = 932EF22E20BE7E6E0052210C /* PBXContainerItemProxy */; }; - 932EF23620BE7E6E0052210C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 932EF22120BE7E6D0052210C /* ARCL */; - targetProxy = 932EF23520BE7E6E0052210C /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 12318E391F3B444400ACAD16 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 12318E3A1F3B444400ACAD16 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; 49A3FBE61F09988100AA59C8 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( @@ -541,13 +586,13 @@ }; 49A3FBED1F09988100AA59C8 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 8C31ACA439BC114F28F96BDD /* Pods-ARKit+CoreLocation.debug.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - DEVELOPMENT_TEAM = Q6W7LYC48G; + DEVELOPMENT_TEAM = 268S5GJFWZ; INFOPLIST_FILE = "ARKit+CoreLocation/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "ProjectDent.ARKit-CoreLocation"; + PRODUCT_BUNDLE_IDENTIFIER = "com.maaap.ProjectDent.ARKit-CoreLocation"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; @@ -556,13 +601,13 @@ }; 49A3FBEE1F09988100AA59C8 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = CED01C5C93D16CD7C03711E5 /* Pods-ARKit+CoreLocation.release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - DEVELOPMENT_TEAM = Q6W7LYC48G; + DEVELOPMENT_TEAM = 268S5GJFWZ; INFOPLIST_FILE = "ARKit+CoreLocation/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "ProjectDent.ARKit-CoreLocation"; + PRODUCT_BUNDLE_IDENTIFIER = "com.maaap.ProjectDent.ARKit-CoreLocation"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; @@ -581,7 +626,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 268S5GJFWZ; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -611,7 +656,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 268S5GJFWZ; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -632,7 +677,6 @@ 932EF23B20BE7E6E0052210C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; @@ -655,7 +699,6 @@ 932EF23C20BE7E6E0052210C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; diff --git a/ARKit+CoreLocation.xcworkspace/contents.xcworkspacedata b/ARKit+CoreLocation.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..4bc1deda --- /dev/null +++ b/ARKit+CoreLocation.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ARKit+CoreLocation.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ARKit+CoreLocation.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/ARKit+CoreLocation.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ARKit+CoreLocation/ARCLViewController.swift b/ARKit+CoreLocation/ARCLViewController.swift new file mode 100644 index 00000000..b863fb96 --- /dev/null +++ b/ARKit+CoreLocation/ARCLViewController.swift @@ -0,0 +1,316 @@ +// +// ARCLViewController.swift +// ARKit+CoreLocation +// +// Created by Andrew Hart on 02/07/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// + +import UIKit +import SceneKit +import MapKit +import ARCL + +@available(iOS 11.0, *) +class ARCLViewController: UIViewController { + @IBOutlet var mapView: MKMapView! + @IBOutlet var infoLabel: UILabel! + + @IBOutlet var contentView: UIView! + let sceneLocationView = SceneLocationView() + + var userAnnotation: MKPointAnnotation? + var locationEstimateAnnotation: MKPointAnnotation? + + var updateUserLocationTimer: Timer? + var updateInfoLabelTimer: Timer? + + var centerMapOnUserLocation: Bool = true + var routes: [MKRoute]? + + var showMap = false { + didSet { + guard let mapView = mapView else { + return + } + mapView.isHidden = !showMap + } + } + + /// Whether to display some debugging data + /// This currently displays the coordinate of the best location estimate + /// The initial value is respected + let displayDebugging = false + + let adjustNorthByTappingSidesOfScreen = false + + class func loadFromStoryboard() -> ARCLViewController { + return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ARCLViewController") as! ARCLViewController + // swiftlint:disable:previous force_cast + } + + override func viewDidLoad() { + super.viewDidLoad() + + updateInfoLabelTimer = Timer.scheduledTimer(timeInterval: 0.1, + target: self, + selector: #selector(ARCLViewController.updateInfoLabel), + userInfo: nil, + repeats: true) + + // Set to true to display an arrow which points north. + // Checkout the comments in the property description and on the readme on this. +// sceneLocationView.orientToTrueNorth = false +// sceneLocationView.locationEstimateMethod = .coreLocationDataOnly + + sceneLocationView.showAxesNode = true + sceneLocationView.showFeaturePoints = displayDebugging + + // Now add the route or location annotations as appropriate + addSceneModels() + + contentView.addSubview(sceneLocationView) + sceneLocationView.frame = contentView.bounds + + mapView.isHidden = !showMap + + if showMap { + updateUserLocationTimer = Timer.scheduledTimer( + timeInterval: 0.5, + target: self, + selector: #selector(ARCLViewController.updateUserLocation), + userInfo: nil, + repeats: true) + + routes?.forEach { mapView.addOverlay($0.polyline) } + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: animated) + print("run") + sceneLocationView.run() + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + print("pause") + // Pause the view's session + sceneLocationView.pause() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + sceneLocationView.frame = contentView.bounds + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + super.touchesBegan(touches, with: event) + guard let touch = touches.first, + let view = touch.view else { return } + + if mapView == view || mapView.recursiveSubviews().contains(view) { + centerMapOnUserLocation = false + } else { + let location = touch.location(in: self.view) + + if location.x <= 40 && adjustNorthByTappingSidesOfScreen { + print("left side of the screen") + sceneLocationView.moveSceneHeadingAntiClockwise() + } else if location.x >= view.frame.size.width - 40 && adjustNorthByTappingSidesOfScreen { + print("right side of the screen") + sceneLocationView.moveSceneHeadingClockwise() + } else { + let image = UIImage(named: "pin")! + let annotationNode = LocationAnnotationNode(location: nil, image: image) + annotationNode.scaleRelativeToDistance = true + sceneLocationView.addLocationNodeForCurrentPosition(locationNode: annotationNode) + } + } + } +} + +// MARK: - MKMapViewDelegate + +@available(iOS 11.0, *) +extension ARCLViewController: MKMapViewDelegate { + + func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { + let renderer = MKPolylineRenderer(overlay: overlay) + renderer.lineWidth = 3 + renderer.strokeColor = UIColor.blue.withAlphaComponent(0.5) + + return renderer + } + + func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { + guard !(annotation is MKUserLocation), + let pointAnnotation = annotation as? MKPointAnnotation else { return nil } + + let marker = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: nil) + + if pointAnnotation == self.userAnnotation { + marker.displayPriority = .required + marker.glyphImage = UIImage(named: "user") + } else { + marker.displayPriority = .required + marker.markerTintColor = UIColor(hue: 0.267, saturation: 0.67, brightness: 0.77, alpha: 1.0) + marker.glyphImage = UIImage(named: "compass") + } + + return marker + } +} + +// MARK: - Implementation + +@available(iOS 11.0, *) +extension ARCLViewController { + + /// Adds the appropriate ARKit models to the scene. Note: that this won't + /// do anything until the scene has a `currentLocation`. It "polls" on that + /// and when a location is finally discovered, the models are added. + func addSceneModels() { + // 1. Don't try to add the models to the scene until we have a current location + guard sceneLocationView.sceneLocationManager.currentLocation != nil else { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in + self?.addSceneModels() + } + return + } + + // 2. If there is a route, show that + if let routes = routes { + sceneLocationView.addRoutes(routes: routes) + } else { + // 3. If not, then show the + buildDemoData().forEach { + sceneLocationView.addLocationNodeWithConfirmedLocation(locationNode: $0) + } + } + } + + /// Builds the location annotations for a few random objects, scattered across the country + /// + /// - Returns: an array of annotation nodes. + func buildDemoData() -> [LocationAnnotationNode] { + var nodes: [LocationAnnotationNode] = [] + + let spaceNeedle = buildNode(latitude: 47.6205, longitude: -122.3493, altitude: 225, imageName: "pin") + nodes.append(spaceNeedle) + + let empireStateBuilding = buildNode(latitude: 40.7484, longitude: -73.9857, altitude: 14.3, imageName: "pin") + nodes.append(empireStateBuilding) + + let canaryWharf = buildNode(latitude: 51.504607, longitude: -0.019592, altitude: 236, imageName: "pin") + nodes.append(canaryWharf) + + let applePark = buildViewNode(latitude: 37.334807, longitude: -122.009076, altitude: 100, text: "Apple Park") + nodes.append(applePark) + + return nodes + } + + @objc + func updateUserLocation() { + guard let currentLocation = sceneLocationView.sceneLocationManager.currentLocation else { + return + } + + DispatchQueue.main.async { [weak self ] in + guard let self = self else { + return + } + + if self.userAnnotation == nil { + self.userAnnotation = MKPointAnnotation() + self.mapView.addAnnotation(self.userAnnotation!) + } + + UIView.animate(withDuration: 0.5, delay: 0, options: .allowUserInteraction, animations: { + self.userAnnotation?.coordinate = currentLocation.coordinate + }, completion: nil) + + if self.centerMapOnUserLocation { + UIView.animate(withDuration: 0.45, + delay: 0, + options: .allowUserInteraction, + animations: { + self.mapView.setCenter(self.userAnnotation!.coordinate, animated: false) + }, completion: { _ in + self.mapView.region.span = MKCoordinateSpan(latitudeDelta: 0.0005, longitudeDelta: 0.0005) + }) + } + + if self.displayDebugging { + if let bestLocationEstimate = self.sceneLocationView.sceneLocationManager.bestLocationEstimate { + if self.locationEstimateAnnotation == nil { + self.locationEstimateAnnotation = MKPointAnnotation() + self.mapView.addAnnotation(self.locationEstimateAnnotation!) + } + self.locationEstimateAnnotation?.coordinate = bestLocationEstimate.location.coordinate + } else if self.locationEstimateAnnotation != nil { + self.mapView.removeAnnotation(self.locationEstimateAnnotation!) + self.locationEstimateAnnotation = nil + } + } + } + } + + @objc + func updateInfoLabel() { + if let position = sceneLocationView.currentScenePosition { + infoLabel.text = "x: \(position.x.short), y: \(position.y.short), z: \(position.z.short)\n" + } + + if let eulerAngles = sceneLocationView.currentEulerAngles { + infoLabel.text!.append("Euler x: \(eulerAngles.x.short), y: \(eulerAngles.y.short), z: \(eulerAngles.z.short)\n") + } + + let comp = Calendar.current.dateComponents([.hour, .minute, .second, .nanosecond], from: Date()) + if let hour = comp.hour, let minute = comp.minute, let second = comp.second, let nanosecond = comp.nanosecond { + infoLabel.text!.append("\(hour.short):\(minute.short):\(second.short):\(nanosecond.short3)") + } + } + + func buildNode(latitude: CLLocationDegrees, longitude: CLLocationDegrees, + altitude: CLLocationDistance, imageName: String) -> LocationAnnotationNode { + let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) + let location = CLLocation(coordinate: coordinate, altitude: altitude) + let image = UIImage(named: imageName)! + return LocationAnnotationNode(location: location, image: image) + } + + func buildViewNode(latitude: CLLocationDegrees, longitude: CLLocationDegrees, + altitude: CLLocationDistance, text: String) -> LocationAnnotationNode { + let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) + let location = CLLocation(coordinate: coordinate, altitude: altitude) + let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) + label.text = text + label.backgroundColor = .green + label.textAlignment = .center + return LocationAnnotationNode(location: location, view: label) + } +} + +// MARK: - Helpers + +extension DispatchQueue { + func asyncAfter(timeInterval: TimeInterval, execute: @escaping () -> Void) { + self.asyncAfter( + deadline: DispatchTime.now() + Double(Int64(timeInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), + execute: execute) + } +} + +extension UIView { + func recursiveSubviews() -> [UIView] { + var recursiveSubviews = self.subviews + + subviews.forEach { recursiveSubviews.append(contentsOf: $0.recursiveSubviews()) } + + return recursiveSubviews + } +} diff --git a/ARKit+CoreLocation/AppDelegate.swift b/ARKit+CoreLocation/AppDelegate.swift index 682439d2..db5b0c9b 100644 --- a/ARKit+CoreLocation/AppDelegate.swift +++ b/ARKit+CoreLocation/AppDelegate.swift @@ -13,8 +13,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - print("NEW SESSION") + func application(_ application: UIApplication, didFinishLaunchingWithOptions + launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { UIApplication.shared.isIdleTimerDisabled = true @@ -23,7 +23,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { self.window!.makeKeyAndVisible() if #available(iOS 11.0, *) { - let vc = ViewController() + guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() else { + return false + } self.window!.rootViewController = vc } else { self.window!.rootViewController = NotSupportedViewController() diff --git a/ARKit+CoreLocation/Base.lproj/Main.storyboard b/ARKit+CoreLocation/Base.lproj/Main.storyboard new file mode 100644 index 00000000..0da97cb3 --- /dev/null +++ b/ARKit+CoreLocation/Base.lproj/Main.storyboard @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ARKit+CoreLocation/LocationCell.swift b/ARKit+CoreLocation/LocationCell.swift new file mode 100644 index 00000000..f8edbe88 --- /dev/null +++ b/ARKit+CoreLocation/LocationCell.swift @@ -0,0 +1,92 @@ +// +// LocationCell.swift +// ARKit+CoreLocation +// +// Created by Eric Internicola on 2/20/19. +// Copyright © 2019 Project Dent. All rights reserved. +// + +import CoreLocation +import MapKit +import UIKit + +class LocationCell: UITableViewCell { + + var locationManager: CLLocationManager? + var locationUpdateTimer: Timer? + + var currentLocation: CLLocation? { + return locationManager?.location + } + + var mapItem: MKMapItem? { + didSet { + updateCell() + } + } + + @IBOutlet weak var distanceLabel: UILabel! + @IBOutlet weak var titleLabel: UILabel! + + override func prepareForReuse() { + super.prepareForReuse() + distanceLabel.text = nil + titleLabel.text = nil + locationUpdateTimer?.invalidate() + } + +} + +// MARK: - Implementation + +extension LocationCell { + + @objc + func updateCell() { + guard let mapItem = mapItem else { + locationUpdateTimer?.invalidate() + return + } + titleLabel.text = mapItem.titleLabelText + + guard let currentLocation = currentLocation else { + distanceLabel.text = "📡" + return + } + guard let mapItemLocation = mapItem.placemark.location else { + distanceLabel.text = "🤷‍♂️" + return + } + + distanceLabel.text = String(format: "%.0f km", mapItemLocation.distance(from: currentLocation)/1000) + + locationUpdateTimer = Timer(timeInterval: 1, target: self, selector: #selector(updateCell), userInfo: nil, repeats: false) + } + +} + +private extension MKMapItem { + + var titleLabelText: String { + var result = "" + + if let name = name { + result += name + } + if let addressDictionary = placemark.addressDictionary { + if let street = addressDictionary["Street"] as? String { + result += "\n\(street)" + } + if let city = addressDictionary["City"] as? String, + let state = addressDictionary["State"] as? String, + let zip = addressDictionary["ZIP"] as? String { + result += "\n\(city), \(state) \(zip)" + } + } else if let location = placemark.location { + result += "\n\(location.coordinate)" + } + + return result + } + +} diff --git a/ARKit+CoreLocation/OpenARCell.swift b/ARKit+CoreLocation/OpenARCell.swift new file mode 100644 index 00000000..3a7c04f7 --- /dev/null +++ b/ARKit+CoreLocation/OpenARCell.swift @@ -0,0 +1,25 @@ +// +// OpenARCell.swift +// ARKit+CoreLocation +// +// Created by Eric Internicola on 2/20/19. +// Copyright © 2019 Project Dent. All rights reserved. +// + +import UIKit + +@available(iOS 11.0, *) +class OpenARCell: UITableViewCell { + + weak var parentVC: SettingsViewController? + @IBOutlet weak var openARButton: UIButton! + + @IBAction + func tappedOpenARButton(_ sender: Any) { + guard let vc = parentVC?.createARVC() else { + return assertionFailure("Failed to create ARVC") + } + parentVC?.navigationController?.pushViewController(vc, animated: true) + } + +} diff --git a/ARKit+CoreLocation/SettingsViewController.swift b/ARKit+CoreLocation/SettingsViewController.swift new file mode 100644 index 00000000..17223fbd --- /dev/null +++ b/ARKit+CoreLocation/SettingsViewController.swift @@ -0,0 +1,262 @@ +// +// SettingsViewController.swift +// ARKit+CoreLocation +// +// Created by Eric Internicola on 2/19/19. +// Copyright © 2019 Project Dent. All rights reserved. +// + +import CoreLocation +import MapKit +import UIKit + +@available(iOS 11.0, *) +class SettingsViewController: UIViewController { + + @IBOutlet weak var showMapSwitch: UISwitch! + @IBOutlet weak var showPointsOfInterest: UISwitch! + @IBOutlet weak var showRouteDirections: UISwitch! + @IBOutlet weak var addressText: UITextField! + @IBOutlet weak var searchResultTable: UITableView! + @IBOutlet weak var refreshControl: UIActivityIndicatorView! + + var locationManager = CLLocationManager() + + var mapSearchResults: [MKMapItem]? + + override func viewDidLoad() { + super.viewDidLoad() + + locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation + locationManager.distanceFilter = kCLDistanceFilterNone + locationManager.headingFilter = kCLHeadingFilterNone + locationManager.pausesLocationUpdatesAutomatically = false + locationManager.delegate = self + locationManager.startUpdatingHeading() + locationManager.startUpdatingLocation() + + locationManager.requestWhenInUseAuthorization() + + addressText.delegate = self + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(true, animated: animated) + } + + @IBAction + func toggledSwitch(_ sender: UISwitch) { + if sender == showPointsOfInterest { + showRouteDirections.isOn = !sender.isOn + searchResultTable.reloadData() + } else if sender == showRouteDirections { + showPointsOfInterest.isOn = !sender.isOn + searchResultTable.reloadData() + } + } + + @IBAction + func tappedSearch(_ sender: Any) { + guard let text = addressText.text, !text.isEmpty else { + return + } + searchForLocation() + } +} + +// MARK: - UITextFieldDelegate + +@available(iOS 11.0, *) +extension SettingsViewController: UITextFieldDelegate { + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + + if string == "\n" { + DispatchQueue.main.async { [weak self] in + self?.searchForLocation() + } + } + + return true + } + +} + +// MARK: - DataSource + +@available(iOS 11.0, *) +extension SettingsViewController: UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if showPointsOfInterest.isOn { + return 1 + } + guard let mapSearchResults = mapSearchResults else { + return 0 + } + + return mapSearchResults.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if showPointsOfInterest.isOn { + let cell = tableView.dequeueReusableCell(withIdentifier: "OpenARCell", for: indexPath) + guard let openARCell = cell as? OpenARCell else { + return cell + } + openARCell.parentVC = self + + return openARCell + } else { + let cell = tableView.dequeueReusableCell(withIdentifier: "LocationCell", for: indexPath) + guard let mapSearchResults = mapSearchResults, + indexPath.row < mapSearchResults.count, + let locationCell = cell as? LocationCell else { + return cell + } + locationCell.locationManager = locationManager + locationCell.mapItem = mapSearchResults[indexPath.row] + + return locationCell + } + } +} + +// MARK: - UITableViewDelegate + +@available(iOS 11.0, *) +extension SettingsViewController: UITableViewDelegate { + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + guard let mapSearchResults = mapSearchResults, indexPath.row < mapSearchResults.count else { + return + } + let selectedMapItem = mapSearchResults[indexPath.row] + getDirections(to: selectedMapItem) + } + +} + +// MARK: - CLLocationManagerDelegate + +@available(iOS 11.0, *) +extension SettingsViewController: CLLocationManagerDelegate { + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + + } +} + + + +// MARK: - Implementation + +@available(iOS 11.0, *) +extension SettingsViewController { + + func createARVC() -> ARCLViewController { + let arclVC = ARCLViewController.loadFromStoryboard() + arclVC.showMap = showMapSwitch.isOn + + return arclVC + } + + func getDirections(to mapLocation: MKMapItem) { + refreshControl.startAnimating() + + let request = MKDirections.Request() + request.source = MKMapItem.forCurrentLocation() + request.destination = mapLocation + request.requestsAlternateRoutes = false + + let directions = MKDirections(request: request) + + directions.calculate(completionHandler: { response, error in + defer { + DispatchQueue.main.async { [weak self] in + self?.refreshControl.stopAnimating() + } + } + if let error = error { + return print("Error getting directions: \(error.localizedDescription)") + } + guard let response = response else { + return assertionFailure("No error, but no response, either.") + } + + DispatchQueue.main.async { [weak self] in + guard let self = self else { + return + } + + let arclVC = self.createARVC() + arclVC.routes = response.routes + self.navigationController?.pushViewController(arclVC, animated: true) + } + }) + } + + /// Searches for the location that was entered into the address text + func searchForLocation() { + guard let addressText = addressText.text, !addressText.isEmpty else { + return + } + + showRouteDirections.isOn = true + toggledSwitch(showRouteDirections) + + refreshControl.startAnimating() + defer { + self.addressText.resignFirstResponder() + } + + let request = MKLocalSearch.Request() + request.naturalLanguageQuery = addressText + + let search = MKLocalSearch(request: request) + search.start { response, error in + defer { + DispatchQueue.main.async { [weak self] in + self?.refreshControl.stopAnimating() + } + } + if let error = error { + return assertionFailure("Error searching for \(addressText): \(error.localizedDescription)") + } + guard let response = response, response.mapItems.count > 0 else { + return assertionFailure("No response or empty response") + } + DispatchQueue.main.async { [weak self] in + guard let self = self else { + return + } + self.mapSearchResults = response.sortedMapItems(byDistanceFrom: self.locationManager.location) + self.searchResultTable.reloadData() + } + } + } +} + +extension MKLocalSearch.Response { + + func sortedMapItems(byDistanceFrom location: CLLocation?) -> [MKMapItem] { + guard let location = location else { + return mapItems + } + + return mapItems.sorted { (first, second) -> Bool in + guard let d1 = first.placemark.location?.distance(from: location), + let d2 = second.placemark.location?.distance(from: location) else { + return true + } + + return d1 < d2 + } + } + +} diff --git a/ARKit+CoreLocation/UIButton+Designable.swift b/ARKit+CoreLocation/UIButton+Designable.swift new file mode 100644 index 00000000..9ab7af88 --- /dev/null +++ b/ARKit+CoreLocation/UIButton+Designable.swift @@ -0,0 +1,36 @@ +// +// UIButton+Designable.swift +// ARKit+CoreLocation +// +// Created by Eric Internicola on 2/20/19. +// Copyright © 2019 Project Dent. All rights reserved. +// + +import UIKit + +extension UIButton { + + @IBInspectable + var borderColor: UIColor? { + get { + guard let cgColor = layer.borderColor else { + return nil + } + return UIColor(cgColor: cgColor) + } + set { + layer.borderColor = newValue?.cgColor + } + } + + @IBInspectable + var borderWidth: CGFloat { + get { + return layer.borderWidth + } + set { + layer.borderWidth = newValue + } + } + +} diff --git a/ARKit+CoreLocation/Utils.swift b/ARKit+CoreLocation/Utils.swift new file mode 100644 index 00000000..7d00d348 --- /dev/null +++ b/ARKit+CoreLocation/Utils.swift @@ -0,0 +1,22 @@ +// +// Utils.swift +// ARKit+CoreLocation +// +// Created by Ilya Seliverstov on 09/08/2017. +// Copyright © 2017 Project Dent. All rights reserved. +// + +import UIKit + +class Utils { + fileprivate init () { } + + class func getStoryboard(_ storyboard: String = "Main") -> UIStoryboard { + return UIStoryboard(name: storyboard, bundle: Bundle.main) + } + + class func createViewController(_ identifier: String, storyboard: String = "Main") -> T { + return Utils.getStoryboard(storyboard) + .instantiateViewController(withIdentifier: identifier) as! T // swiftlint:disable:this force_cast + } +} diff --git a/ARKit+CoreLocation/ViewController.swift b/ARKit+CoreLocation/ViewController.swift deleted file mode 100644 index f36808b9..00000000 --- a/ARKit+CoreLocation/ViewController.swift +++ /dev/null @@ -1,339 +0,0 @@ -// -// ViewController.swift -// ARKit+CoreLocation -// -// Created by Andrew Hart on 02/07/2017. -// Copyright © 2017 Project Dent. All rights reserved. -// - -import UIKit -import SceneKit -import MapKit -import ARCL - -@available(iOS 11.0, *) -class ViewController: UIViewController { - let sceneLocationView = SceneLocationView() - - let mapView = MKMapView() - var userAnnotation: MKPointAnnotation? - var locationEstimateAnnotation: MKPointAnnotation? - - var updateUserLocationTimer: Timer? - - ///Whether to show a map view - ///The initial value is respected - var showMapView: Bool = false - - var centerMapOnUserLocation: Bool = true - - ///Whether to display some debugging data - ///This currently displays the coordinate of the best location estimate - ///The initial value is respected - var displayDebugging = false - - var infoLabel = UILabel() - - var updateInfoLabelTimer: Timer? - - var adjustNorthByTappingSidesOfScreen = false - - override func viewDidLoad() { - super.viewDidLoad() - - infoLabel.font = UIFont.systemFont(ofSize: 10) - infoLabel.textAlignment = .left - infoLabel.textColor = UIColor.white - infoLabel.numberOfLines = 0 - sceneLocationView.addSubview(infoLabel) - - updateInfoLabelTimer = Timer.scheduledTimer( - timeInterval: 0.1, - target: self, - selector: #selector(ViewController.updateInfoLabel), - userInfo: nil, - repeats: true) - - // Set to true to display an arrow which points north. - //Checkout the comments in the property description and on the readme on this. -// sceneLocationView.orientToTrueNorth = false - -// sceneLocationView.locationEstimateMethod = .coreLocationDataOnly - sceneLocationView.showAxesNode = true - sceneLocationView.locationDelegate = self - - if displayDebugging { - sceneLocationView.showFeaturePoints = true - } - - buildDemoData().forEach { sceneLocationView.addLocationNodeWithConfirmedLocation(locationNode: $0) } - - view.addSubview(sceneLocationView) - - if showMapView { - mapView.delegate = self - mapView.showsUserLocation = true - mapView.alpha = 0.8 - view.addSubview(mapView) - - updateUserLocationTimer = Timer.scheduledTimer( - timeInterval: 0.5, - target: self, - selector: #selector(ViewController.updateUserLocation), - userInfo: nil, - repeats: true) - } - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - print("run") - sceneLocationView.run() - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - - print("pause") - // Pause the view's session - sceneLocationView.pause() - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - sceneLocationView.frame = view.bounds - - infoLabel.frame = CGRect(x: 6, y: 0, width: self.view.frame.size.width - 12, height: 14 * 4) - - if showMapView { - infoLabel.frame.origin.y = (self.view.frame.size.height / 2) - infoLabel.frame.size.height - } else { - infoLabel.frame.origin.y = self.view.frame.size.height - infoLabel.frame.size.height - } - - mapView.frame = CGRect( - x: 0, - y: self.view.frame.size.height / 2, - width: self.view.frame.size.width, - height: self.view.frame.size.height / 2) - } - - @objc func updateUserLocation() { - guard let currentLocation = sceneLocationView.currentLocation() else { - return - } - - DispatchQueue.main.async { - if let bestEstimate = self.sceneLocationView.bestLocationEstimate(), - let position = self.sceneLocationView.currentScenePosition() { - print("") - print("Fetch current location") - print("best location estimate, position: \(bestEstimate.position), location: \(bestEstimate.location.coordinate), accuracy: \(bestEstimate.location.horizontalAccuracy), date: \(bestEstimate.location.timestamp)") - print("current position: \(position)") - - let translation = bestEstimate.translatedLocation(to: position) - - print("translation: \(translation)") - print("translated location: \(currentLocation)") - print("") - } - - if self.userAnnotation == nil { - self.userAnnotation = MKPointAnnotation() - self.mapView.addAnnotation(self.userAnnotation!) - } - - UIView.animate(withDuration: 0.5, delay: 0, options: UIView.AnimationOptions.allowUserInteraction, animations: { - self.userAnnotation?.coordinate = currentLocation.coordinate - }, completion: nil) - - if self.centerMapOnUserLocation { - UIView.animate(withDuration: 0.45, delay: 0, options: UIView.AnimationOptions.allowUserInteraction, animations: { - self.mapView.setCenter(self.userAnnotation!.coordinate, animated: false) - }, completion: { _ in - self.mapView.region.span = MKCoordinateSpan(latitudeDelta: 0.0005, longitudeDelta: 0.0005) - }) - } - - if self.displayDebugging { - let bestLocationEstimate = self.sceneLocationView.bestLocationEstimate() - - if bestLocationEstimate != nil { - if self.locationEstimateAnnotation == nil { - self.locationEstimateAnnotation = MKPointAnnotation() - self.mapView.addAnnotation(self.locationEstimateAnnotation!) - } - - self.locationEstimateAnnotation!.coordinate = bestLocationEstimate!.location.coordinate - } else { - if self.locationEstimateAnnotation != nil { - self.mapView.removeAnnotation(self.locationEstimateAnnotation!) - self.locationEstimateAnnotation = nil - } - } - } - } - } - - @objc func updateInfoLabel() { - if let position = sceneLocationView.currentScenePosition() { - infoLabel.text = "x: \(String(format: "%.2f", position.x)), y: \(String(format: "%.2f", position.y)), z: \(String(format: "%.2f", position.z))\n" - } - - if let eulerAngles = sceneLocationView.currentEulerAngles() { - infoLabel.text!.append("Euler x: \(String(format: "%.2f", eulerAngles.x)), y: \(String(format: "%.2f", eulerAngles.y)), z: \(String(format: "%.2f", eulerAngles.z))\n") - } - - if let heading = sceneLocationView.locationManager.heading, - let accuracy = sceneLocationView.locationManager.headingAccuracy { - infoLabel.text!.append("Heading: \(heading)º, accuracy: \(Int(round(accuracy)))º\n") - } - - let date = Date() - let comp = Calendar.current.dateComponents([.hour, .minute, .second, .nanosecond], from: date) - - if let hour = comp.hour, let minute = comp.minute, let second = comp.second, let nanosecond = comp.nanosecond { - infoLabel.text!.append("\(String(format: "%02d", hour)):\(String(format: "%02d", minute)):\(String(format: "%02d", second)):\(String(format: "%03d", nanosecond / 1000000))") - } - } - - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - super.touchesBegan(touches, with: event) - - guard - let touch = touches.first, - let touchView = touch.view - else { - return - } - - if mapView == touchView || mapView.recursiveSubviews().contains(touchView) { - centerMapOnUserLocation = false - } else { - let location = touch.location(in: self.view) - - if location.x <= 40 && adjustNorthByTappingSidesOfScreen { - print("left side of the screen") - sceneLocationView.moveSceneHeadingAntiClockwise() - } else if location.x >= view.frame.size.width - 40 && adjustNorthByTappingSidesOfScreen { - print("right side of the screen") - sceneLocationView.moveSceneHeadingClockwise() - } else { - let image = UIImage(named: "pin")! - let annotationNode = LocationAnnotationNode(location: nil, image: image) - annotationNode.scaleRelativeToDistance = true - sceneLocationView.addLocationNodeForCurrentPosition(locationNode: annotationNode) - } - } - } -} - -// MARK: - MKMapViewDelegate -@available(iOS 11.0, *) -extension ViewController: MKMapViewDelegate { - func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { - if annotation is MKUserLocation { - return nil - } - - guard let pointAnnotation = annotation as? MKPointAnnotation else { - return nil - } - - let marker = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: nil) - marker.displayPriority = .required - - if pointAnnotation == self.userAnnotation { - marker.glyphImage = UIImage(named: "user") - } else { - marker.markerTintColor = UIColor(hue: 0.267, saturation: 0.67, brightness: 0.77, alpha: 1.0) - marker.glyphImage = UIImage(named: "compass") - } - - return marker - } -} - -// MARK: - SceneLocationViewDelegate -@available(iOS 11.0, *) -extension ViewController: SceneLocationViewDelegate { - func sceneLocationViewDidAddSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) { - print("add scene location estimate, position: \(position), location: \(location.coordinate), accuracy: \(location.horizontalAccuracy), date: \(location.timestamp)") - } - - func sceneLocationViewDidRemoveSceneLocationEstimate(sceneLocationView: SceneLocationView, position: SCNVector3, location: CLLocation) { - print("remove scene location estimate, position: \(position), location: \(location.coordinate), accuracy: \(location.horizontalAccuracy), date: \(location.timestamp)") - } - - func sceneLocationViewDidConfirmLocationOfNode(sceneLocationView: SceneLocationView, node: LocationNode) { - } - - func sceneLocationViewDidSetupSceneNode(sceneLocationView: SceneLocationView, sceneNode: SCNNode) { - - } - - func sceneLocationViewDidUpdateLocationAndScaleOfLocationNode(sceneLocationView: SceneLocationView, locationNode: LocationNode) { - - } -} - -// MARK: - Data Helpers -@available(iOS 11.0, *) -private extension ViewController { - func buildDemoData() -> [LocationAnnotationNode] { - var nodes: [LocationAnnotationNode] = [] - - // TODO: add a few more demo points of interest. - // TODO: use more varied imagery. - - let spaceNeedle = buildNode(latitude: 47.6205, longitude: -122.3493, altitude: 225, imageName: "pin") - nodes.append(spaceNeedle) - - let empireStateBuilding = buildNode(latitude: 40.7484, longitude: -73.9857, altitude: 14.3, imageName: "pin") - nodes.append(empireStateBuilding) - - let canaryWharf = buildNode(latitude: 51.504607, longitude: -0.019592, altitude: 236, imageName: "pin") - nodes.append(canaryWharf) - - let applePark = buildViewNode(latitude: 37.334807, longitude: -122.009076, altitude: 100, text: "Apple Park") - nodes.append(applePark) - - return nodes - } - - func buildNode(latitude: CLLocationDegrees, longitude: CLLocationDegrees, altitude: CLLocationDistance, imageName: String) -> LocationAnnotationNode { - let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) - let location = CLLocation(coordinate: coordinate, altitude: altitude) - let image = UIImage(named: imageName)! - return LocationAnnotationNode(location: location, image: image) - } - - func buildViewNode(latitude: CLLocationDegrees, longitude: CLLocationDegrees, altitude: CLLocationDistance, text: String) -> LocationAnnotationNode { - let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) - let location = CLLocation(coordinate: coordinate, altitude: altitude) - let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) - label.text = text - label.backgroundColor = .green - return LocationAnnotationNode(location: location, view: label) - } -} - -extension DispatchQueue { - func asyncAfter(timeInterval: TimeInterval, execute: @escaping () -> Void) { - self.asyncAfter( - deadline: DispatchTime.now() + Double(Int64(timeInterval * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: execute) - } -} - -extension UIView { - func recursiveSubviews() -> [UIView] { - var recursiveSubviews = self.subviews - - for subview in subviews { - recursiveSubviews.append(contentsOf: subview.recursiveSubviews()) - } - - return recursiveSubviews - } -} diff --git a/Podfile b/Podfile new file mode 100644 index 00000000..0fc89de4 --- /dev/null +++ b/Podfile @@ -0,0 +1,8 @@ +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '11.0' +use_frameworks! +inhibit_all_warnings! + +target 'ARKit+CoreLocation' do + pod 'ARCL', :path => '.' +end diff --git a/Podfile.lock b/Podfile.lock new file mode 100644 index 00000000..9cc28368 --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - ARCL (1.0.4) + +DEPENDENCIES: + - ARCL (from `.`) + +EXTERNAL SOURCES: + ARCL: + :path: . + +SPEC CHECKSUMS: + ARCL: f759ad05cd3aef4ff81ea69b0774ed96c49aa544 + +PODFILE CHECKSUM: 0253a6a9d478bb7f0d71292e3283c52bdad2bd40 + +COCOAPODS: 1.4.0 diff --git a/Pods/Local Podspecs/ARCL.podspec.json b/Pods/Local Podspecs/ARCL.podspec.json new file mode 100644 index 00000000..8e5c70b0 --- /dev/null +++ b/Pods/Local Podspecs/ARCL.podspec.json @@ -0,0 +1,32 @@ +{ + "name": "ARCL", + "version": "1.0.4", + "summary": "ARKit + CoreLocation combines the high accuracy of AR with the scale of GPS data.", + "homepage": "https://github.com/ProjectDent/arkit-corelocation", + "authors": { + "Andrew Hart": "Andrew@ProjectDent.com" + }, + "license": { + "type": "MIT", + "file": "LICENSE" + }, + "source": { + "git": "https://ProjectDent@github.com/ProjectDent/ARKit-CoreLocation.git", + "tag": "1.0.4", + "submodules": false + }, + "platforms": { + "ios": "9.0" + }, + "swift_version": "4.2", + "requires_arc": true, + "source_files": "ARCL/Source/**/*.{swift}", + "frameworks": [ + "Foundation", + "UIKit", + "ARKit", + "CoreLocation", + "MapKit", + "SceneKit" + ] +} diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock new file mode 100644 index 00000000..9cc28368 --- /dev/null +++ b/Pods/Manifest.lock @@ -0,0 +1,16 @@ +PODS: + - ARCL (1.0.4) + +DEPENDENCIES: + - ARCL (from `.`) + +EXTERNAL SOURCES: + ARCL: + :path: . + +SPEC CHECKSUMS: + ARCL: f759ad05cd3aef4ff81ea69b0774ed96c49aa544 + +PODFILE CHECKSUM: 0253a6a9d478bb7f0d71292e3283c52bdad2bd40 + +COCOAPODS: 1.4.0 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 00000000..58b08a23 --- /dev/null +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,710 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 09ACA8CC9A3368AA873194BA28444F73 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73571F4B2281E0098DC76443D509656 /* Foundation.framework */; }; + 0C91A8DA418831E877CCA779333BCF0D /* Pods-ARKit+CoreLocation-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 1569D8AB75F6B4E0C4BB77FF9E53D61B /* Pods-ARKit+CoreLocation-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 14A6A686C90AFFDA970F45704840C229 /* SCNNode+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0DA643017FBBAA818CB7F76131A44F8 /* SCNNode+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3DE089ADC309F48F08141FCF1490A3FB /* CLLocation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E0422089577C15C1C0FCF1242687867 /* CLLocation+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 48938EB4F29DBE6E7F35BF3EE0FB5F32 /* ARCL-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A712144F76E5E1B0D30F7BE9BADCD4EB /* ARCL-dummy.m */; }; + 599CE3641B291140A8FB9E5D603F5D00 /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E76B312B647B2F7BD980DC2154894497 /* LocationManager.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5B4C10A00978AE1C3399AA575EE1E268 /* Pods-ARKit+CoreLocation-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D33B939D8285598F2C92F217F8E11CC6 /* Pods-ARKit+CoreLocation-dummy.m */; }; + 5DF44D6C8FB62B1F7675ABDD11CF2559 /* ARCL-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 69B96848BF644E78DD7C33D5B10BAE77 /* ARCL-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 63D0A822C50464A12515A4A7C17391B6 /* SceneLocationEstimate+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53CECF9ABC2C4785BD2C7C9DD901D74 /* SceneLocationEstimate+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 697460847D0DFE257FAAC2949867A056 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C77626DC61CC820DD862D736C3A8262 /* MapKit.framework */; }; + 6A07D0DE2872B0D0531C9D920E4BB114 /* SceneLocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19C516D9B979CDA8009D52F8EFE4351 /* SceneLocationManager.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 86B9BC78365017A09587892A218914F5 /* ARKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8448C8D3B02A33C992689E219E119203 /* ARKit.framework */; }; + 9B5798F537C91F6FA1FE92C60C9A405E /* SceneKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C7175760E70DBC0C749A613721BD92E3 /* SceneKit.framework */; }; + 9BCEAE87FDF2D9FB81641D19695DA15D /* FloatingPoint+Radians.swift in Sources */ = {isa = PBXBuildFile; fileRef = C08BF2189E40B1AEBDE5583CAA2C84B4 /* FloatingPoint+Radians.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9EDF3493B30106BF04CE6E8D58800DFB /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 893DA6918C0ED7EBDEE9A9C24940A7C5 /* CoreLocation.framework */; }; + B3AFFFFE4556B049893E062C5D766203 /* PolylineNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A955E7B9945823C9112DC45C333B65A /* PolylineNode.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B47A38E2D38C140007442C9C6AD08A31 /* CGPoint+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F89E65049BF2BF20F88DA1FB7E0BA5F /* CGPoint+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B536EBFA2C27782AFB6C859CD6B909CE /* SceneLocationViewEstimateDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91149C058CC2C7680A542C1764BE4FB1 /* SceneLocationViewEstimateDelegate.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B5BACEB22A43E845BBE0E822ADD3E0F1 /* SCNVector3+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3168EB8D57DD20FD65776E6E3E14644D /* SCNVector3+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + B6F75E6B64EEE45BFA7345D8E615DEFB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73571F4B2281E0098DC76443D509656 /* Foundation.framework */; }; + DA404C101804320A8214E463E334E308 /* SceneLocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4562550955B4278CDA3943C6043CE797 /* SceneLocationView.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E3AFA301454D38DB58F9FA5AA101928D /* SceneLocationView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A02D1AC555B012B8650EDB84F0ACC6E /* SceneLocationView+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E86F59767C2B326586FFEA1C9AD66D61 /* LocationAnnotationNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EC1A7FFBC06F12DDACC575520AC537 /* LocationAnnotationNode.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + EEBA8F60DC05CC128BEC96056C446F00 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9C167BE81500CB0164A60D9EEFFBD72 /* UIKit.framework */; }; + F0B85ABCD119C994FFEF7DAC02ADD35A /* SceneLocationEstimate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD17C8FFE8E07C175696087F92B2566 /* SceneLocationEstimate.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F561B76D6E66E38CA6DA638326F7FFE6 /* BaseTypes+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6984206E65585B8B022DA93360E14DD /* BaseTypes+Extensions.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FA93CA2766EFE77410BE4EF82B791E47 /* LocationNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57A325FB8CDAF8A062982C66A07A975D /* LocationNode.swift */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + E927894478333674B728678135340438 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = A4134F75EC58E09F3C60888E4C5EC4A3; + remoteInfo = ARCL; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 035356C852C901DCEDC674A281131F3D /* readme.jp.md */ = {isa = PBXFileReference; includeInIndex = 1; path = readme.jp.md; sourceTree = ""; }; + 0A02D1AC555B012B8650EDB84F0ACC6E /* SceneLocationView+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "SceneLocationView+Extensions.swift"; path = "ARCL/Source/SceneLocationView+Extensions.swift"; sourceTree = ""; }; + 0CD17C8FFE8E07C175696087F92B2566 /* SceneLocationEstimate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SceneLocationEstimate.swift; sourceTree = ""; }; + 14020CD2FADC6360BEB98E8F9A6A0C2F /* Pods-ARKit+CoreLocation.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-ARKit+CoreLocation.modulemap"; sourceTree = ""; }; + 1569D8AB75F6B4E0C4BB77FF9E53D61B /* Pods-ARKit+CoreLocation-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ARKit+CoreLocation-umbrella.h"; sourceTree = ""; }; + 1D74A47AD7FB1304DC0FF2D215FCE1B4 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1DE8136DA93CFFFCEBB235D0B18D7B12 /* Pods-ARKit+CoreLocation-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ARKit+CoreLocation-acknowledgements.plist"; sourceTree = ""; }; + 1F4ECE99464F4194DF857FAFEFCCA50B /* Pods_ARKit_CoreLocation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_ARKit_CoreLocation.framework; path = "Pods-ARKit+CoreLocation.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2A955E7B9945823C9112DC45C333B65A /* PolylineNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PolylineNode.swift; sourceTree = ""; }; + 2DFE09E4F7A507739F33B75C24DD1614 /* ARCL.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = ARCL.framework; path = ARCL.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3168EB8D57DD20FD65776E6E3E14644D /* SCNVector3+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "SCNVector3+Extensions.swift"; sourceTree = ""; }; + 3E0422089577C15C1C0FCF1242687867 /* CLLocation+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "CLLocation+Extensions.swift"; sourceTree = ""; }; + 3F89E65049BF2BF20F88DA1FB7E0BA5F /* CGPoint+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "CGPoint+Extensions.swift"; sourceTree = ""; }; + 4562550955B4278CDA3943C6043CE797 /* SceneLocationView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SceneLocationView.swift; path = ARCL/Source/SceneLocationView.swift; sourceTree = ""; }; + 49AF8AA326E76711FB29567A31A81D88 /* Pods-ARKit+CoreLocation.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ARKit+CoreLocation.release.xcconfig"; sourceTree = ""; }; + 57A325FB8CDAF8A062982C66A07A975D /* LocationNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocationNode.swift; sourceTree = ""; }; + 5C77626DC61CC820DD862D736C3A8262 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/MapKit.framework; sourceTree = DEVELOPER_DIR; }; + 69B96848BF644E78DD7C33D5B10BAE77 /* ARCL-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ARCL-umbrella.h"; sourceTree = ""; }; + 8448C8D3B02A33C992689E219E119203 /* ARKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ARKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/ARKit.framework; sourceTree = DEVELOPER_DIR; }; + 893DA6918C0ED7EBDEE9A9C24940A7C5 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/CoreLocation.framework; sourceTree = DEVELOPER_DIR; }; + 91149C058CC2C7680A542C1764BE4FB1 /* SceneLocationViewEstimateDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SceneLocationViewEstimateDelegate.swift; path = ARCL/Source/SceneLocationViewEstimateDelegate.swift; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9F26BAB6A40C4B6A19E747B3F459C8FF /* Pods-ARKit+CoreLocation-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ARKit+CoreLocation-frameworks.sh"; sourceTree = ""; }; + A0A555079EEFF9470F1B3705FBC9E6BC /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A4FF28CC89209C8800BB15011F5F0604 /* Pods-ARKit+CoreLocation-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ARKit+CoreLocation-acknowledgements.markdown"; sourceTree = ""; }; + A712144F76E5E1B0D30F7BE9BADCD4EB /* ARCL-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ARCL-dummy.m"; sourceTree = ""; }; + A9C167BE81500CB0164A60D9EEFFBD72 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + B0DA643017FBBAA818CB7F76131A44F8 /* SCNNode+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "SCNNode+Extensions.swift"; sourceTree = ""; }; + B1915EE8F804D88AB2BC9010EE047C95 /* ARCL.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ARCL.xcconfig; sourceTree = ""; }; + B19C516D9B979CDA8009D52F8EFE4351 /* SceneLocationManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SceneLocationManager.swift; sourceTree = ""; }; + B53CECF9ABC2C4785BD2C7C9DD901D74 /* SceneLocationEstimate+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "SceneLocationEstimate+Extensions.swift"; sourceTree = ""; }; + B6835AF43D315B11D80DBEB20CB41295 /* ARCL.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = ARCL.modulemap; sourceTree = ""; }; + B6EC1A7FFBC06F12DDACC575520AC537 /* LocationAnnotationNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocationAnnotationNode.swift; sourceTree = ""; }; + B7A0E4E6F76C3400D5E6906D558B8FB8 /* Pods-ARKit+CoreLocation-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ARKit+CoreLocation-resources.sh"; sourceTree = ""; }; + C08BF2189E40B1AEBDE5583CAA2C84B4 /* FloatingPoint+Radians.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "FloatingPoint+Radians.swift"; sourceTree = ""; }; + C7175760E70DBC0C749A613721BD92E3 /* SceneKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SceneKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/SceneKit.framework; sourceTree = DEVELOPER_DIR; }; + D33B939D8285598F2C92F217F8E11CC6 /* Pods-ARKit+CoreLocation-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ARKit+CoreLocation-dummy.m"; sourceTree = ""; }; + D73571F4B2281E0098DC76443D509656 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + E1B572321DFCEDF759AD8D43141BE0F2 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + E1E347CEEE5468A8FD669A4FA76E22E9 /* Pods-ARKit+CoreLocation.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ARKit+CoreLocation.debug.xcconfig"; sourceTree = ""; }; + E30F5FECFAFC63B60951A78A99A4E6AB /* ARCL-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ARCL-prefix.pch"; sourceTree = ""; }; + E6984206E65585B8B022DA93360E14DD /* BaseTypes+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "BaseTypes+Extensions.swift"; sourceTree = ""; }; + E76B312B647B2F7BD980DC2154894497 /* LocationManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = ""; }; + EAD9ABF955DC8BEDEC91957C73F04AF1 /* ARCL.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = ARCL.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 164428F8FF40D44675418C0939F965A4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 86B9BC78365017A09587892A218914F5 /* ARKit.framework in Frameworks */, + 9EDF3493B30106BF04CE6E8D58800DFB /* CoreLocation.framework in Frameworks */, + 09ACA8CC9A3368AA873194BA28444F73 /* Foundation.framework in Frameworks */, + 697460847D0DFE257FAAC2949867A056 /* MapKit.framework in Frameworks */, + 9B5798F537C91F6FA1FE92C60C9A405E /* SceneKit.framework in Frameworks */, + EEBA8F60DC05CC128BEC96056C446F00 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8A103B59D61D9FE5D31E158215EF36AF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B6F75E6B64EEE45BFA7345D8E615DEFB /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0F75DF6C7C5F002280EC53F48E80B587 /* Frameworks */ = { + isa = PBXGroup; + children = ( + D4DC2673D61F82023A75FD920E4A2251 /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3B93F1E1A417B09DC0DA25786EC8BAD2 /* Pods-ARKit+CoreLocation */ = { + isa = PBXGroup; + children = ( + 1D74A47AD7FB1304DC0FF2D215FCE1B4 /* Info.plist */, + 14020CD2FADC6360BEB98E8F9A6A0C2F /* Pods-ARKit+CoreLocation.modulemap */, + A4FF28CC89209C8800BB15011F5F0604 /* Pods-ARKit+CoreLocation-acknowledgements.markdown */, + 1DE8136DA93CFFFCEBB235D0B18D7B12 /* Pods-ARKit+CoreLocation-acknowledgements.plist */, + D33B939D8285598F2C92F217F8E11CC6 /* Pods-ARKit+CoreLocation-dummy.m */, + 9F26BAB6A40C4B6A19E747B3F459C8FF /* Pods-ARKit+CoreLocation-frameworks.sh */, + B7A0E4E6F76C3400D5E6906D558B8FB8 /* Pods-ARKit+CoreLocation-resources.sh */, + 1569D8AB75F6B4E0C4BB77FF9E53D61B /* Pods-ARKit+CoreLocation-umbrella.h */, + E1E347CEEE5468A8FD669A4FA76E22E9 /* Pods-ARKit+CoreLocation.debug.xcconfig */, + 49AF8AA326E76711FB29567A31A81D88 /* Pods-ARKit+CoreLocation.release.xcconfig */, + ); + name = "Pods-ARKit+CoreLocation"; + path = "Target Support Files/Pods-ARKit+CoreLocation"; + sourceTree = ""; + }; + 49D283F84C1FC24134F93997C7135FBC /* ARCL */ = { + isa = PBXGroup; + children = ( + 4562550955B4278CDA3943C6043CE797 /* SceneLocationView.swift */, + 0A02D1AC555B012B8650EDB84F0ACC6E /* SceneLocationView+Extensions.swift */, + 91149C058CC2C7680A542C1764BE4FB1 /* SceneLocationViewEstimateDelegate.swift */, + C8EE5A34B5520829D2FBE7088B173F55 /* Extensions */, + F3A61C43C001F0901AFC3AA98128335E /* Location Manager */, + 6F988965F21B9F58E323F9169869751E /* Nodes */, + 592496A22A950BADEAB60A9CCDCFCBB6 /* Pod */, + 5AA3100B49BBC143F6383CA1862AB9DA /* Support Files */, + ); + name = ARCL; + path = ..; + sourceTree = ""; + }; + 592496A22A950BADEAB60A9CCDCFCBB6 /* Pod */ = { + isa = PBXGroup; + children = ( + EAD9ABF955DC8BEDEC91957C73F04AF1 /* ARCL.podspec */, + E1B572321DFCEDF759AD8D43141BE0F2 /* LICENSE */, + 035356C852C901DCEDC674A281131F3D /* readme.jp.md */, + ); + name = Pod; + sourceTree = ""; + }; + 5AA3100B49BBC143F6383CA1862AB9DA /* Support Files */ = { + isa = PBXGroup; + children = ( + B6835AF43D315B11D80DBEB20CB41295 /* ARCL.modulemap */, + B1915EE8F804D88AB2BC9010EE047C95 /* ARCL.xcconfig */, + A712144F76E5E1B0D30F7BE9BADCD4EB /* ARCL-dummy.m */, + E30F5FECFAFC63B60951A78A99A4E6AB /* ARCL-prefix.pch */, + 69B96848BF644E78DD7C33D5B10BAE77 /* ARCL-umbrella.h */, + A0A555079EEFF9470F1B3705FBC9E6BC /* Info.plist */, + ); + name = "Support Files"; + path = "Pods/Target Support Files/ARCL"; + sourceTree = ""; + }; + 6F988965F21B9F58E323F9169869751E /* Nodes */ = { + isa = PBXGroup; + children = ( + B6EC1A7FFBC06F12DDACC575520AC537 /* LocationAnnotationNode.swift */, + 57A325FB8CDAF8A062982C66A07A975D /* LocationNode.swift */, + 2A955E7B9945823C9112DC45C333B65A /* PolylineNode.swift */, + ); + name = Nodes; + path = ARCL/Source/Nodes; + sourceTree = ""; + }; + 7DB346D0F39D3F0E887471402A8071AB = { + isa = PBXGroup; + children = ( + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + C52D675150BFF311C502EB6902211EB1 /* Development Pods */, + 0F75DF6C7C5F002280EC53F48E80B587 /* Frameworks */, + C2D0960AF168969E6AB57B86A4715268 /* Products */, + 97E9381D658B8FC5E881E17582CF9A82 /* Targets Support Files */, + ); + sourceTree = ""; + }; + 97E9381D658B8FC5E881E17582CF9A82 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 3B93F1E1A417B09DC0DA25786EC8BAD2 /* Pods-ARKit+CoreLocation */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + C2D0960AF168969E6AB57B86A4715268 /* Products */ = { + isa = PBXGroup; + children = ( + 2DFE09E4F7A507739F33B75C24DD1614 /* ARCL.framework */, + 1F4ECE99464F4194DF857FAFEFCCA50B /* Pods_ARKit_CoreLocation.framework */, + ); + name = Products; + sourceTree = ""; + }; + C52D675150BFF311C502EB6902211EB1 /* Development Pods */ = { + isa = PBXGroup; + children = ( + 49D283F84C1FC24134F93997C7135FBC /* ARCL */, + ); + name = "Development Pods"; + sourceTree = ""; + }; + C8EE5A34B5520829D2FBE7088B173F55 /* Extensions */ = { + isa = PBXGroup; + children = ( + E6984206E65585B8B022DA93360E14DD /* BaseTypes+Extensions.swift */, + 3F89E65049BF2BF20F88DA1FB7E0BA5F /* CGPoint+Extensions.swift */, + 3E0422089577C15C1C0FCF1242687867 /* CLLocation+Extensions.swift */, + C08BF2189E40B1AEBDE5583CAA2C84B4 /* FloatingPoint+Radians.swift */, + B0DA643017FBBAA818CB7F76131A44F8 /* SCNNode+Extensions.swift */, + 3168EB8D57DD20FD65776E6E3E14644D /* SCNVector3+Extensions.swift */, + ); + name = Extensions; + path = ARCL/Source/Extensions; + sourceTree = ""; + }; + D4DC2673D61F82023A75FD920E4A2251 /* iOS */ = { + isa = PBXGroup; + children = ( + 8448C8D3B02A33C992689E219E119203 /* ARKit.framework */, + 893DA6918C0ED7EBDEE9A9C24940A7C5 /* CoreLocation.framework */, + D73571F4B2281E0098DC76443D509656 /* Foundation.framework */, + 5C77626DC61CC820DD862D736C3A8262 /* MapKit.framework */, + C7175760E70DBC0C749A613721BD92E3 /* SceneKit.framework */, + A9C167BE81500CB0164A60D9EEFFBD72 /* UIKit.framework */, + ); + name = iOS; + sourceTree = ""; + }; + F3A61C43C001F0901AFC3AA98128335E /* Location Manager */ = { + isa = PBXGroup; + children = ( + E76B312B647B2F7BD980DC2154894497 /* LocationManager.swift */, + 0CD17C8FFE8E07C175696087F92B2566 /* SceneLocationEstimate.swift */, + B53CECF9ABC2C4785BD2C7C9DD901D74 /* SceneLocationEstimate+Extensions.swift */, + B19C516D9B979CDA8009D52F8EFE4351 /* SceneLocationManager.swift */, + ); + name = "Location Manager"; + path = "ARCL/Source/Location Manager"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4F22C9818191093F398F142D406BDD7D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C91A8DA418831E877CCA779333BCF0D /* Pods-ARKit+CoreLocation-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F73C125FE4ECBBC46E7CD9F0DB0EBC5D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DF44D6C8FB62B1F7675ABDD11CF2559 /* ARCL-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + A4134F75EC58E09F3C60888E4C5EC4A3 /* ARCL */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29B97F4322165800FB812304083E7286 /* Build configuration list for PBXNativeTarget "ARCL" */; + buildPhases = ( + F73C125FE4ECBBC46E7CD9F0DB0EBC5D /* Headers */, + F4F16C64A6F65CF94D43BB1512F92C72 /* Sources */, + 164428F8FF40D44675418C0939F965A4 /* Frameworks */, + B6CA4E1BFF39F63A3475EF6707CB1B6C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ARCL; + productName = ARCL; + productReference = 2DFE09E4F7A507739F33B75C24DD1614 /* ARCL.framework */; + productType = "com.apple.product-type.framework"; + }; + B2D014144CFE84BA0AEDA13C067037D6 /* Pods-ARKit+CoreLocation */ = { + isa = PBXNativeTarget; + buildConfigurationList = 55BD1EC0814D5A040E187CFF2C6725FE /* Build configuration list for PBXNativeTarget "Pods-ARKit+CoreLocation" */; + buildPhases = ( + 4F22C9818191093F398F142D406BDD7D /* Headers */, + 1BF5F5D5A68260DD2212A12A393BE704 /* Sources */, + 8A103B59D61D9FE5D31E158215EF36AF /* Frameworks */, + F559FA46A914970AD713C9E8393E99D1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 6DE3B9E0C21D660C09D8923193B3DBA3 /* PBXTargetDependency */, + ); + name = "Pods-ARKit+CoreLocation"; + productName = "Pods-ARKit+CoreLocation"; + productReference = 1F4ECE99464F4194DF857FAFEFCCA50B /* Pods_ARKit_CoreLocation.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0930; + LastUpgradeCheck = 0930; + }; + buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7DB346D0F39D3F0E887471402A8071AB; + productRefGroup = C2D0960AF168969E6AB57B86A4715268 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A4134F75EC58E09F3C60888E4C5EC4A3 /* ARCL */, + B2D014144CFE84BA0AEDA13C067037D6 /* Pods-ARKit+CoreLocation */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + B6CA4E1BFF39F63A3475EF6707CB1B6C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F559FA46A914970AD713C9E8393E99D1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1BF5F5D5A68260DD2212A12A393BE704 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5B4C10A00978AE1C3399AA575EE1E268 /* Pods-ARKit+CoreLocation-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F4F16C64A6F65CF94D43BB1512F92C72 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 48938EB4F29DBE6E7F35BF3EE0FB5F32 /* ARCL-dummy.m in Sources */, + F561B76D6E66E38CA6DA638326F7FFE6 /* BaseTypes+Extensions.swift in Sources */, + B47A38E2D38C140007442C9C6AD08A31 /* CGPoint+Extensions.swift in Sources */, + 3DE089ADC309F48F08141FCF1490A3FB /* CLLocation+Extensions.swift in Sources */, + 9BCEAE87FDF2D9FB81641D19695DA15D /* FloatingPoint+Radians.swift in Sources */, + E86F59767C2B326586FFEA1C9AD66D61 /* LocationAnnotationNode.swift in Sources */, + 599CE3641B291140A8FB9E5D603F5D00 /* LocationManager.swift in Sources */, + FA93CA2766EFE77410BE4EF82B791E47 /* LocationNode.swift in Sources */, + B3AFFFFE4556B049893E062C5D766203 /* PolylineNode.swift in Sources */, + 63D0A822C50464A12515A4A7C17391B6 /* SceneLocationEstimate+Extensions.swift in Sources */, + F0B85ABCD119C994FFEF7DAC02ADD35A /* SceneLocationEstimate.swift in Sources */, + 6A07D0DE2872B0D0531C9D920E4BB114 /* SceneLocationManager.swift in Sources */, + E3AFA301454D38DB58F9FA5AA101928D /* SceneLocationView+Extensions.swift in Sources */, + DA404C101804320A8214E463E334E308 /* SceneLocationView.swift in Sources */, + B536EBFA2C27782AFB6C859CD6B909CE /* SceneLocationViewEstimateDelegate.swift in Sources */, + 14A6A686C90AFFDA970F45704840C229 /* SCNNode+Extensions.swift in Sources */, + B5BACEB22A43E845BBE0E822ADD3E0F1 /* SCNVector3+Extensions.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 6DE3B9E0C21D660C09D8923193B3DBA3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ARCL; + target = A4134F75EC58E09F3C60888E4C5EC4A3 /* ARCL */; + targetProxy = E927894478333674B728678135340438 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0D25CF74E10E547FBA27C5F490BA0D84 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B1915EE8F804D88AB2BC9010EE047C95 /* ARCL.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ARCL/ARCL-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ARCL/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ARCL/ARCL.modulemap"; + PRODUCT_NAME = ARCL; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 5CA3B0FFD006EF1B905073CB234C7A5F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 49AF8AA326E76711FB29567A31A81D88 /* Pods-ARKit+CoreLocation.release.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-ARKit+CoreLocation/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_ARKit_CoreLocation; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 82C03B78DD2C262968679FC283A1A971 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B1915EE8F804D88AB2BC9010EE047C95 /* ARCL.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ARCL/ARCL-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ARCL/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ARCL/ARCL.modulemap"; + PRODUCT_NAME = ARCL; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 83230E6D706408FBF97AC0852934EE53 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E1E347CEEE5468A8FD669A4FA76E22E9 /* Pods-ARKit+CoreLocation.debug.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-ARKit+CoreLocation/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_ARKit_CoreLocation; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 9CBE43BEF079F20EF85ABF6900142B11 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 4.2; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + FE4017C6988784A274FF93B4FF612EC6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29B97F4322165800FB812304083E7286 /* Build configuration list for PBXNativeTarget "ARCL" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 82C03B78DD2C262968679FC283A1A971 /* Debug */, + 0D25CF74E10E547FBA27C5F490BA0D84 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FE4017C6988784A274FF93B4FF612EC6 /* Debug */, + 9CBE43BEF079F20EF85ABF6900142B11 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 55BD1EC0814D5A040E187CFF2C6725FE /* Build configuration list for PBXNativeTarget "Pods-ARKit+CoreLocation" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83230E6D706408FBF97AC0852934EE53 /* Debug */, + 5CA3B0FFD006EF1B905073CB234C7A5F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; +} diff --git a/Pods/Target Support Files/ARCL/ARCL-dummy.m b/Pods/Target Support Files/ARCL/ARCL-dummy.m new file mode 100644 index 00000000..dffeaa90 --- /dev/null +++ b/Pods/Target Support Files/ARCL/ARCL-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_ARCL : NSObject +@end +@implementation PodsDummy_ARCL +@end diff --git a/Pods/Target Support Files/ARCL/ARCL-prefix.pch b/Pods/Target Support Files/ARCL/ARCL-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Pods/Target Support Files/ARCL/ARCL-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Pods/Target Support Files/ARCL/ARCL-umbrella.h b/Pods/Target Support Files/ARCL/ARCL-umbrella.h new file mode 100644 index 00000000..72ab46c9 --- /dev/null +++ b/Pods/Target Support Files/ARCL/ARCL-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double ARCLVersionNumber; +FOUNDATION_EXPORT const unsigned char ARCLVersionString[]; + diff --git a/Pods/Target Support Files/ARCL/ARCL.modulemap b/Pods/Target Support Files/ARCL/ARCL.modulemap new file mode 100644 index 00000000..56addf02 --- /dev/null +++ b/Pods/Target Support Files/ARCL/ARCL.modulemap @@ -0,0 +1,6 @@ +framework module ARCL { + umbrella header "ARCL-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/ARCL/ARCL.xcconfig b/Pods/Target Support Files/ARCL/ARCL.xcconfig new file mode 100644 index 00000000..2e10e192 --- /dev/null +++ b/Pods/Target Support Files/ARCL/ARCL.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ARCL +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = -framework "ARKit" -framework "CoreLocation" -framework "Foundation" -framework "MapKit" -framework "SceneKit" -framework "UIKit" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" "-suppress-warnings" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/.. +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Pods/Target Support Files/ARCL/Info.plist b/Pods/Target Support Files/ARCL/Info.plist new file mode 100644 index 00000000..2660a939 --- /dev/null +++ b/Pods/Target Support Files/ARCL/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.4 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Info.plist b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Info.plist new file mode 100644 index 00000000..2243fe6e --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-acknowledgements.markdown b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-acknowledgements.markdown new file mode 100644 index 00000000..74c3b20c --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-acknowledgements.markdown @@ -0,0 +1,27 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## ARCL + +MIT License + +Copyright (c) 2017 Project Dent (https://ProjectDent.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +Generated by CocoaPods - https://cocoapods.org diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-acknowledgements.plist b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-acknowledgements.plist new file mode 100644 index 00000000..b896f3ea --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-acknowledgements.plist @@ -0,0 +1,59 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + MIT License + +Copyright (c) 2017 Project Dent (https://ProjectDent.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + License + MIT + Title + ARCL + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-dummy.m b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-dummy.m new file mode 100644 index 00000000..74a73896 --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_ARKit_CoreLocation : NSObject +@end +@implementation PodsDummy_Pods_ARKit_CoreLocation +@end diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-frameworks.sh b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-frameworks.sh new file mode 100755 index 00000000..2e4f30d6 --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-frameworks.sh @@ -0,0 +1,144 @@ +#!/bin/sh +set -e + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ARCL/ARCL.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ARCL/ARCL.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-resources.sh b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-resources.sh new file mode 100755 index 00000000..a7df4405 --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-resources.sh @@ -0,0 +1,106 @@ +#!/bin/sh +set -e + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-umbrella.h b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-umbrella.h new file mode 100644 index 00000000..0e3d67a6 --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_ARKit_CoreLocationVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_ARKit_CoreLocationVersionString[]; + diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.debug.xcconfig b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.debug.xcconfig new file mode 100644 index 00000000..db53176b --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.debug.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ARCL" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ARCL/ARCL.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ARCL" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.modulemap b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.modulemap new file mode 100644 index 00000000..f072a302 --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.modulemap @@ -0,0 +1,6 @@ +framework module Pods_ARKit_CoreLocation { + umbrella header "Pods-ARKit+CoreLocation-umbrella.h" + + export * + module * { export * } +} diff --git a/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.release.xcconfig b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.release.xcconfig new file mode 100644 index 00000000..db53176b --- /dev/null +++ b/Pods/Target Support Files/Pods-ARKit+CoreLocation/Pods-ARKit+CoreLocation.release.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ARCL" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ARCL/ARCL.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "ARCL" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/changelog.md b/changelog.md new file mode 100644 index 00000000..b2587472 --- /dev/null +++ b/changelog.md @@ -0,0 +1,5 @@ +# Changelog + +- [PR #59 - Routing / Polylines](https://github.com/ProjectDent/ARKit-CoreLocation/pull/159) + - Adds the ability to take an array of `MKRoute` objects and render it as a route in AR (similar to the demo gif on the README) + - Updates the demo app to allow you to demonstrate this capability