From ca24241d01bf5b59b1c847f65427c823fc6ff9e8 Mon Sep 17 00:00:00 2001 From: Tomasz Kurylik Date: Tue, 19 Nov 2024 20:24:44 +0100 Subject: [PATCH 1/8] 1 --- Sources/Internal/Extensions/Bundle++.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sources/Internal/Extensions/Bundle++.swift b/Sources/Internal/Extensions/Bundle++.swift index 3b905f4db..b09c5b8ee 100644 --- a/Sources/Internal/Extensions/Bundle++.swift +++ b/Sources/Internal/Extensions/Bundle++.swift @@ -12,5 +12,10 @@ import Foundation extension Bundle { - static var mijick: Bundle { .init(identifier: "MijickCameraView-MijickCameraView-resources") ?? .main } + static var mijick: Bundle { + .allBundles + .compactMap { $0.resourceURL?.appendingPathComponent("MijickCameraView_MijickCameraView", isDirectory: false).appendingPathExtension("bundle") } + .compactMap { Bundle(url: $0) } + .first ?? .main + } } From 925fc6ab9928d218a5a463d7485170033c122a5a Mon Sep 17 00:00:00 2001 From: Tomasz Kurylik Date: Thu, 21 Nov 2024 12:45:55 +0100 Subject: [PATCH 2/8] 1 --- Sources/Internal/Managers/CameraManager.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/Internal/Managers/CameraManager.swift b/Sources/Internal/Managers/CameraManager.swift index a04d2ca2b..06bd76c36 100644 --- a/Sources/Internal/Managers/CameraManager.swift +++ b/Sources/Internal/Managers/CameraManager.swift @@ -398,7 +398,7 @@ private extension CameraManager { animateCameraFocusView() }} func setCameraFocus(_ touchPoint: CGPoint, _ device: AVCaptureDevice) throws { - let focusPoint = cameraLayer.captureDevicePointConverted(fromLayerPoint: touchPoint) + let focusPoint = convertTouchPointToFocusPoint(touchPoint) try configureCameraFocus(focusPoint, device) } } @@ -417,6 +417,10 @@ private extension CameraManager { UIView.animate(withDuration: 0.5, delay: 3.5) { [self] in cameraFocusView.alpha = 0 } } } + func convertTouchPointToFocusPoint(_ touchPoint: CGPoint) -> CGPoint { .init( + x: touchPoint.x / cameraView.frame.width, + y: touchPoint.y / cameraView.frame.height + )} func configureCameraFocus(_ focusPoint: CGPoint, _ device: AVCaptureDevice) throws { try withLockingDeviceForConfiguration(device) { device in setFocusPointOfInterest(focusPoint, device) setExposurePointOfInterest(focusPoint, device) From 776174a944c8e04ece81b16744b907d467fc990e Mon Sep 17 00:00:00 2001 From: Tomasz Kurylik Date: Thu, 21 Nov 2024 13:09:16 +0100 Subject: [PATCH 3/8] 1 --- Sources/Internal/Managers/CameraManager.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Internal/Managers/CameraManager.swift b/Sources/Internal/Managers/CameraManager.swift index 06bd76c36..2ae83bc81 100644 --- a/Sources/Internal/Managers/CameraManager.swift +++ b/Sources/Internal/Managers/CameraManager.swift @@ -418,8 +418,8 @@ private extension CameraManager { } } func convertTouchPointToFocusPoint(_ touchPoint: CGPoint) -> CGPoint { .init( - x: touchPoint.x / cameraView.frame.width, - y: touchPoint.y / cameraView.frame.height + x: touchPoint.y / cameraView.frame.height, + y: 1 - touchPoint.x / cameraView.frame.width )} func configureCameraFocus(_ focusPoint: CGPoint, _ device: AVCaptureDevice) throws { try withLockingDeviceForConfiguration(device) { device in setFocusPointOfInterest(focusPoint, device) From 813bd50dc6f43c23442345e7b3b261035631196e Mon Sep 17 00:00:00 2001 From: Tomasz Kurylik Date: Thu, 21 Nov 2024 18:36:23 +0100 Subject: [PATCH 4/8] 1 --- .../Views/Main/CameraInputBridgeView.swift | 86 +++++++++---------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/Sources/Internal/Views/Main/CameraInputBridgeView.swift b/Sources/Internal/Views/Main/CameraInputBridgeView.swift index dcf0dc1ac..e3185a44c 100644 --- a/Sources/Internal/Views/Main/CameraInputBridgeView.swift +++ b/Sources/Internal/Views/Main/CameraInputBridgeView.swift @@ -11,84 +11,80 @@ import SwiftUI -struct CameraInputBridgeView: UIViewRepresentable { +struct CameraInputBridgeView { let cameraManager: CameraManager - private var inputView: UICameraInputView = .init() + let inputView: UIView = .init() init(_ cameraManager: CameraManager) { self.cameraManager = cameraManager } } -extension CameraInputBridgeView { - func makeUIView(context: Context) -> some UIView { - inputView.cameraManager = cameraManager - return inputView.view - } - func updateUIView(_ uiView: UIViewType, context: Context) {} -} -extension CameraInputBridgeView: Equatable { - static func == (lhs: Self, rhs: Self) -> Bool { true } -} -// MARK: - UIViewController -fileprivate class UICameraInputView: UIViewController { - var cameraManager: CameraManager! +// MARK: - PROTOCOLS CONFORMANCE - override func viewDidLoad() { - super.viewDidLoad() +// MARK: UIViewRepresentable +extension CameraInputBridgeView: UIViewRepresentable { + func makeUIView(context: Context) -> some UIView { setupCameraManager() - setupTapGesture() - setupPinchGesture() - } - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - cameraManager.fixCameraRotation() + setupTapGesture(context) + setupPinchGesture(context) + return inputView } + func updateUIView(_ uiView: UIViewType, context: Context) {} + func makeCoordinator() -> Coordinator { .init(self) } } - -// MARK: - Setup -private extension UICameraInputView { +private extension CameraInputBridgeView { func setupCameraManager() { - cameraManager.setup(in: view) + cameraManager.setup(in: inputView) } - func setupTapGesture() { - let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture)) - view.addGestureRecognizer(tapRecognizer) + func setupTapGesture(_ context: Context) { + let tapRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handleTapGesture)) + inputView.addGestureRecognizer(tapRecognizer) } - func setupPinchGesture() { - let pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchGesture)) - view.addGestureRecognizer(pinchRecognizer) + func setupPinchGesture(_ context: Context) { + let pinchRecognizer = UIPinchGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handlePinchGesture)) + inputView.addGestureRecognizer(pinchRecognizer) } } -// MARK: - Gestures +// MARK: Equatable +extension CameraInputBridgeView: Equatable { + static func ==(lhs: Self, rhs: Self) -> Bool { true } +} + + +// MARK: - LOGIC +extension CameraInputBridgeView { class Coordinator: NSObject { + let parent: CameraInputBridgeView + + init(_ parent: CameraInputBridgeView) { self.parent = parent } +}} -// MARK: Tap -private extension UICameraInputView { +// MARK: On Tap +extension CameraInputBridgeView.Coordinator { @objc func handleTapGesture(_ tap: UITapGestureRecognizer) { - let touchPoint = tap.location(in: view) + let touchPoint = tap.location(in: parent.inputView) setCameraFocus(touchPoint) } } -private extension UICameraInputView { +private extension CameraInputBridgeView.Coordinator { func setCameraFocus(_ touchPoint: CGPoint) { - do { try cameraManager.setCameraFocus(touchPoint) } + do { try parent.cameraManager.setCameraFocus(touchPoint) } catch {} } } -// MARK: Pinch -private extension UICameraInputView { +// MARK: On Pinch +extension CameraInputBridgeView.Coordinator { @objc func handlePinchGesture(_ pinch: UIPinchGestureRecognizer) { if pinch.state == .changed { - let desiredZoomFactor = cameraManager.attributes.zoomFactor + atan2(pinch.velocity, 33) + let desiredZoomFactor = parent.cameraManager.attributes.zoomFactor + atan2(pinch.velocity, 33) changeZoomFactor(desiredZoomFactor) }} } -private extension UICameraInputView { +private extension CameraInputBridgeView.Coordinator { func changeZoomFactor(_ desiredZoomFactor: CGFloat) { - do { try cameraManager.changeZoomFactor(desiredZoomFactor) } + do { try parent.cameraManager.changeZoomFactor(desiredZoomFactor) } catch {} } } From a6f6a592ef2eb71130404673b02ba280e324edab Mon Sep 17 00:00:00 2001 From: Tomasz Kurylik Date: Thu, 21 Nov 2024 18:39:47 +0100 Subject: [PATCH 5/8] 1 --- Sources/Internal/Managers/CameraManager.swift | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Sources/Internal/Managers/CameraManager.swift b/Sources/Internal/Managers/CameraManager.swift index 2ae83bc81..7acefa4a3 100644 --- a/Sources/Internal/Managers/CameraManager.swift +++ b/Sources/Internal/Managers/CameraManager.swift @@ -305,18 +305,6 @@ extension CameraManager { } } -// MARK: - Camera Rotation -extension CameraManager { - func fixCameraRotation() { if !orientationLocked { - redrawGrid() - }} -} -private extension CameraManager { - func redrawGrid() { - cameraGridView?.draw(.zero) - } -} - // MARK: - Changing Output Type extension CameraManager { func changeOutputType(_ newOutputType: CameraOutputType) throws { if newOutputType != attributes.outputType && !isChanging { @@ -755,6 +743,7 @@ private extension CameraManager { updateDeviceOrientation(newDeviceOrientation) updateUserBlockedScreenRotation() updateFrameOrientation() + redrawGrid() }} } private extension CameraManager { @@ -776,6 +765,9 @@ private extension CameraManager { let newFrameOrientation = getNewFrameOrientation(orientationLocked ? .portrait : UIDevice.current.orientation) updateFrameOrientation(newFrameOrientation) }} + func redrawGrid() { if !orientationLocked { + cameraGridView?.draw(.zero) + }} } private extension CameraManager { func getNewUserBlockedScreenRotation() -> Bool { switch attributes.deviceOrientation.rawValue == UIDevice.current.orientation.rawValue { From a968ab2293c24e3f787fefb81ff66b7a1699fef4 Mon Sep 17 00:00:00 2001 From: Tomasz Kurylik Date: Thu, 21 Nov 2024 18:46:39 +0100 Subject: [PATCH 6/8] 1 --- .../Views/Main/CameraInputBridgeView.swift | 38 +++++++------------ .../View Protocols/Public+MCameraView.swift | 2 +- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/Sources/Internal/Views/Main/CameraInputBridgeView.swift b/Sources/Internal/Views/Main/CameraInputBridgeView.swift index e3185a44c..152def2fb 100644 --- a/Sources/Internal/Views/Main/CameraInputBridgeView.swift +++ b/Sources/Internal/Views/Main/CameraInputBridgeView.swift @@ -14,8 +14,6 @@ import SwiftUI struct CameraInputBridgeView { let cameraManager: CameraManager let inputView: UIView = .init() - - init(_ cameraManager: CameraManager) { self.cameraManager = cameraManager } } @@ -39,11 +37,11 @@ private extension CameraInputBridgeView { cameraManager.setup(in: inputView) } func setupTapGesture(_ context: Context) { - let tapRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handleTapGesture)) + let tapRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.onTapGesture)) inputView.addGestureRecognizer(tapRecognizer) } func setupPinchGesture(_ context: Context) { - let pinchRecognizer = UIPinchGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handlePinchGesture)) + let pinchRecognizer = UIPinchGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.onPinchGesture)) inputView.addGestureRecognizer(pinchRecognizer) } } @@ -55,36 +53,26 @@ extension CameraInputBridgeView: Equatable { // MARK: - LOGIC -extension CameraInputBridgeView { class Coordinator: NSObject { +extension CameraInputBridgeView { class Coordinator: NSObject { init(_ parent: CameraInputBridgeView) { self.parent = parent } let parent: CameraInputBridgeView - - init(_ parent: CameraInputBridgeView) { self.parent = parent } }} // MARK: On Tap extension CameraInputBridgeView.Coordinator { - @objc func handleTapGesture(_ tap: UITapGestureRecognizer) { - let touchPoint = tap.location(in: parent.inputView) - setCameraFocus(touchPoint) - } -} -private extension CameraInputBridgeView.Coordinator { - func setCameraFocus(_ touchPoint: CGPoint) { - do { try parent.cameraManager.setCameraFocus(touchPoint) } - catch {} + @objc func onTapGesture(_ tap: UITapGestureRecognizer) { + do { + let touchPoint = tap.location(in: parent.inputView) + try parent.cameraManager.setCameraFocus(touchPoint) + } catch {} } } // MARK: On Pinch extension CameraInputBridgeView.Coordinator { - @objc func handlePinchGesture(_ pinch: UIPinchGestureRecognizer) { if pinch.state == .changed { - let desiredZoomFactor = parent.cameraManager.attributes.zoomFactor + atan2(pinch.velocity, 33) - changeZoomFactor(desiredZoomFactor) + @objc func onPinchGesture(_ pinch: UIPinchGestureRecognizer) { if pinch.state == .changed { + do { + let desiredZoomFactor = parent.cameraManager.attributes.zoomFactor + atan2(pinch.velocity, 33) + try parent.cameraManager.changeZoomFactor(desiredZoomFactor) + } catch {} }} } -private extension CameraInputBridgeView.Coordinator { - func changeZoomFactor(_ desiredZoomFactor: CGFloat) { - do { try parent.cameraManager.changeZoomFactor(desiredZoomFactor) } - catch {} - } -} diff --git a/Sources/Public/View Protocols/Public+MCameraView.swift b/Sources/Public/View Protocols/Public+MCameraView.swift index ad71ccf8f..4e38deabf 100644 --- a/Sources/Public/View Protocols/Public+MCameraView.swift +++ b/Sources/Public/View Protocols/Public+MCameraView.swift @@ -21,7 +21,7 @@ public protocol MCameraView: View { // MARK: - Use-only View Methods public extension MCameraView { - func createCameraView() -> some View { CameraInputBridgeView(cameraManager).equatable() } + func createCameraView() -> some View { CameraInputBridgeView(cameraManager: cameraManager).equatable() } } // MARK: - Use-only Logic Methods From e8412cfe78bd5ab4be62ce41727990337a5e0e89 Mon Sep 17 00:00:00 2001 From: Tomasz Kurylik Date: Thu, 21 Nov 2024 18:50:30 +0100 Subject: [PATCH 7/8] 1 --- Sources/Internal/Managers/CameraManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Internal/Managers/CameraManager.swift b/Sources/Internal/Managers/CameraManager.swift index 7acefa4a3..73e4ea23e 100644 --- a/Sources/Internal/Managers/CameraManager.swift +++ b/Sources/Internal/Managers/CameraManager.swift @@ -117,7 +117,7 @@ private extension CameraManager { cameraMetalView = nil cameraGridView = nil cameraBlurView = nil - cameraFocusView = .init() + cameraFocusView = .create(image: .iconCrosshair, tintColor: .yellow, size: 92) motionManager = .init() } func removeObservers() { From f57f9bbd18bc2c8ff4ec5af58c79ed974de0e10b Mon Sep 17 00:00:00 2001 From: Tomasz Kurylik Date: Fri, 22 Nov 2024 03:02:14 +0100 Subject: [PATCH 8/8] 1 --- .../AVCaptureVideoOrientation++.swift | 11 +++++++++++ Sources/Internal/Managers/CameraManager.swift | 17 ++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Sources/Internal/Extensions/AVCaptureVideoOrientation++.swift b/Sources/Internal/Extensions/AVCaptureVideoOrientation++.swift index 8a1dc7233..a0af22951 100644 --- a/Sources/Internal/Extensions/AVCaptureVideoOrientation++.swift +++ b/Sources/Internal/Extensions/AVCaptureVideoOrientation++.swift @@ -33,3 +33,14 @@ extension AVCaptureVideoOrientation { default: .up }} } + +// MARK: - To UIDeviceOrientation +extension AVCaptureVideoOrientation { + func toDeviceOrientation() -> UIDeviceOrientation { switch self { + case .portrait: .portrait + case .portraitUpsideDown: .portraitUpsideDown + case .landscapeLeft: .landscapeLeft + case .landscapeRight: .landscapeRight + default: .portrait + }} +} diff --git a/Sources/Internal/Managers/CameraManager.swift b/Sources/Internal/Managers/CameraManager.swift index 73e4ea23e..89fefcb9e 100644 --- a/Sources/Internal/Managers/CameraManager.swift +++ b/Sources/Internal/Managers/CameraManager.swift @@ -676,7 +676,22 @@ private extension CameraManager { extension CameraManager: AVCapturePhotoCaptureDelegate { public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: (any Swift.Error)?) { - attributes.capturedMedia = .create(imageData: photo, orientation: frameOrientation, filters: attributes.cameraFilters) + attributes.capturedMedia = .create(imageData: photo, orientation: fixedFrameOrientation(), filters: attributes.cameraFilters) + } +} +private extension CameraManager { + func fixedFrameOrientation() -> CGImagePropertyOrientation { guard UIDevice.current.orientation != attributes.deviceOrientation.toDeviceOrientation() else { return frameOrientation } + return switch (attributes.deviceOrientation, attributes.cameraPosition) { + case (.portrait, .front): .left + case (.portrait, .back): .right + case (.landscapeLeft, .back): .down + case (.landscapeRight, .back): .up + case (.landscapeLeft, .front) where attributes.mirrorOutput: .up + case (.landscapeLeft, .front): .upMirrored + case (.landscapeRight, .front) where attributes.mirrorOutput: .down + case (.landscapeRight, .front): .downMirrored + default: .right + } } }