MijickCamera/Sources/Public/UI/Public+UI+MCameraScreen.swift

244 lines
8.5 KiB
Swift
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Public+UI+MCameraScreen.swift of MijickCamera
//
// Created by Tomasz Kurylik. Sending from Kraków!
// - Mail: tomasz.kurylik@mijick.com
// - GitHub: https://github.com/FulcrumOne
// - Medium: https://medium.com/@mijick
//
// Copyright ©2024 Mijick. All rights reserved.
import SwiftUI
import AVFoundation
import MijickTimer
/**
Screen that displays the camera view and manages camera actions.
- important: A view conforming to **MCameraScreen** has to be passed directly to ``MCamera``. See ``MCamera/setCameraScreen(_:)`` for more details.
## Usage
```swift
struct ContentView: View {
var body: some View {
MCamera()
.setCameraScreen(CustomCameraErrorScreen.init)
// MUST BE CALLED!
.startSession()
}
}
// MARK: Custom Camera Screen
struct CustomCameraScreen: MCameraScreen {
@ObservedObject var cameraManager: CameraManager
let namespace: Namespace.ID
let closeMCameraAction: () -> ()
var body: some View {
VStack(spacing: 0) {
createNavigationBar()
createCameraOutputView()
createCaptureButton()
}
}
}
private extension CustomCameraScreen {
func createNavigationBar() -> some View {
Text("This is a Custom Camera View")
.padding(.top, 12)
.padding(.bottom, 12)
}
func createCaptureButton() -> some View {
Button(action: captureOutput) { Text("Click to capture") }
.padding(.top, 12)
.padding(.bottom, 12)
}
}
```
*/
public protocol MCameraScreen: View {
var cameraManager: CameraManager { get }
var namespace: Namespace.ID { get }
var closeMCameraAction: () -> () { get }
}
// MARK: Methods
public extension MCameraScreen {
/**
View that displays the camera output.
## Usage
```swift
struct CustomCameraScreen: MCameraScreen {
@ObservedObject var cameraManager: CameraManager
let namespace: Namespace.ID
let closeMCameraAction: () -> ()
var body: some View {
(...)
createCameraOutputView()
(...)
}
}
```
*/
func createCameraOutputView() -> some View { CameraBridgeView(cameraManager: cameraManager).equatable() }
}
public extension MCameraScreen {
/**
Capture the current camera output.
The output type depends on what ``cameraOutputType`` is set to.
*/
func captureOutput() { cameraManager.captureOutput() }
/**
Set the output type of the camera.
For available options, please refer to the ``CameraOutputType`` documentation.
*/
func setOutputType(_ outputType: CameraOutputType) { cameraManager.setOutputType(outputType) }
/**
Set the camera position.
For available options, please refer to the ``CameraPosition`` documentation.
- note: If the selected camera position is not available, the camera will not be changed.
*/
func setCameraPosition(_ cameraPosition: CameraPosition) async throws { try await cameraManager.setCameraPosition(cameraPosition) }
/**
Set the zoom factor of the camera.
- note: If the zoom factor is out of bounds, it will be set to the closest available value.
*/
func setZoomFactor(_ zoomFactor: CGFloat) throws { try cameraManager.setCameraZoomFactor(zoomFactor) }
/**
Set the flash mode of the camera.
For available options, please refer to the ``CameraFlashMode`` documentation.
- note: If the selected flash mode is not available, the flash mode will not be changed.
*/
func setFlashMode(_ flashMode: CameraFlashMode) { cameraManager.setFlashMode(flashMode) }
/**
Set the screen flash color for front camera captures.
When taking photos with the front camera with flash enabled, the screen will illuminate
with this color to light up the subject's face. If not set, defaults to white.
- parameter color: The UIColor to use for screen flash illumination. Pass nil for white.
*/
func setScreenFlashColor(_ color: UIColor?) { cameraManager.setScreenFlashColor(color) }
/**
Set the light mode of the camera.
For available options, please refer to the ``CameraLightMode`` documentation.
- note: If the selected light mode is not available, the light mode will not be changed.
*/
func setLightMode(_ lightMode: CameraLightMode) throws { try cameraManager.setLightMode(lightMode) }
/**
Set the camera resolution.
- important: Changing the resolution may affect the maximum frame rate that can be set.
*/
func setResolution(_ resolution: AVCaptureSession.Preset) { cameraManager.setResolution(resolution) }
/**
Set the camera frame rate.
- important: Changing the resolution may affect the maximum frame rate that can be set.
- note: If the frame rate is out of bounds, it will be set to the closest available value.
*/
func setFrameRate(_ frameRate: Int32) throws { try cameraManager.setFrameRate(frameRate) }
/**
Set the camera exposure duration.
- note: If the exposure duration is out of bounds, it will be set to the closest available value.
*/
func setExposureDuration(_ exposureDuration: CMTime) throws { try cameraManager.setExposureDuration(exposureDuration) }
/**
Set the camera exposure target bias.
- note: If the target bias is out of bounds, it will be set to the closest available value.
*/
func setExposureTargetBias(_ exposureTargetBias: Float) throws { try cameraManager.setExposureTargetBias(exposureTargetBias) }
/**
Set the camera ISO.
- note: If the ISO is out of bounds, it will be set to the closest available value.
*/
func setISO(_ iso: Float) throws { try cameraManager.setISO(iso) }
/**
Set the camera exposure mode.
- note: If the exposure mode is not supported, the exposure mode will not be changed.
*/
func setExposureMode(_ exposureMode: AVCaptureDevice.ExposureMode) throws { try cameraManager.setExposureMode(exposureMode) }
/**
Set the camera HDR mode.
For available options, please refer to the ``CameraHDRMode`` documentation.
*/
func setHDRMode(_ hdrMode: CameraHDRMode) throws { try cameraManager.setHDRMode(hdrMode) }
/**
Set the camera filters to be applied to the camera output.
- important: Setting multiple filters simultaneously can affect the performance of the camera.
*/
func setCameraFilters(_ filters: [CIFilter]) { cameraManager.setCameraFilters(filters) }
/**
Set whether the camera output should be mirrored.
*/
func setMirrorOutput(_ shouldMirror: Bool) { cameraManager.setMirrorOutput(shouldMirror) }
/**
Set whether the camera grid should be visible.
*/
func setGridVisibility(_ shouldShowGrid: Bool) { cameraManager.setGridVisibility(shouldShowGrid) }
}
// MARK: Attributes
public extension MCameraScreen {
var cameraOutputType: CameraOutputType { cameraManager.attributes.outputType }
var cameraPosition: CameraPosition { cameraManager.attributes.cameraPosition }
var zoomFactor: CGFloat { cameraManager.attributes.zoomFactor }
var flashMode: CameraFlashMode { cameraManager.attributes.flashMode }
var lightMode: CameraLightMode { cameraManager.attributes.lightMode }
var resolution: AVCaptureSession.Preset { cameraManager.attributes.resolution }
var frameRate: Int32 { cameraManager.attributes.frameRate }
var exposureDuration: CMTime { cameraManager.attributes.cameraExposure.duration }
var exposureTargetBias: Float { cameraManager.attributes.cameraExposure.targetBias }
var iso: Float { cameraManager.attributes.cameraExposure.iso }
var exposureMode: AVCaptureDevice.ExposureMode { cameraManager.attributes.cameraExposure.mode }
var hdrMode: CameraHDRMode { cameraManager.attributes.hdrMode }
var cameraFilters: [CIFilter] { cameraManager.attributes.cameraFilters }
var isOutputMirrored: Bool { cameraManager.attributes.mirrorOutput }
var isGridVisible: Bool { cameraManager.attributes.isGridVisible }
}
public extension MCameraScreen {
var hasFlash: Bool { cameraManager.hasFlash }
var hasLight: Bool { cameraManager.hasLight }
var recordingTime: MTime { cameraManager.videoOutput.recordingTime }
var isRecording: Bool { cameraManager.videoOutput.timer.timerStatus == .running }
var isOrientationLocked: Bool { cameraManager.attributes.orientationLocked || cameraManager.attributes.userBlockedScreenRotation }
var deviceOrientation: AVCaptureVideoOrientation { cameraManager.attributes.deviceOrientation }
}