hang animation until focus completes

This commit is contained in:
Michael Kirk 2019-12-12 19:23:54 -08:00
parent dcdce02066
commit ee5f86cbf4
4 changed files with 75 additions and 4 deletions

View File

@ -166,6 +166,10 @@ extension AttachmentFormatPickerView: PhotoCaptureDelegate {
func endCaptureButtonAnimation(_ duration: TimeInterval) {
owsFailDebug("\(#function) should never be called")
}
func photoCapture(_ photoCapture: PhotoCapture, didCompleteFocusingAtPoint focusPoint: CGPoint) {
owsFailDebug("\(#function) should never be called")
}
}
// MARK: - UICollectionViewDataSource

View File

@ -13,7 +13,7 @@ protocol PhotoCaptureDelegate: AnyObject {
func photoCapture(_ photoCapture: PhotoCapture, didFinishProcessingAttachment attachment: SignalAttachment)
func photoCapture(_ photoCapture: PhotoCapture, processingDidError error: Error)
// MARK: Video
// MARK: Movie
func photoCaptureDidBeginMovie(_ photoCapture: PhotoCapture)
func photoCaptureDidCompleteMovie(_ photoCapture: PhotoCapture)
@ -28,6 +28,9 @@ protocol PhotoCaptureDelegate: AnyObject {
func beginCaptureButtonAnimation(_ duration: TimeInterval)
func endCaptureButtonAnimation(_ duration: TimeInterval)
func photoCapture(_ photoCapture: PhotoCapture, didCompleteFocusingAtPoint focusPoint: CGPoint)
}
@objc
@ -61,11 +64,25 @@ class PhotoCapture: NSObject {
private let recordingAudioActivity = AudioActivity(audioDescription: "PhotoCapture", behavior: .playAndRecord)
var focusObservation: NSKeyValueObservation?
override init() {
self.session = AVCaptureSession()
self.captureOutput = CaptureOutput()
}
func didCompleteFocusing() {
Logger.debug("")
guard let currentCaptureInput = currentCaptureInput else {
return
}
let focusPoint = currentCaptureInput.device.focusPointOfInterest
DispatchQueue.main.async {
self.delegate?.photoCapture(self, didCompleteFocusingAtPoint: focusPoint)
}
}
// MARK: - Dependencies
private var audioSession: OWSAudioSession {
@ -265,6 +282,26 @@ class PhotoCapture: NSObject {
session.addInput(newInput)
NotificationCenter.default.addObserver(self, selector: #selector(subjectAreaDidChange), name: .AVCaptureDeviceSubjectAreaDidChange, object: newInput.device)
if let focusObservation = focusObservation {
focusObservation.invalidate()
}
self.focusObservation = newInput.observe(\.device.isAdjustingFocus,
options: [.old, .new]) { [weak self] _, change in
guard let self = self else { return }
guard let oldValue = change.oldValue else {
return
}
guard let newValue = change.newValue else {
return
}
if oldValue == true && newValue == false {
self.didCompleteFocusing()
}
}
currentCaptureInput = newInput
resetFocusAndExposure()

View File

@ -362,13 +362,29 @@ class PhotoCaptureViewController: OWSViewController {
func didTapFocusExpose(tapGesture: UITapGestureRecognizer) {
let viewLocation = tapGesture.location(in: view)
let devicePoint = previewView.previewLayer.captureDevicePointConverted(fromLayerPoint: viewLocation)
currentlyFocusingAtPoint = devicePoint
tapToFocusView.center = viewLocation
tapToFocusView.play()
startFocusAnimation()
photoCapture.focus(with: .autoFocus, exposureMode: .autoExpose, at: devicePoint, monitorSubjectAreaChange: true)
}
// MARK: - Focus Animations
func startFocusAnimation() {
tapToFocusView.stop()
tapToFocusView.play(fromProgress: 0.0, toProgress: 0.9)
}
var currentlyFocusingAtPoint = CGPoint(x: 0.5, y: 0.5)
func completeFocusAnimation(forFocusPoint focusPoint: CGPoint) {
guard currentlyFocusingAtPoint.within(0.005, of: focusPoint) else {
Logger.verbose("focus completed for obsolete focus point. User has refocused on.")
return
}
tapToFocusView.play(toProgress: 1.0)
}
// MARK: - Orientation
// MARK: -
@ -543,6 +559,10 @@ extension PhotoCaptureViewController: PhotoCaptureDelegate {
photoCapture.updateVideoPreviewConnection(toOrientation: orientation)
}
}
func photoCapture(_ photoCapture: PhotoCapture, didCompleteFocusingAtPoint focusPoint: CGPoint) {
completeFocusAnimation(forFocusPoint: focusPoint)
}
}
// MARK: - Views

View File

@ -342,6 +342,16 @@ public extension CGPoint {
return sqrt(x * x + y * y)
}
@inlinable
func distance(_ other: CGPoint) -> CGFloat {
return sqrt(pow(x - other.x, 2) + pow(y - other.y, 2))
}
@inlinable
func within(_ delta: CGFloat, of other: CGPoint) -> Bool {
return distance(other) <= delta
}
static let unit: CGPoint = CGPoint(x: 1.0, y: 1.0)
static let unitMidpoint: CGPoint = CGPoint(x: 0.5, y: 0.5)