mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-02 00:32:56 +02:00
Add a fourth, virtual zoom factor for triple camera iPhones that have a large difference between their zoom factors. Closes #663
This commit is contained in:
@@ -61,9 +61,10 @@
|
|||||||
AVCaptureDevicePosition _cameraPosition;
|
AVCaptureDevicePosition _cameraPosition;
|
||||||
UIButton *_cameraPositionButton;
|
UIButton *_cameraPositionButton;
|
||||||
UIButton *_changeCameraButton;
|
UIButton *_changeCameraButton;
|
||||||
NSArray *_allCaptureDevices;
|
AVCaptureDevice *_frontCaptureDevice;
|
||||||
NSArray *_backCaptureDevices;
|
AVCaptureDevice *_backCaptureDevice;
|
||||||
AVCaptureDevice *_selectedBackCaptureDevice;
|
NSMutableArray<NSNumber *> *_zoomLevels;
|
||||||
|
unsigned _currentZoomIndex;
|
||||||
|
|
||||||
__weak GCController *_lastController;
|
__weak GCController *_lastController;
|
||||||
|
|
||||||
@@ -285,32 +286,42 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
|
|||||||
|
|
||||||
_motionManager = [[CMMotionManager alloc] init];
|
_motionManager = [[CMMotionManager alloc] init];
|
||||||
_cameraPosition = AVCaptureDevicePositionBack;
|
_cameraPosition = AVCaptureDevicePositionBack;
|
||||||
_selectedBackCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
|
|
||||||
|
|
||||||
// Back camera setup
|
// Back camera setup
|
||||||
NSArray *deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera,
|
NSArray *deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera,
|
||||||
AVCaptureDeviceTypeBuiltInTelephotoCamera];
|
AVCaptureDeviceTypeBuiltInTelephotoCamera,
|
||||||
|
AVCaptureDeviceTypeBuiltInDualCamera];
|
||||||
if (@available(iOS 13.0, *)) {
|
if (@available(iOS 13.0, *)) {
|
||||||
// AVCaptureDeviceTypeBuiltInUltraWideCamera is only available in iOS 13+
|
// AVCaptureDeviceTypeBuiltInUltraWideCamera is only available in iOS 13+
|
||||||
deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera,
|
deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera,
|
||||||
AVCaptureDeviceTypeBuiltInUltraWideCamera,
|
AVCaptureDeviceTypeBuiltInUltraWideCamera,
|
||||||
AVCaptureDeviceTypeBuiltInTelephotoCamera];
|
AVCaptureDeviceTypeBuiltInTelephotoCamera,
|
||||||
|
AVCaptureDeviceTypeBuiltInTripleCamera,
|
||||||
|
AVCaptureDeviceTypeBuiltInDualWideCamera,
|
||||||
|
AVCaptureDeviceTypeBuiltInDualCamera];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a discovery session to gather the capture devices (all back cameras as well as the front camera)
|
// Use a discovery session to gather the capture devices (all back cameras as well as the front camera)
|
||||||
AVCaptureDeviceDiscoverySession *cameraDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceTypes
|
AVCaptureDeviceDiscoverySession *cameraDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceTypes
|
||||||
mediaType:AVMediaTypeVideo
|
mediaType:AVMediaTypeVideo
|
||||||
position:AVCaptureDevicePositionUnspecified];
|
position:AVCaptureDevicePositionUnspecified];
|
||||||
_allCaptureDevices = cameraDiscoverySession.devices;
|
for (AVCaptureDevice *device in cameraDiscoverySession.devices) {
|
||||||
|
|
||||||
// Filter only the back cameras into a list used for switching between them
|
|
||||||
NSMutableArray *filteredBackCameras = [NSMutableArray array];
|
|
||||||
for (AVCaptureDevice *device in _allCaptureDevices) {
|
|
||||||
if ([device position] == AVCaptureDevicePositionBack) {
|
if ([device position] == AVCaptureDevicePositionBack) {
|
||||||
[filteredBackCameras addObject:device];
|
if (!_backCaptureDevice ||
|
||||||
|
_backCaptureDevice.virtualDeviceSwitchOverVideoZoomFactors.count < device.virtualDeviceSwitchOverVideoZoomFactors.count) {
|
||||||
|
_backCaptureDevice = device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ([device position] == AVCaptureDevicePositionFront) {
|
||||||
|
_frontCaptureDevice = device;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_backCaptureDevices = filteredBackCameras;
|
|
||||||
|
_zoomLevels = _backCaptureDevice.virtualDeviceSwitchOverVideoZoomFactors.mutableCopy;
|
||||||
|
[_zoomLevels insertObject:@1 atIndex:0];
|
||||||
|
if (_zoomLevels.count == 3 && _zoomLevels[2].doubleValue > 5.5 && _zoomLevels[1].doubleValue < 3.5) {
|
||||||
|
[_zoomLevels insertObject:@4 atIndex:2];
|
||||||
|
}
|
||||||
|
|
||||||
_cameraPositionButton = [[UIButton alloc] init];
|
_cameraPositionButton = [[UIButton alloc] init];
|
||||||
[self didRotateFromInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation];
|
[self didRotateFromInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation];
|
||||||
@@ -332,7 +343,7 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
|
|||||||
action:@selector(changeCamera)
|
action:@selector(changeCamera)
|
||||||
forControlEvents:UIControlEventTouchUpInside];
|
forControlEvents:UIControlEventTouchUpInside];
|
||||||
// Only show the change camera button if we have more than one back camera to swap between.
|
// Only show the change camera button if we have more than one back camera to swap between.
|
||||||
if ([_backCaptureDevices count] > 1) {
|
if (_zoomLevels.count > 1) {
|
||||||
[_backgroundView addSubview:_changeCameraButton];
|
[_backgroundView addSubview:_changeCameraButton];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1561,21 +1572,10 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response
|
|||||||
|
|
||||||
- (AVCaptureDevice *)captureDevice
|
- (AVCaptureDevice *)captureDevice
|
||||||
{
|
{
|
||||||
for (AVCaptureDevice *device in _allCaptureDevices) {
|
if (_cameraPosition == AVCaptureDevicePositionFront) {
|
||||||
if ([device position] == _cameraPosition) {
|
return _frontCaptureDevice ?: [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
|
||||||
// There is only one front camera, return it
|
|
||||||
if (_cameraPosition == AVCaptureDevicePositionFront) {
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There may be several back cameras, return the one with the matching type
|
|
||||||
if ([device deviceType] == [_selectedBackCaptureDevice deviceType]) {
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Return the default camera
|
return _backCaptureDevice ?: [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
|
||||||
return [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cameraRequestUpdate
|
- (void)cameraRequestUpdate
|
||||||
@@ -1756,19 +1756,13 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response
|
|||||||
- (void)changeCamera
|
- (void)changeCamera
|
||||||
{
|
{
|
||||||
dispatch_async(_cameraQueue, ^{
|
dispatch_async(_cameraQueue, ^{
|
||||||
// Get index of selected camera and select the next one, wrapping to the beginning
|
if (![_backCaptureDevice lockForConfiguration:nil]) return;
|
||||||
NSUInteger i = [_backCaptureDevices indexOfObject:_selectedBackCaptureDevice];
|
_currentZoomIndex++;
|
||||||
int nextIndex = (i + 1) % _backCaptureDevices.count;
|
if (_currentZoomIndex == _zoomLevels.count) {
|
||||||
_selectedBackCaptureDevice = _backCaptureDevices[nextIndex];
|
_currentZoomIndex = 0;
|
||||||
|
|
||||||
[_cameraSession stopRunning];
|
|
||||||
_cameraSession = nil;
|
|
||||||
_cameraConnection = nil;
|
|
||||||
_cameraOutput = nil;
|
|
||||||
if (_cameraNeedsUpdate) {
|
|
||||||
_cameraNeedsUpdate = false;
|
|
||||||
GB_camera_updated(&_gb);
|
|
||||||
}
|
}
|
||||||
|
[_backCaptureDevice rampToVideoZoomFactor:_zoomLevels[_currentZoomIndex].doubleValue withRate:2];
|
||||||
|
[_backCaptureDevice unlockForConfiguration];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user