├── .gitignore ├── .swiftlint.yml ├── Cartfile ├── Cartfile.resolved ├── Example ├── Example.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Example.xcscheme ├── Example.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ └── SCNRecorder.podspec.json │ ├── MTDMulticastDelegate │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── Sources │ │ │ └── MulticastDelegate │ │ │ ├── MTDMulticastDelegate.m │ │ │ ├── MTDOriginMulticastDelegate.m │ │ │ └── include │ │ │ └── MulticastDelegate │ │ │ ├── MTDMulticastDelegate.h │ │ │ ├── MTDOriginMulticastDelegate.h │ │ │ └── MulticastDelegate.h │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ ├── SnapKit │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ ├── Constraint.swift │ │ │ ├── ConstraintAttributes.swift │ │ │ ├── ConstraintConfig.swift │ │ │ ├── ConstraintConstantTarget.swift │ │ │ ├── ConstraintDSL.swift │ │ │ ├── ConstraintDescription.swift │ │ │ ├── ConstraintDirectionalInsetTarget.swift │ │ │ ├── ConstraintDirectionalInsets.swift │ │ │ ├── ConstraintInsetTarget.swift │ │ │ ├── ConstraintInsets.swift │ │ │ ├── ConstraintItem.swift │ │ │ ├── ConstraintLayoutGuide+Extensions.swift │ │ │ ├── ConstraintLayoutGuide.swift │ │ │ ├── ConstraintLayoutGuideDSL.swift │ │ │ ├── ConstraintLayoutSupport.swift │ │ │ ├── ConstraintLayoutSupportDSL.swift │ │ │ ├── ConstraintMaker.swift │ │ │ ├── ConstraintMakerEditable.swift │ │ │ ├── ConstraintMakerExtendable.swift │ │ │ ├── ConstraintMakerFinalizable.swift │ │ │ ├── ConstraintMakerPrioritizable.swift │ │ │ ├── ConstraintMakerRelatable+Extensions.swift │ │ │ ├── ConstraintMakerRelatable.swift │ │ │ ├── ConstraintMultiplierTarget.swift │ │ │ ├── ConstraintOffsetTarget.swift │ │ │ ├── ConstraintPriority.swift │ │ │ ├── ConstraintPriorityTarget.swift │ │ │ ├── ConstraintRelatableTarget.swift │ │ │ ├── ConstraintRelation.swift │ │ │ ├── ConstraintView+Extensions.swift │ │ │ ├── ConstraintView.swift │ │ │ ├── ConstraintViewDSL.swift │ │ │ ├── Debugging.swift │ │ │ ├── LayoutConstraint.swift │ │ │ ├── LayoutConstraintItem.swift │ │ │ ├── PrivacyInfo.xcprivacy │ │ │ ├── Typealiases.swift │ │ │ └── UILayoutSupport+Extensions.swift │ └── Target Support Files │ │ ├── MTDMulticastDelegate │ │ ├── MTDMulticastDelegate-Info.plist │ │ ├── MTDMulticastDelegate-dummy.m │ │ ├── MTDMulticastDelegate-prefix.pch │ │ ├── MTDMulticastDelegate-umbrella.h │ │ ├── MTDMulticastDelegate.debug.xcconfig │ │ ├── MTDMulticastDelegate.modulemap │ │ └── MTDMulticastDelegate.release.xcconfig │ │ ├── Pods-Example │ │ ├── Pods-Example-Info.plist │ │ ├── Pods-Example-acknowledgements.markdown │ │ ├── Pods-Example-acknowledgements.plist │ │ ├── Pods-Example-dummy.m │ │ ├── Pods-Example-frameworks-Debug-input-files.xcfilelist │ │ ├── Pods-Example-frameworks-Debug-output-files.xcfilelist │ │ ├── Pods-Example-frameworks-Release-input-files.xcfilelist │ │ ├── Pods-Example-frameworks-Release-output-files.xcfilelist │ │ ├── Pods-Example-frameworks.sh │ │ ├── Pods-Example-umbrella.h │ │ ├── Pods-Example.debug.xcconfig │ │ ├── Pods-Example.modulemap │ │ └── Pods-Example.release.xcconfig │ │ ├── SCNRecorder │ │ ├── SCNRecorder-Info.plist │ │ ├── SCNRecorder-dummy.m │ │ ├── SCNRecorder-prefix.pch │ │ ├── SCNRecorder-umbrella.h │ │ ├── SCNRecorder.debug.xcconfig │ │ ├── SCNRecorder.modulemap │ │ └── SCNRecorder.release.xcconfig │ │ └── SnapKit │ │ ├── ResourceBundle-SnapKit_Privacy-SnapKit-Info.plist │ │ ├── SnapKit-Info.plist │ │ ├── SnapKit-dummy.m │ │ ├── SnapKit-prefix.pch │ │ ├── SnapKit-umbrella.h │ │ ├── SnapKit.debug.xcconfig │ │ ├── SnapKit.modulemap │ │ └── SnapKit.release.xcconfig └── Source │ ├── .swiftlint.yml │ ├── AppDelegate.swift │ ├── Common │ ├── Button.swift │ ├── View.swift │ ├── ViewController.swift │ └── Weakify │ │ ├── Weakifiable.swift │ │ └── Weakify.swift │ ├── Content │ ├── ARKit │ │ └── ARKitViewController.swift │ ├── Metal │ │ ├── MetalShaderTypes.h │ │ ├── MetalShaders.metal │ │ ├── MetalView.swift │ │ ├── MetalViewController.swift │ │ └── SquadRenderer.swift │ ├── RealityKit │ │ ├── ARView+MetalRecordable.swift │ │ ├── ARView+SelfSceneRecordable.swift │ │ └── RealityKitViewController.swift │ └── SceneKit │ │ └── SceneKitViewController.swift │ ├── Controls │ ├── Controllable.swift │ ├── ControlsView.swift │ └── ControlsViewController.swift │ ├── Example-Bridging-Header.h │ ├── Extensions │ └── UIColor+Helpers.swift │ ├── Info.plist │ ├── MainViewController.swift │ ├── Preview │ ├── PhotoPreviewController.swift │ └── VideoPreviewController.swift │ └── Resources │ ├── 0-9.mp3 │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── Experience.rcproject │ ├── Library │ │ └── ProjectLibrary │ │ │ ├── Contents.json │ │ │ └── Version.json │ ├── SceneThumbnails │ │ └── F9610871-0955-494F-A5C3-51D1A281BAB3.thumbnails │ │ │ ├── square │ │ │ └── wide │ └── com.apple.RCFoundation.Project │ └── art.scnassets │ ├── ship.scn │ └── texture.png ├── Info.plist ├── LICENSE.md ├── Package.resolved ├── Package.swift ├── README.md ├── SCNRecorder.podspec ├── SCNRecorder.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ ├── xcbaselines │ └── D57464AD25725BA70025578A.xcbaseline │ │ ├── 36E9BB1D-0C31-4B9C-B571-24EE0254D4FB.plist │ │ └── Info.plist │ └── xcschemes │ ├── SCNRecorder.xcscheme │ ├── SCNRecorderTests.xcscheme │ └── SCNRecorderTestsApp.xcscheme ├── SCNRecorderTests ├── Extensions │ ├── MTLPixelFormat+Helpers.swift │ ├── UIColor+Helpers.swift │ └── VideoSetting.Codec+Helpers.swift ├── Info.plist ├── Metal │ ├── TestMetalShaderTypes.h │ ├── TestMetalShaders.metal │ ├── TestRecordableLayer.swift │ └── TestRenderer.swift ├── MetalPixelBufferProducerTests.swift ├── SCNRecorderTests-Bridging-Header.h └── SceneRecorderTests.swift ├── SCNRecorderTestsApp ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist └── ViewController.swift ├── Sources ├── AudioEngine │ ├── AudioEngine.Player.State.swift │ ├── AudioEngine.Player.swift │ └── AudioEngine.swift ├── AudioSettings.swift ├── Extensions │ ├── AVCaptureSession+BaseRecorder.swift │ ├── CALayer+InterfaceOrientation.swift │ ├── IOSurface+Size.swift │ ├── MTLPixelFormat+Helpers.swift │ └── SCNView+MulticastDelegate.swift ├── Helpers │ ├── AssociatedStorage.swift │ ├── AudioAdapter.swift │ ├── Buffer.swift │ ├── Multithreading │ │ ├── Atomic.swift │ │ ├── Dispatch │ │ │ └── DispatchAtomic.swift │ │ ├── ReadWrite │ │ │ ├── ReadWriteAtomic.swift │ │ │ └── ReadWriteLock.swift │ │ └── Unfair │ │ │ ├── UnfairAtomic.swift │ │ │ └── UnfairLock.swift │ ├── Observable.swift │ ├── Property.swift │ ├── Updater.swift │ ├── Weak.swift │ └── WeakCollection.swift ├── MediaSession │ ├── MediaSession.swift │ ├── MediaSessionInput.swift │ └── MediaSessionOutput.swift ├── Outputs │ ├── ImageOutput │ │ └── ImageOutput.swift │ ├── PixelBufferOutput.swift │ └── VideoOutput │ │ ├── VideoOutput.Error.swift │ │ ├── VideoOutput.State.swift │ │ └── VideoOutput.swift ├── PixelBuffer │ ├── MetalPixelBufferProducer.swift │ ├── MetalTexture.swift │ ├── MetalTexturePool.swift │ ├── MetalTexturePoolFactory.swift │ ├── PixelBuffer.swift │ ├── PixelBufferPool.swift │ └── PixelBufferPoolFactory.swift ├── Protocols │ ├── Renderable.swift │ └── TimeScalable.swift ├── Recordable │ ├── CleanRecordable.swift │ ├── Extensions │ │ ├── ARSCNView+CleanRecordable.swift │ │ └── SCNView+MetalRecordable.swift │ └── MetalRecordable.swift ├── RecordableLayer │ ├── CAMetalLayer+RecordableLayer.swift │ └── RecordableLayer.swift ├── Recorder │ ├── BaseRecorder │ │ ├── BaseRecorder.AudioInput.swift │ │ └── BaseRecorder.swift │ ├── CleanRecorder │ │ ├── CleanRecorder.VideoInput.swift │ │ └── CleanRecorder.swift │ └── SceneRecorder │ │ ├── SceneRecorder.VideoInput.swift │ │ └── SceneRecorder.swift ├── SelfRecordable │ ├── Extensions │ │ └── SCNView+SelfSceneRecordable.swift │ ├── SelfRecordable.swift │ └── SelfSceneRecordable.swift ├── VideoRecording.Info.swift ├── VideoRecording.State.swift ├── VideoRecording.swift ├── VideoSettings.Codec.swift ├── VideoSettings.CompressionProperties.swift ├── VideoSettings.FileType.swift ├── VideoSettings.ScalingMode.swift └── VideoSettings.swift └── images └── sample2.gif /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: 2 | - identifier_name 3 | - statement_position 4 | - nesting 5 | - trailing_comma 6 | included: 7 | - Sources 8 | - Example/Source 9 | reporter: "xcode" 10 | 11 | identifier_name: 12 | min_length: 1 13 | allowed_symbols: ["_"] 14 | 15 | cyclomatic_complexity: 16 | ignores_case_statements: true 17 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "v-grigoriev/MulticastDelegate" 2 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "v-grigoriev/MulticastDelegate" "1.0.1" 2 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Example.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '13.0' 2 | 3 | use_frameworks! 4 | 5 | target 'Example' do 6 | pod 'SnapKit', '~> 5.7.1' 7 | pod 'SCNRecorder', :path => '../' 8 | end 9 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MTDMulticastDelegate (1.0.1) 3 | - SCNRecorder (2.9.0): 4 | - MTDMulticastDelegate 5 | - SnapKit (5.7.1) 6 | 7 | DEPENDENCIES: 8 | - SCNRecorder (from `../`) 9 | - SnapKit (~> 5.7.1) 10 | 11 | SPEC REPOS: 12 | trunk: 13 | - MTDMulticastDelegate 14 | - SnapKit 15 | 16 | EXTERNAL SOURCES: 17 | SCNRecorder: 18 | :path: "../" 19 | 20 | SPEC CHECKSUMS: 21 | MTDMulticastDelegate: dcedff914c281710e3faa64b79ff775741f25b4b 22 | SCNRecorder: cad6d2f1d7420db813e0d426515dbed9cbd87571 23 | SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a 24 | 25 | PODFILE CHECKSUM: 6cdab886091e4aeb20218508030c8f0592e2ce55 26 | 27 | COCOAPODS: 1.15.2 28 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/SCNRecorder.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SCNRecorder", 3 | "version": "2.9.0", 4 | "summary": "A lags-free recorder of ARKit and SceneKit for iOS in Swift", 5 | "homepage": "https://github.com/gorastudio/SCNRecorder", 6 | "license": { 7 | "type": "MIT", 8 | "file": "LICENSE.md" 9 | }, 10 | "authors": { 11 | "Vladislav Grigoryev": "dev.grigoriev@gmail.com" 12 | }, 13 | "platforms": { 14 | "ios": "12.0" 15 | }, 16 | "source": { 17 | "git": "https://github.com/gorastudio-ceo/SCNRecorder.git", 18 | "tag": "2.9.0" 19 | }, 20 | "module_name": "SCNRecorder", 21 | "swift_versions": "5.0", 22 | "source_files": "Sources/**/*.{swift}", 23 | "dependencies": { 24 | "MTDMulticastDelegate": [ 25 | 26 | ] 27 | }, 28 | "testspecs": [ 29 | { 30 | "name": "Tests", 31 | "test_type": "unit", 32 | "platforms": { 33 | "ios": "13.0" 34 | }, 35 | "requires_app_host": true, 36 | "app_host_name": "SCNRecorder/Example", 37 | "source_files": [ 38 | "SCNRecorderTests/**/*.{m,swift,metal}", 39 | "SCNRecorderTests/Metal/**/*.h" 40 | ], 41 | "preserve_paths": "SCNRecorderTests/SCNRecorderTests-Bridging-Header.h", 42 | "pod_target_xcconfig": { 43 | "SWIFT_OBJC_BRIDGING_HEADER": "$(PODS_TARGET_SRCROOT)/SCNRecorderTests/SCNRecorderTests-Bridging-Header.h" 44 | }, 45 | "dependencies": { 46 | "SCNRecorder/Example": [ 47 | 48 | ] 49 | } 50 | } 51 | ], 52 | "appspecs": [ 53 | { 54 | "name": "Example", 55 | "platforms": { 56 | "ios": "13.0" 57 | }, 58 | "source_files": [ 59 | "Example/Source/**/*.{m,swift,metal}", 60 | "Example/Source/Content/**/*.{h}" 61 | ], 62 | "preserve_paths": "Example/Source/Example-Bridging-Header.h", 63 | "resources": "Example/Source/Resources/**/*.{scnassets,xcassets}", 64 | "pod_target_xcconfig": { 65 | "SWIFT_OBJC_BRIDGING_HEADER": "$(PODS_TARGET_SRCROOT)/Example/Source/Example-Bridging-Header.h" 66 | }, 67 | "dependencies": { 68 | "SnapKit": [ 69 | "~> 5.7.1" 70 | ] 71 | } 72 | } 73 | ], 74 | "swift_version": "5.0" 75 | } 76 | -------------------------------------------------------------------------------- /Example/Pods/MTDMulticastDelegate/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2021 GORA Studio. https://gora.studio 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Example/Pods/MTDMulticastDelegate/README.md: -------------------------------------------------------------------------------- 1 | # MulticastDelegate 2 | 3 | [![GitHub license](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/v-grigoriev/MulticastDelegate/master/LICENSE.md) 4 | ![Platforms](https://img.shields.io/cocoapods/p/MTDMulticastDelegate.svg) 5 | ![Objective-C](https://img.shields.io/badge/Objective--C-red) 6 | [![Cocoapods compatible](https://img.shields.io/cocoapods/v/MTDMulticastDelegate.svg)](https://cocoapods.org/pods/MTDMulticastDelegate) 7 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 8 | 9 | An Objective-C implementation of multicast delegate. Primarly is used by [SCNRecorder](https://github.com/gorastudio/SCNRecorder). 10 | -------------------------------------------------------------------------------- /Example/Pods/MTDMulticastDelegate/Sources/MulticastDelegate/MTDOriginMulticastDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // MTDOriginMulticastDelegate.m 3 | // MulticastDelegate 4 | // 5 | // Created by Vladislav Grigoryev on 30.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | @implementation MTDOriginMulticastDelegate 29 | 30 | #pragma mark - NSProxy 31 | 32 | - (void)forwardInvocation:(NSInvocation *)invocation 33 | { 34 | if ([self.origin respondsToSelector:invocation.selector]) { 35 | [invocation invokeWithTarget:self.origin]; 36 | } 37 | 38 | [super forwardInvocation:invocation]; 39 | } 40 | 41 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector 42 | { 43 | NSMethodSignature *methodSinature = [self.origin methodSignatureForSelector:selector]; 44 | if (methodSinature) { 45 | return methodSinature; 46 | } 47 | return [super methodSignatureForSelector:selector]; 48 | } 49 | 50 | - (BOOL)respondsToSelector:(SEL)selector 51 | { 52 | return [self.origin respondsToSelector:selector] || [super respondsToSelector:selector]; 53 | } 54 | 55 | - (BOOL)conformsToProtocol:(Protocol *)protocol 56 | { 57 | return [self.origin conformsToProtocol:protocol] || [super conformsToProtocol:protocol]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Example/Pods/MTDMulticastDelegate/Sources/MulticastDelegate/include/MulticastDelegate/MTDMulticastDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MTDMulticastDelegate.h 3 | // MulticastDelegate 4 | // 5 | // Created by Vladislav Grigoryev on 30.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | NS_SWIFT_NAME(MulticastDelegate) 31 | @interface MTDMulticastDelegate<__covariant Delegate> : NSProxy 32 | 33 | @property (nonatomic, strong, readonly) NSArray *delegates; 34 | 35 | - (instancetype)init; 36 | 37 | - (void)addDelegate:(Delegate)delegate; 38 | 39 | - (void)removeDelegate:(Delegate)delegate; 40 | 41 | @end 42 | 43 | NS_ASSUME_NONNULL_END 44 | -------------------------------------------------------------------------------- /Example/Pods/MTDMulticastDelegate/Sources/MulticastDelegate/include/MulticastDelegate/MTDOriginMulticastDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MTDOriginMulticastDelegate.h 3 | // MulticastDelegate 4 | // 5 | // Created by Vladislav Grigoryev on 30.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | #import 28 | 29 | NS_ASSUME_NONNULL_BEGIN 30 | 31 | NS_SWIFT_NAME(OriginMulticastDelegate) 32 | @interface MTDOriginMulticastDelegate<__covariant Delegate> : MTDMulticastDelegate 33 | 34 | @property (nonatomic, weak, nullable) Delegate origin; 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /Example/Pods/MTDMulticastDelegate/Sources/MulticastDelegate/include/MulticastDelegate/MulticastDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MulticastDelegate.h 3 | // MulticastDelegate 4 | // 5 | // Created by Vladislav Grigoryev on 30.05.2020. 6 | // Copyright © 2021 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #import 27 | 28 | //! Project version number for MulticastDelegate. 29 | FOUNDATION_EXPORT double MulticastDelegateVersionNumber; 30 | 31 | //! Project version string for MulticastDelegate. 32 | FOUNDATION_EXPORT const unsigned char MulticastDelegateVersionString[]; 33 | 34 | #import 35 | #import 36 | 37 | 38 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MTDMulticastDelegate (1.0.1) 3 | - SCNRecorder (2.9.0): 4 | - MTDMulticastDelegate 5 | - SnapKit (5.7.1) 6 | 7 | DEPENDENCIES: 8 | - SCNRecorder (from `../`) 9 | - SnapKit (~> 5.7.1) 10 | 11 | SPEC REPOS: 12 | trunk: 13 | - MTDMulticastDelegate 14 | - SnapKit 15 | 16 | EXTERNAL SOURCES: 17 | SCNRecorder: 18 | :path: "../" 19 | 20 | SPEC CHECKSUMS: 21 | MTDMulticastDelegate: dcedff914c281710e3faa64b79ff775741f25b4b 22 | SCNRecorder: cad6d2f1d7420db813e0d426515dbed9cbd87571 23 | SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a 24 | 25 | PODFILE CHECKSUM: 6cdab886091e4aeb20218508030c8f0592e2ce55 26 | 27 | COCOAPODS: 1.15.2 28 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection 27 | #else 28 | import AppKit 29 | public typealias ConstraintInterfaceLayoutDirection = NSUserInterfaceLayoutDirection 30 | #endif 31 | 32 | 33 | public struct ConstraintConfig { 34 | 35 | public static var interfaceLayoutDirection: ConstraintInterfaceLayoutDirection = .leftToRight 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintDirectionalInsetTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | #if canImport(UIKit) 31 | public protocol ConstraintDirectionalInsetTarget: ConstraintConstantTarget { 32 | } 33 | 34 | @available(iOS 11.0, tvOS 11.0, *) 35 | extension ConstraintDirectionalInsets: ConstraintDirectionalInsetTarget { 36 | } 37 | 38 | extension ConstraintDirectionalInsetTarget { 39 | 40 | @available(iOS 11.0, tvOS 11.0, *) 41 | internal var constraintDirectionalInsetTargetValue: ConstraintDirectionalInsets { 42 | if let amount = self as? ConstraintDirectionalInsets { 43 | return amount 44 | } else { 45 | return ConstraintDirectionalInsets(top: 0, leading: 0, bottom: 0, trailing: 0) 46 | } 47 | } 48 | } 49 | #endif 50 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintDirectionalInsets.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if canImport(UIKit) 32 | @available(iOS 11.0, tvOS 11.0, *) 33 | public typealias ConstraintDirectionalInsets = NSDirectionalEdgeInsets 34 | #endif 35 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintInsets.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if canImport(UIKit) 32 | public typealias ConstraintInsets = UIEdgeInsets 33 | #else 34 | public typealias ConstraintInsets = NSEdgeInsets 35 | #endif 36 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public final class ConstraintItem { 32 | 33 | internal weak var target: AnyObject? 34 | internal let attributes: ConstraintAttributes 35 | 36 | internal init(target: AnyObject?, attributes: ConstraintAttributes) { 37 | self.target = target 38 | self.attributes = attributes 39 | } 40 | 41 | internal var layoutConstraintItem: LayoutConstraintItem? { 42 | return self.target as? LayoutConstraintItem 43 | } 44 | 45 | } 46 | 47 | public func ==(lhs: ConstraintItem, rhs: ConstraintItem) -> Bool { 48 | // pointer equality 49 | guard lhs !== rhs else { 50 | return true 51 | } 52 | 53 | // must both have valid targets and identical attributes 54 | guard let target1 = lhs.target, 55 | let target2 = rhs.target, 56 | target1 === target2 && lhs.attributes == rhs.attributes else { 57 | return false 58 | } 59 | 60 | return true 61 | } 62 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintLayoutGuide+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #endif 27 | 28 | 29 | @available(iOS 9.0, OSX 10.11, *) 30 | public extension ConstraintLayoutGuide { 31 | 32 | var snp: ConstraintLayoutGuideDSL { 33 | return ConstraintLayoutGuideDSL(guide: self) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintLayoutGuide.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if canImport(UIKit) 32 | @available(iOS 9.0, *) 33 | public typealias ConstraintLayoutGuide = UILayoutGuide 34 | #else 35 | @available(OSX 10.11, *) 36 | public typealias ConstraintLayoutGuide = NSLayoutGuide 37 | #endif 38 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintLayoutGuideDSL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | @available(iOS 9.0, OSX 10.11, *) 32 | public struct ConstraintLayoutGuideDSL: ConstraintAttributesDSL { 33 | 34 | @discardableResult 35 | public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] { 36 | return ConstraintMaker.prepareConstraints(item: self.guide, closure: closure) 37 | } 38 | 39 | public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 40 | ConstraintMaker.makeConstraints(item: self.guide, closure: closure) 41 | } 42 | 43 | public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 44 | ConstraintMaker.remakeConstraints(item: self.guide, closure: closure) 45 | } 46 | 47 | public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 48 | ConstraintMaker.updateConstraints(item: self.guide, closure: closure) 49 | } 50 | 51 | public func removeConstraints() { 52 | ConstraintMaker.removeConstraints(item: self.guide) 53 | } 54 | 55 | public var target: AnyObject? { 56 | return self.guide 57 | } 58 | 59 | internal let guide: ConstraintLayoutGuide 60 | 61 | internal init(guide: ConstraintLayoutGuide) { 62 | self.guide = guide 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintLayoutSupport.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if canImport(UIKit) 32 | @available(iOS 8.0, *) 33 | public typealias ConstraintLayoutSupport = UILayoutSupport 34 | #else 35 | public class ConstraintLayoutSupport {} 36 | #endif 37 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintLayoutSupportDSL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | @available(iOS 8.0, *) 32 | public struct ConstraintLayoutSupportDSL: ConstraintDSL { 33 | 34 | public var target: AnyObject? { 35 | return self.support 36 | } 37 | 38 | internal let support: ConstraintLayoutSupport 39 | 40 | internal init(support: ConstraintLayoutSupport) { 41 | self.support = support 42 | 43 | } 44 | 45 | public var top: ConstraintItem { 46 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top) 47 | } 48 | 49 | public var bottom: ConstraintItem { 50 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom) 51 | } 52 | 53 | public var height: ConstraintItem { 54 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintMakerEditable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintMakerEditable: ConstraintMakerPrioritizable { 32 | 33 | @discardableResult 34 | public func multipliedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable { 35 | self.description.multiplier = amount 36 | return self 37 | } 38 | 39 | @discardableResult 40 | public func dividedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable { 41 | return self.multipliedBy(1.0 / amount.constraintMultiplierTargetValue) 42 | } 43 | 44 | @discardableResult 45 | public func offset(_ amount: ConstraintOffsetTarget) -> ConstraintMakerEditable { 46 | self.description.constant = amount.constraintOffsetTargetValue 47 | return self 48 | } 49 | 50 | @discardableResult 51 | public func inset(_ amount: ConstraintInsetTarget) -> ConstraintMakerEditable { 52 | self.description.constant = amount.constraintInsetTargetValue 53 | return self 54 | } 55 | 56 | #if canImport(UIKit) 57 | @discardableResult 58 | @available(iOS 11.0, tvOS 11.0, *) 59 | public func inset(_ amount: ConstraintDirectionalInsetTarget) -> ConstraintMakerEditable { 60 | self.description.constant = amount.constraintDirectionalInsetTargetValue 61 | return self 62 | } 63 | #endif 64 | } 65 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintMakerFinalizable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintMakerFinalizable { 32 | 33 | internal let description: ConstraintDescription 34 | 35 | internal init(_ description: ConstraintDescription) { 36 | self.description = description 37 | } 38 | 39 | @discardableResult 40 | public func labeled(_ label: String) -> ConstraintMakerFinalizable { 41 | self.description.label = label 42 | return self 43 | } 44 | 45 | public var constraint: Constraint { 46 | return self.description.constraint! 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintMultiplierTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintMultiplierTarget { 32 | 33 | var constraintMultiplierTargetValue: CGFloat { get } 34 | 35 | } 36 | 37 | extension Int: ConstraintMultiplierTarget { 38 | 39 | public var constraintMultiplierTargetValue: CGFloat { 40 | return CGFloat(self) 41 | } 42 | 43 | } 44 | 45 | extension UInt: ConstraintMultiplierTarget { 46 | 47 | public var constraintMultiplierTargetValue: CGFloat { 48 | return CGFloat(self) 49 | } 50 | 51 | } 52 | 53 | extension Float: ConstraintMultiplierTarget { 54 | 55 | public var constraintMultiplierTargetValue: CGFloat { 56 | return CGFloat(self) 57 | } 58 | 59 | } 60 | 61 | extension Double: ConstraintMultiplierTarget { 62 | 63 | public var constraintMultiplierTargetValue: CGFloat { 64 | return CGFloat(self) 65 | } 66 | 67 | } 68 | 69 | extension CGFloat: ConstraintMultiplierTarget { 70 | 71 | public var constraintMultiplierTargetValue: CGFloat { 72 | return self 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintOffsetTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintOffsetTarget: ConstraintConstantTarget { 32 | } 33 | 34 | extension Int: ConstraintOffsetTarget { 35 | } 36 | 37 | extension UInt: ConstraintOffsetTarget { 38 | } 39 | 40 | extension Float: ConstraintOffsetTarget { 41 | } 42 | 43 | extension Double: ConstraintOffsetTarget { 44 | } 45 | 46 | extension CGFloat: ConstraintOffsetTarget { 47 | } 48 | 49 | extension ConstraintOffsetTarget { 50 | 51 | internal var constraintOffsetTargetValue: CGFloat { 52 | let offset: CGFloat 53 | if let amount = self as? Float { 54 | offset = CGFloat(amount) 55 | } else if let amount = self as? Double { 56 | offset = CGFloat(amount) 57 | } else if let amount = self as? CGFloat { 58 | offset = CGFloat(amount) 59 | } else if let amount = self as? Int { 60 | offset = CGFloat(amount) 61 | } else if let amount = self as? UInt { 62 | offset = CGFloat(amount) 63 | } else { 64 | offset = 0.0 65 | } 66 | return offset 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintPriorityTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintPriorityTarget { 32 | 33 | var constraintPriorityTargetValue: Float { get } 34 | 35 | } 36 | 37 | extension Int: ConstraintPriorityTarget { 38 | 39 | public var constraintPriorityTargetValue: Float { 40 | return Float(self) 41 | } 42 | 43 | } 44 | 45 | extension UInt: ConstraintPriorityTarget { 46 | 47 | public var constraintPriorityTargetValue: Float { 48 | return Float(self) 49 | } 50 | 51 | } 52 | 53 | extension Float: ConstraintPriorityTarget { 54 | 55 | public var constraintPriorityTargetValue: Float { 56 | return self 57 | } 58 | 59 | } 60 | 61 | extension Double: ConstraintPriorityTarget { 62 | 63 | public var constraintPriorityTargetValue: Float { 64 | return Float(self) 65 | } 66 | 67 | } 68 | 69 | extension CGFloat: ConstraintPriorityTarget { 70 | 71 | public var constraintPriorityTargetValue: Float { 72 | return Float(self) 73 | } 74 | 75 | } 76 | 77 | #if canImport(UIKit) 78 | extension UILayoutPriority: ConstraintPriorityTarget { 79 | 80 | public var constraintPriorityTargetValue: Float { 81 | return self.rawValue 82 | } 83 | 84 | } 85 | #endif 86 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintRelatableTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintRelatableTarget { 32 | } 33 | 34 | extension Int: ConstraintRelatableTarget { 35 | } 36 | 37 | extension UInt: ConstraintRelatableTarget { 38 | } 39 | 40 | extension Float: ConstraintRelatableTarget { 41 | } 42 | 43 | extension Double: ConstraintRelatableTarget { 44 | } 45 | 46 | extension CGFloat: ConstraintRelatableTarget { 47 | } 48 | 49 | extension CGSize: ConstraintRelatableTarget { 50 | } 51 | 52 | extension CGPoint: ConstraintRelatableTarget { 53 | } 54 | 55 | extension ConstraintInsets: ConstraintRelatableTarget { 56 | } 57 | 58 | #if canImport(UIKit) 59 | @available(iOS 11.0, tvOS 11.0, *) 60 | extension ConstraintDirectionalInsets: ConstraintRelatableTarget { 61 | } 62 | #endif 63 | 64 | extension ConstraintItem: ConstraintRelatableTarget { 65 | } 66 | 67 | extension ConstraintView: ConstraintRelatableTarget { 68 | } 69 | 70 | @available(iOS 9.0, OSX 10.11, *) 71 | extension ConstraintLayoutGuide: ConstraintRelatableTarget { 72 | } 73 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintRelation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | internal enum ConstraintRelation : Int { 32 | case equal = 1 33 | case lessThanOrEqual 34 | case greaterThanOrEqual 35 | 36 | internal var layoutRelation: LayoutRelation { 37 | get { 38 | switch(self) { 39 | case .equal: 40 | return .equal 41 | case .lessThanOrEqual: 42 | return .lessThanOrEqual 43 | case .greaterThanOrEqual: 44 | return .greaterThanOrEqual 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/ConstraintView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if canImport(UIKit) 32 | public typealias ConstraintView = UIView 33 | #else 34 | public typealias ConstraintView = NSView 35 | #endif 36 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/LayoutConstraint.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class LayoutConstraint : NSLayoutConstraint { 32 | 33 | public var label: String? { 34 | get { 35 | return self.identifier 36 | } 37 | set { 38 | self.identifier = newValue 39 | } 40 | } 41 | 42 | internal weak var constraint: Constraint? = nil 43 | 44 | } 45 | 46 | internal func ==(lhs: LayoutConstraint, rhs: LayoutConstraint) -> Bool { 47 | // If firstItem or secondItem on either constraint has a dangling pointer 48 | // this comparison can cause a crash. The solution for this is to ensure 49 | // your layout code hold strong references to things like Views, LayoutGuides 50 | // and LayoutAnchors as SnapKit will not keep strong references to any of these. 51 | guard lhs.firstAttribute == rhs.firstAttribute && 52 | lhs.secondAttribute == rhs.secondAttribute && 53 | lhs.relation == rhs.relation && 54 | lhs.priority == rhs.priority && 55 | lhs.multiplier == rhs.multiplier && 56 | lhs.secondItem === rhs.secondItem && 57 | lhs.firstItem === rhs.firstItem else { 58 | return false 59 | } 60 | return true 61 | } 62 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyTracking 6 | 7 | NSPrivacyAccessedAPITypes 8 | 9 | NSPrivacyCollectedDataTypes 10 | 11 | NSPrivacyTrackingDomains 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/Typealiases.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | import Foundation 25 | 26 | #if canImport(UIKit) 27 | import UIKit 28 | #if swift(>=4.2) 29 | typealias LayoutRelation = NSLayoutConstraint.Relation 30 | typealias LayoutAttribute = NSLayoutConstraint.Attribute 31 | #else 32 | typealias LayoutRelation = NSLayoutRelation 33 | typealias LayoutAttribute = NSLayoutAttribute 34 | #endif 35 | typealias LayoutPriority = UILayoutPriority 36 | #else 37 | import AppKit 38 | typealias LayoutRelation = NSLayoutConstraint.Relation 39 | typealias LayoutAttribute = NSLayoutConstraint.Attribute 40 | typealias LayoutPriority = NSLayoutConstraint.Priority 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Sources/UILayoutSupport+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if canImport(UIKit) 25 | import UIKit 26 | #endif 27 | 28 | 29 | @available(iOS 8.0, *) 30 | public extension ConstraintLayoutSupport { 31 | 32 | var snp: ConstraintLayoutSupportDSL { 33 | return ConstraintLayoutSupportDSL(support: self) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/MTDMulticastDelegate/MTDMulticastDelegate-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/MTDMulticastDelegate/MTDMulticastDelegate-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_MTDMulticastDelegate : NSObject 3 | @end 4 | @implementation PodsDummy_MTDMulticastDelegate 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/MTDMulticastDelegate/MTDMulticastDelegate-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/MTDMulticastDelegate/MTDMulticastDelegate-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "MTDMulticastDelegate.h" 14 | #import "MTDOriginMulticastDelegate.h" 15 | #import "MulticastDelegate.h" 16 | 17 | FOUNDATION_EXPORT double MulticastDelegateVersionNumber; 18 | FOUNDATION_EXPORT const unsigned char MulticastDelegateVersionString[]; 19 | 20 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/MTDMulticastDelegate/MTDMulticastDelegate.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MTDMulticastDelegate 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/MTDMulticastDelegate 9 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/MTDMulticastDelegate/MTDMulticastDelegate.modulemap: -------------------------------------------------------------------------------- 1 | framework module MulticastDelegate { 2 | umbrella header "MTDMulticastDelegate-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/MTDMulticastDelegate/MTDMulticastDelegate.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MTDMulticastDelegate 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/MTDMulticastDelegate 9 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks-Debug-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/MTDMulticastDelegate/MulticastDelegate.framework 3 | ${BUILT_PRODUCTS_DIR}/SCNRecorder/SCNRecorder.framework 4 | ${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks-Debug-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MulticastDelegate.framework 2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SCNRecorder.framework 3 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks-Release-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/MTDMulticastDelegate/MulticastDelegate.framework 3 | ${BUILT_PRODUCTS_DIR}/SCNRecorder/SCNRecorder.framework 4 | ${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks-Release-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MulticastDelegate.framework 2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SCNRecorder.framework 3 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MTDMulticastDelegate" "${PODS_CONFIGURATION_BUILD_DIR}/SCNRecorder" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MTDMulticastDelegate/MulticastDelegate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SCNRecorder/SCNRecorder.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" 6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' 7 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift 8 | OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" -framework "MulticastDelegate" -framework "SCNRecorder" -framework "SnapKit" 9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 10 | PODS_BUILD_DIR = ${BUILD_DIR} 11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 13 | PODS_ROOT = ${SRCROOT}/Pods 14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Example { 2 | umbrella header "Pods-Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MTDMulticastDelegate" "${PODS_CONFIGURATION_BUILD_DIR}/SCNRecorder" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MTDMulticastDelegate/MulticastDelegate.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SCNRecorder/SCNRecorder.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" 6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' 7 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift 8 | OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" -framework "MulticastDelegate" -framework "SCNRecorder" -framework "SnapKit" 9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 10 | PODS_BUILD_DIR = ${BUILD_DIR} 11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 13 | PODS_ROOT = ${SRCROOT}/Pods 14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SCNRecorder/SCNRecorder-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.9.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SCNRecorder/SCNRecorder-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SCNRecorder : NSObject 3 | @end 4 | @implementation PodsDummy_SCNRecorder 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SCNRecorder/SCNRecorder-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SCNRecorder/SCNRecorder-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double SCNRecorderVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char SCNRecorderVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SCNRecorder/SCNRecorder.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SCNRecorder 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MTDMulticastDelegate" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 6 | OTHER_LDFLAGS = $(inherited) -framework "MulticastDelegate" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 11 | PODS_ROOT = ${SRCROOT} 12 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 15 | SKIP_INSTALL = YES 16 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SCNRecorder/SCNRecorder.modulemap: -------------------------------------------------------------------------------- 1 | framework module SCNRecorder { 2 | umbrella header "SCNRecorder-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SCNRecorder/SCNRecorder.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SCNRecorder 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MTDMulticastDelegate" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 6 | OTHER_LDFLAGS = $(inherited) -framework "MulticastDelegate" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 11 | PODS_ROOT = ${SRCROOT} 12 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 13 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 14 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 15 | SKIP_INSTALL = YES 16 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/ResourceBundle-SnapKit_Privacy-SnapKit-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 5.7.1 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 5.7.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SnapKit : NSObject 3 | @end 4 | @implementation PodsDummy_SnapKit 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double SnapKitVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char SnapKitVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SnapKit 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift 5 | OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" 6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 10 | PODS_ROOT = ${SRCROOT} 11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SnapKit 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 14 | SKIP_INSTALL = YES 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit.modulemap: -------------------------------------------------------------------------------- 1 | framework module SnapKit { 2 | umbrella header "SnapKit-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SnapKit 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift $(SDKROOT)/usr/lib/swift 5 | OTHER_LDFLAGS = $(inherited) -l"swiftCoreGraphics" 6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 10 | PODS_ROOT = ${SRCROOT} 11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SnapKit 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 14 | SKIP_INSTALL = YES 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Source/.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: 2 | - statement_position 3 | - nesting 4 | included: 5 | - Source 6 | - ../Source 7 | reporter: "xcode" 8 | 9 | identifier_name: 10 | min_length: 1 11 | allowed_symbols: ["_"] 12 | 13 | -------------------------------------------------------------------------------- /Example/Source/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 12/03/2019. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import UIKit 27 | 28 | @UIApplicationMain 29 | class AppDelegate: UIResponder, UIApplicationDelegate { 30 | 31 | lazy var window: UIWindow? = UIWindow(frame: UIScreen.main.bounds) 32 | 33 | func application( 34 | _ application: UIApplication, 35 | willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil 36 | ) -> Bool { 37 | let appearance = UINavigationBarAppearance() 38 | appearance.configureWithTransparentBackground() 39 | UINavigationBar.appearance().standardAppearance = appearance 40 | 41 | let mainViewController = MainViewController() 42 | let navigationController = UINavigationController(rootViewController: mainViewController) 43 | 44 | window?.rootViewController = navigationController 45 | window?.makeKeyAndVisible() 46 | 47 | return true 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Example/Source/Common/Button.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Button.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 19.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | 29 | class Button: UIButton { 30 | 31 | typealias Action = () -> Void 32 | 33 | @objc func _touchUpInside() { touchUpInside?() } 34 | var touchUpInside: Action? { 35 | didSet { 36 | switch (oldValue, touchUpInside) { 37 | case (.none, .some): 38 | addTarget(self, action: #selector(_touchUpInside), for: .touchUpInside) 39 | case (.some, .none): 40 | removeTarget(self, action: #selector(_touchUpInside), for: .touchUpInside) 41 | default: break 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Example/Source/Common/View.swift: -------------------------------------------------------------------------------- 1 | // 2 | // View.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 19.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | 29 | class View: UIView { 30 | 31 | override init(frame: CGRect) { 32 | super.init(frame: frame) 33 | setupView() 34 | } 35 | 36 | @available(*, unavailable) 37 | required init?(coder aDecoder: NSCoder) { 38 | fatalError("init(coder:) has not been implemented") 39 | } 40 | 41 | @available(*, unavailable) 42 | override func awakeFromNib() { 43 | fatalError("awakeFromNib() has not been implemented") 44 | } 45 | 46 | private func setupView() { 47 | addSubviews() 48 | makeConstraints() 49 | } 50 | 51 | func addSubviews() { } 52 | 53 | func makeConstraints() { } 54 | } 55 | -------------------------------------------------------------------------------- /Example/Source/Common/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 19.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | 29 | class ViewController: UIViewController { 30 | 31 | init() { super.init(nibName: nil, bundle: nil) } 32 | 33 | @available(*, unavailable) 34 | required init?(coder aDecoder: NSCoder) { 35 | fatalError("init(coder:) has not been implemented") 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Example/Source/Common/Weakify/Weakifiable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Weakifiable.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 19.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | protocol Weakifiable: AnyObject { } 29 | 30 | extension Weakifiable { 31 | 32 | typealias This = Self 33 | 34 | func weakify( 35 | _ closure: @escaping (Self) -> () -> Void 36 | ) -> () -> Void { 37 | Global.weakify(self, closure) 38 | } 39 | 40 | func weakify( 41 | _ closure: @escaping (Self) -> () -> Result 42 | ) -> () -> Result? { 43 | Global.weakify(self, closure) 44 | } 45 | 46 | func weakify( 47 | _ closure: @escaping (Self) -> (Parameter) -> Void 48 | ) -> (Parameter) -> Void { 49 | Global.weakify(self, closure) 50 | } 51 | 52 | func weakify( 53 | _ closure: @escaping (Self) -> (Parameter) -> Result 54 | ) -> (Parameter) -> Result? { 55 | Global.weakify(self, closure) 56 | } 57 | } 58 | 59 | extension NSObject: Weakifiable { } 60 | -------------------------------------------------------------------------------- /Example/Source/Content/Metal/MetalShaderTypes.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalShaderTypes.h 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 18.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #ifndef MetalShaderTypes_h 27 | #define MetalShaderTypes_h 28 | 29 | #include 30 | 31 | typedef enum MetalVertexInputIndex 32 | { 33 | MetalVertexInputIndexVertices = 0, 34 | MetalVertexInputIndexUniforms = 1, 35 | } MetalVertexInputIndex; 36 | 37 | typedef struct 38 | { 39 | vector_float2 position; 40 | vector_float3 color; 41 | } MetalVertex; 42 | 43 | typedef struct 44 | { 45 | float scale; 46 | vector_uint2 viewportSize; 47 | } MetalUniforms; 48 | 49 | 50 | #endif /* MetalShaderTypes_h */ 51 | -------------------------------------------------------------------------------- /Example/Source/Content/RealityKit/ARView+MetalRecordable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ARView+SceneRecordableView.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 17.08.2020. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import RealityKit 28 | import SCNRecorder 29 | 30 | private var sceneRecorderKey: UInt8 = 0 31 | private var cancellableKey: UInt8 = 0 32 | 33 | @available(iOS 13.0, *) 34 | extension ARView: @retroactive MetalRecordable { 35 | 36 | #if !targetEnvironment(simulator) 37 | public var recordableLayer: RecordableLayer? { layer.sublayers?.first as? RecordableLayer } 38 | #else 39 | public var recordableLayer: RecordableLayer? { layer as? RecordableLayer } 40 | #endif 41 | } 42 | -------------------------------------------------------------------------------- /Example/Source/Content/RealityKit/ARView+SelfSceneRecordable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ARView.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 17.08.2020. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import RealityKit 28 | import SCNRecorder 29 | import Combine 30 | 31 | private var cancellableKey: UInt8 = 0 32 | 33 | @available(iOS 13.0, *) 34 | extension ARView: @retroactive SelfSceneRecordable { 35 | 36 | var _cancelable: Cancellable? { 37 | get { 38 | objc_getAssociatedObject( 39 | self, 40 | &cancellableKey 41 | ) as? Cancellable 42 | } 43 | set { 44 | objc_setAssociatedObject( 45 | self, 46 | &cancellableKey, 47 | newValue, 48 | .OBJC_ASSOCIATION_RETAIN 49 | ) 50 | } 51 | } 52 | 53 | public func injectRecorder() { 54 | do { 55 | sceneRecorder = try SceneRecorder(self) 56 | 57 | #if !targetEnvironment(simulator) 58 | session.delegate = sceneRecorder 59 | #endif 60 | 61 | _cancelable?.cancel() 62 | _cancelable = scene.subscribe( 63 | to: SceneEvents.Update.self 64 | ) { [weak sceneRecorder] (_) in 65 | sceneRecorder?.render() 66 | } 67 | } 68 | catch { assertionFailure("\(error)") } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Example/Source/Controls/Controllable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Controllable.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 19.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | import SCNRecorder 29 | 30 | protocol Controllable { 31 | 32 | func takePhoto(handler: @escaping (UIImage) -> Void) 33 | 34 | func startVideoRecording(size: CGSize) throws -> VideoRecording 35 | 36 | func finishVideoRecording(handler: @escaping (URL) -> Void) 37 | } 38 | 39 | typealias ControllableViewController = UIViewController & Controllable 40 | -------------------------------------------------------------------------------- /Example/Source/Example-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "MetalShaderTypes.h" 6 | -------------------------------------------------------------------------------- /Example/Source/Extensions/UIColor+Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Helpers.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 01.12.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | 29 | extension UIColor { 30 | 31 | var vec3: vector_float3 { 32 | var colors: (red: CGFloat, green: CGFloat, blue: CGFloat) = (0, 0, 0) 33 | getRed(&colors.red, green: &colors.green, blue: &colors.blue, alpha: nil) 34 | return vector_float3(Float(colors.red), Float(colors.green), Float(colors.blue)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Example/Source/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | LSRequiresIPhoneOS 22 | 23 | NSCameraUsageDescription 24 | To show you amazing AR! 25 | NSMicrophoneUsageDescription 26 | To capture your amazing voice! 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | arkit 33 | 34 | UIStatusBarHidden 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | UIInterfaceOrientationPortraitUpsideDown 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Example/Source/Preview/PhotoPreviewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoPreviewController.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 12/03/2019. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | 29 | final class PhotoPreviewController: ViewController { 30 | 31 | let photo: UIImage 32 | 33 | init(photo: UIImage) { 34 | self.photo = photo 35 | super.init() 36 | } 37 | 38 | override func loadView() { 39 | view = UIImageView(image: photo) 40 | } 41 | 42 | override func viewDidLoad() { 43 | super.viewDidLoad() 44 | 45 | navigationItem.rightBarButtonItem = UIBarButtonItem( 46 | barButtonSystemItem: .action, 47 | target: self, 48 | action: #selector(share) 49 | ) 50 | } 51 | 52 | @objc func share() { 53 | 54 | let format = UIGraphicsImageRendererFormat() 55 | format.scale = 1.0 56 | format.preferredRange = .extended 57 | format.opaque = true 58 | 59 | let data = photo.jpegData(compressionQuality: 1.0)! 60 | 61 | let url = FileManager.default.temporaryDirectory.appendingPathComponent("photo.jpg") 62 | try? data.write(to: url) 63 | 64 | present( 65 | UIActivityViewController(activityItems: [url], applicationActivities: nil), 66 | animated: true, 67 | completion: nil 68 | ) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Example/Source/Preview/VideoPreviewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoPreviewController.swift 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 19.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVKit 28 | 29 | final class VideoPreviewController: AVPlayerViewController { 30 | 31 | let videoURL: URL 32 | 33 | init(videoURL: URL) { 34 | self.videoURL = videoURL 35 | super.init(nibName: nil, bundle: nil) 36 | } 37 | 38 | required init?(coder: NSCoder) { 39 | fatalError("init(coder:) has not been implemented") 40 | } 41 | 42 | override func viewDidLoad() { 43 | super.viewDidLoad() 44 | player = AVPlayer(url: videoURL) 45 | 46 | navigationItem.rightBarButtonItem = UIBarButtonItem( 47 | barButtonSystemItem: .action, 48 | target: self, 49 | action: #selector(share) 50 | ) 51 | } 52 | 53 | override func viewDidDisappear(_ animated: Bool) { 54 | super.viewDidAppear(animated) 55 | 56 | if isMovingFromParent { 57 | try? FileManager.default.removeItem(at: videoURL) 58 | } 59 | } 60 | 61 | @objc func share() { 62 | present( 63 | UIActivityViewController(activityItems: [videoURL], applicationActivities: nil), 64 | animated: true, 65 | completion: nil 66 | ) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Example/Source/Resources/0-9.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gorastudio-git/SCNRecorder/795dc264708c814a4ce6041e605e125f2d663123/Example/Source/Resources/0-9.mp3 -------------------------------------------------------------------------------- /Example/Source/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/Source/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Source/Resources/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/Source/Resources/Experience.rcproject/Library/ProjectLibrary/Contents.json: -------------------------------------------------------------------------------- 1 | [ 2 | 3 | ] -------------------------------------------------------------------------------- /Example/Source/Resources/Experience.rcproject/Library/ProjectLibrary/Version.json: -------------------------------------------------------------------------------- 1 | { 2 | "LibraryID" : "BBB5EDD2-CBE1-49E5-931D-2C81F724D19D", 3 | "Version" : "1.0" 4 | } -------------------------------------------------------------------------------- /Example/Source/Resources/Experience.rcproject/SceneThumbnails/F9610871-0955-494F-A5C3-51D1A281BAB3.thumbnails/square: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gorastudio-git/SCNRecorder/795dc264708c814a4ce6041e605e125f2d663123/Example/Source/Resources/Experience.rcproject/SceneThumbnails/F9610871-0955-494F-A5C3-51D1A281BAB3.thumbnails/square -------------------------------------------------------------------------------- /Example/Source/Resources/Experience.rcproject/SceneThumbnails/F9610871-0955-494F-A5C3-51D1A281BAB3.thumbnails/wide: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gorastudio-git/SCNRecorder/795dc264708c814a4ce6041e605e125f2d663123/Example/Source/Resources/Experience.rcproject/SceneThumbnails/F9610871-0955-494F-A5C3-51D1A281BAB3.thumbnails/wide -------------------------------------------------------------------------------- /Example/Source/Resources/art.scnassets/ship.scn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gorastudio-git/SCNRecorder/795dc264708c814a4ce6041e605e125f2d663123/Example/Source/Resources/art.scnassets/ship.scn -------------------------------------------------------------------------------- /Example/Source/Resources/art.scnassets/texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gorastudio-git/SCNRecorder/795dc264708c814a4ce6041e605e125f2d663123/Example/Source/Resources/art.scnassets/texture.png -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2021 GORA Studio. https://gora.studio 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "MulticastDelegate", 6 | "repositoryURL": "https://github.com/v-grigoriev/MulticastDelegate.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "d650db9f294d2ebeab9e48e1825b6a16af860a62", 10 | "version": "1.0.1" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "SCNRecorder", 7 | platforms: [ .iOS(.v12) ], 8 | products: [ 9 | .library( 10 | name: "SCNRecorder", 11 | targets: ["SCNRecorder"]), 12 | ], 13 | dependencies: [ 14 | .package( 15 | url: "https://github.com/v-grigoriev/MulticastDelegate.git", 16 | from: "1.0.1" 17 | ) 18 | ], 19 | targets: [ 20 | .target( 21 | name: "SCNRecorder", 22 | dependencies: ["MulticastDelegate"], 23 | path: "Sources" 24 | ) 25 | ] 26 | ) 27 | -------------------------------------------------------------------------------- /SCNRecorder.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'SCNRecorder' 3 | s.version = '2.9.0' 4 | s.summary = 'A lags-free recorder of ARKit and SceneKit for iOS in Swift' 5 | s.homepage = 'https://github.com/gorastudio/SCNRecorder' 6 | s.license = { :type => 'MIT', :file => 'LICENSE.md' } 7 | s.author = { 'Vladislav Grigoryev' => 'dev.grigoriev@gmail.com' } 8 | s.platform = :ios, '12.0' 9 | s.source = { :git => 'https://github.com/gorastudio-ceo/SCNRecorder.git', :tag => s.version.to_s } 10 | s.module_name = 'SCNRecorder' 11 | s.swift_version = '5.0' 12 | s.source_files = 'Sources/**/*.{swift}' 13 | s.dependency 'MTDMulticastDelegate' 14 | 15 | s.app_spec 'Example' do |app_spec| 16 | app_spec.name = "Example" 17 | app_spec.platform = :ios, '13.0' 18 | app_spec.source_files = 'Example/Source/**/*.{m,swift,metal}', 'Example/Source/Content/**/*.{h}' 19 | app_spec.preserve_paths = 'Example/Source/Example-Bridging-Header.h' 20 | app_spec.resources = 'Example/Source/Resources/**/*.{scnassets,xcassets}' 21 | app_spec.pod_target_xcconfig = { 22 | "SWIFT_OBJC_BRIDGING_HEADER" => "$(PODS_TARGET_SRCROOT)/Example/Source/Example-Bridging-Header.h" 23 | } 24 | 25 | app_spec.dependency 'SnapKit', '~> 5.7.1' 26 | end 27 | 28 | s.test_spec 'Tests' do |test_spec| 29 | test_spec.platform = :ios, '13.0' 30 | test_spec.requires_app_host = true 31 | test_spec.app_host_name = 'SCNRecorder/Example' 32 | test_spec.source_files = 'SCNRecorderTests/**/*.{m,swift,metal}', 'SCNRecorderTests/Metal/**/*.h' 33 | test_spec.preserve_paths = 'SCNRecorderTests/SCNRecorderTests-Bridging-Header.h' 34 | test_spec.pod_target_xcconfig = { 35 | "SWIFT_OBJC_BRIDGING_HEADER" => "$(PODS_TARGET_SRCROOT)/SCNRecorderTests/SCNRecorderTests-Bridging-Header.h" 36 | } 37 | 38 | test_spec.dependency 'SCNRecorder/Example' 39 | end 40 | end 41 | 42 | 43 | -------------------------------------------------------------------------------- /SCNRecorder.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SCNRecorder.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SCNRecorder.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SCNRecorder.xcodeproj/xcshareddata/xcbaselines/D57464AD25725BA70025578A.xcbaseline/36E9BB1D-0C31-4B9C-B571-24EE0254D4FB.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | MetalPixelBufferProducerTests 8 | 9 | testBGR10XRPerfomance() 10 | 11 | com.apple.XCTPerformanceMetric_WallClockTime 12 | 13 | baselineAverage 14 | 0.005 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | testBGR10XRSRGBPerfomance() 20 | 21 | com.apple.XCTPerformanceMetric_WallClockTime 22 | 23 | baselineAverage 24 | 0.005 25 | baselineIntegrationDisplayName 26 | Local Baseline 27 | 28 | 29 | testBGRA10XRPerfomance() 30 | 31 | com.apple.XCTPerformanceMetric_WallClockTime 32 | 33 | baselineAverage 34 | 0.005 35 | baselineIntegrationDisplayName 36 | Local Baseline 37 | 38 | 39 | testBGRA10XRSRGBPerfomance() 40 | 41 | com.apple.XCTPerformanceMetric_WallClockTime 42 | 43 | baselineAverage 44 | 0.005 45 | baselineIntegrationDisplayName 46 | Local Baseline 47 | 48 | 49 | testBGRA8UnormPerfomance() 50 | 51 | com.apple.XCTPerformanceMetric_WallClockTime 52 | 53 | baselineAverage 54 | 0.005 55 | baselineIntegrationDisplayName 56 | Local Baseline 57 | 58 | 59 | testBGRA8UnormSRGBPerfomance() 60 | 61 | com.apple.XCTPerformanceMetric_WallClockTime 62 | 63 | baselineAverage 64 | 0.005 65 | baselineIntegrationDisplayName 66 | Local Baseline 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /SCNRecorder.xcodeproj/xcshareddata/xcbaselines/D57464AD25725BA70025578A.xcbaseline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runDestinationsByUUID 6 | 7 | 36E9BB1D-0C31-4B9C-B571-24EE0254D4FB 8 | 9 | targetArchitecture 10 | arm64e 11 | targetDevice 12 | 13 | modelCode 14 | iPhone13,2 15 | platformIdentifier 16 | com.apple.platform.iphoneos 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SCNRecorder.xcodeproj/xcshareddata/xcschemes/SCNRecorder.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /SCNRecorderTests/Extensions/MTLPixelFormat+Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MTLPixelFormat+Helpers.swift 3 | // SCNRecorderTests 4 | // 5 | // Created by Vladislav Grigoryev on 04.12.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import Metal 28 | @testable import SCNRecorder 29 | 30 | extension MTLPixelFormat { 31 | 32 | static let supportedPixelFormatsNames: [Self: String] = [ 33 | .bgra8Unorm: "bgra8Unorm", 34 | .bgra8Unorm_srgb: "bgra8Unorm_srgb", 35 | .bgr10_xr: "bgr10_xr", 36 | .bgr10_xr_srgb: "bgr10_xr_srgb", 37 | .bgra10_xr: "bgra10_xr", 38 | .bgra10_xr_srgb: "bgra10_xr_srgb" 39 | ] 40 | 41 | static let wideGamutPixelFormats = Set([ 42 | .bgr10_xr, 43 | .bgr10_xr_srgb, 44 | .bgra10_xr, 45 | .bgra10_xr_srgb 46 | ]) 47 | 48 | static let srgbPixelFormats = Set([ 49 | .bgra8Unorm_srgb, 50 | .bgr10_xr_srgb, 51 | .bgra10_xr_srgb 52 | ]) 53 | 54 | var name: String { Self.supportedPixelFormatsNames[self] ?? "unknown \(rawValue)" } 55 | 56 | var isWideGamut: Bool { Self.wideGamutPixelFormats.contains(self) } 57 | 58 | var isSRGB: Bool { Self.srgbPixelFormats.contains(self) } 59 | } 60 | -------------------------------------------------------------------------------- /SCNRecorderTests/Extensions/UIColor+Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Helpers.swift 3 | // SCNRecorderTests 4 | // 5 | // Created by Vladislav Grigoryev on 04.12.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | import simd 29 | 30 | extension UIColor { 31 | 32 | var vec3: vector_float3 { 33 | var colors: (red: CGFloat, green: CGFloat, blue: CGFloat) = (0, 0, 0) 34 | getRed(&colors.red, green: &colors.green, blue: &colors.blue, alpha: nil) 35 | return vector_float3(Float(colors.red), Float(colors.green), Float(colors.blue)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SCNRecorderTests/Extensions/VideoSetting.Codec+Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoSetting.Codec+Helpers.swift 3 | // SCNRecorderTests 4 | // 5 | // Created by Vladislav Grigoryev on 05.12.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | @testable import SCNRecorder 28 | 29 | extension VideoSettings.Codec { 30 | 31 | var name: String { 32 | switch self { 33 | case .hevc: return "hevc" 34 | case .hevcWithAlpha: return "hevcWithAlpha" 35 | case .h264: return "h264" 36 | case .jpeg: return "jpeg" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SCNRecorderTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SCNRecorderTests/Metal/TestMetalShaderTypes.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalShaderTypes.h 3 | // Example 4 | // 5 | // Created by Vladislav Grigoryev on 18.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #ifndef MetalShaderTypes_h 27 | #define MetalShaderTypes_h 28 | 29 | #include 30 | 31 | typedef enum MetalVertexInputIndex 32 | { 33 | MetalVertexInputIndexVertices = 0, 34 | MetalVertexInputIndexUniforms = 1, 35 | } MetalVertexInputIndex; 36 | 37 | typedef struct 38 | { 39 | vector_float2 position; 40 | vector_float3 color; 41 | } MetalVertex; 42 | 43 | typedef struct 44 | { 45 | float scale; 46 | vector_uint2 viewportSize; 47 | } MetalUniforms; 48 | 49 | 50 | #endif /* MetalShaderTypes_h */ 51 | -------------------------------------------------------------------------------- /SCNRecorderTests/SCNRecorderTests-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCNRecorderTests-Bridging-Header.h 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 04.12.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #ifndef SCNRecorderTests_Bridging_Header_h 27 | #define SCNRecorderTests_Bridging_Header_h 28 | 29 | #import "TestMetalShaderTypes.h" 30 | 31 | #endif /* SCNRecorderTests_Bridging_Header_h */ 32 | -------------------------------------------------------------------------------- /SCNRecorderTestsApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SCNRecorderTestsApp 4 | // 5 | // Created by Vladislav Grigoryev on 06.12.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import UIKit 27 | 28 | @main 29 | class AppDelegate: UIResponder, UIApplicationDelegate { 30 | 31 | func application( 32 | _ application: UIApplication, 33 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 34 | ) -> Bool { 35 | true 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /SCNRecorderTestsApp/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SCNRecorderTestsApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /SCNRecorderTestsApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SCNRecorderTestsApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SCNRecorderTestsApp/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SCNRecorderTestsApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSupportsIndirectInputEvents 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /SCNRecorderTestsApp/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SCNRecorderTestsApp 4 | // 5 | // Created by Vladislav Grigoryev on 06.12.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import UIKit 27 | 28 | class ViewController: UIViewController { 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | // Do any additional setup after loading the view. 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Sources/AudioSettings.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AudioSettings.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 15.09.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | 29 | public struct AudioSettings { 30 | 31 | static let defaultSampleRate = 44100.0 32 | 33 | static let defaultNumberOfChannels = 1 34 | 35 | public var format = kAudioFormatMPEG4AAC 36 | 37 | public var sampleRate = defaultSampleRate 38 | 39 | public var numberOfChannels = defaultNumberOfChannels 40 | } 41 | 42 | extension AudioSettings { 43 | 44 | init(audioFormat: AVAudioFormat) { 45 | sampleRate = audioFormat.sampleRate 46 | numberOfChannels = Int(audioFormat.channelCount) 47 | } 48 | 49 | var outputSettings: [String: Any] { 50 | [ 51 | AVFormatIDKey: format, 52 | AVSampleRateKey: sampleRate, 53 | AVNumberOfChannelsKey: numberOfChannels 54 | ] 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/Extensions/CALayer+InterfaceOrientation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+Window.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 03.06.2021. 6 | // Copyright © 2021 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | 29 | extension CALayer { 30 | 31 | var window: UIWindow? { 32 | (delegate as? UIView)?.window 33 | ?? superlayer?.window 34 | ?? UIApplication.shared.keyWindow 35 | } 36 | 37 | public var interfaceOrientation: UIInterfaceOrientation { 38 | if #available(iOS 13.0, *) { 39 | return window?.windowScene?.interfaceOrientation ?? _interfaceOrientation 40 | } else { 41 | return _interfaceOrientation 42 | } 43 | } 44 | 45 | private var _interfaceOrientation: UIInterfaceOrientation { 46 | guard let window = window else { return .unknown } 47 | let fixedCoordinateSpace = window.screen.fixedCoordinateSpace 48 | 49 | let origin = convert(frame.origin, to: window.layer) 50 | let fixedOrigin = window.convert(origin, to: fixedCoordinateSpace) 51 | 52 | let isXGreater = fixedOrigin.x > origin.x 53 | let isYGreater = fixedOrigin.y > origin.y 54 | 55 | switch (isXGreater, isYGreater) { 56 | case (true, true): return .portraitUpsideDown 57 | case (true, false): return .landscapeRight 58 | case (false, true): return .landscapeLeft 59 | case (false, false): return .portrait 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/Extensions/IOSurface+Size.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IOSurface+Size.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 04.06.2021. 6 | // Copyright © 2021 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | 29 | extension IOSurface { 30 | 31 | var size: CGSize { CGSize(width: width, height: height) } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Helpers/AssociatedStorage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AssociatedStorage.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 30.05.2020. 6 | // 7 | 8 | import Foundation 9 | 10 | struct AssociatedStorage { 11 | 12 | let object: AnyObject 13 | 14 | let key: UnsafeRawPointer 15 | 16 | let policy: objc_AssociationPolicy 17 | 18 | init(object: AnyObject, key: UnsafeRawPointer, policy: objc_AssociationPolicy) { 19 | self.object = object 20 | self.key = key 21 | self.policy = policy 22 | } 23 | 24 | func get() -> T? { objc_getAssociatedObject(object, key) as? T } 25 | 26 | nonmutating func set(_ value: T?) { objc_setAssociatedObject(object, key, value, policy) } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/Helpers/AudioAdapter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AudioAdapter.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 26.04.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | 29 | final class AudioAdapter: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate { 30 | 31 | typealias Callback = (_ sampleBuffer: CMSampleBuffer) -> Void 32 | 33 | let output: AVCaptureAudioDataOutput 34 | 35 | let queue: DispatchQueue 36 | 37 | let callback: Callback 38 | 39 | init(queue: DispatchQueue, callback: @escaping Callback) { 40 | self.queue = queue 41 | self.callback = callback 42 | output = AVCaptureAudioDataOutput() 43 | 44 | super.init() 45 | output.setSampleBufferDelegate(self, queue: queue) 46 | } 47 | 48 | @objc func captureOutput( 49 | _ output: AVCaptureOutput, 50 | didOutput sampleBuffer: CMSampleBuffer, 51 | from connection: AVCaptureConnection 52 | ) { 53 | callback(sampleBuffer) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/Helpers/Buffer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Buffer.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 24.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | final class Buffer { 29 | 30 | static func zeroed(size: Int, alignment: Int = 1) -> Buffer { 31 | let buffer = Buffer(size: size, alignment: alignment) 32 | buffer.ptr.initializeMemory(as: UInt8.self, repeating: 0, count: size) 33 | return buffer 34 | } 35 | 36 | let size: Int 37 | 38 | let alignment: Int 39 | 40 | let ptr: UnsafeMutableRawPointer 41 | 42 | init(size: Int, alignment: Int) { 43 | self.size = size 44 | self.alignment = alignment 45 | self.ptr = .allocate(byteCount: size, alignment: alignment) 46 | } 47 | 48 | deinit { ptr.deallocate() } 49 | } 50 | -------------------------------------------------------------------------------- /Sources/Helpers/Multithreading/Atomic.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Atomic.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 17.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | public protocol Atomic: AnyObject { 29 | 30 | associatedtype Value 31 | 32 | @discardableResult 33 | func withValue(_ action: (Value) throws -> Result) rethrows -> Result 34 | 35 | @discardableResult 36 | func modify(_ action: (inout Value) throws -> Result) rethrows -> Result 37 | } 38 | 39 | public extension Atomic { 40 | 41 | var value: Value { 42 | get { withValue { $0 } } 43 | set { swap(newValue) } 44 | } 45 | 46 | @discardableResult 47 | func swap(_ newValue: Value) -> Value { 48 | modify { (value: inout Value) in 49 | let oldValue = value 50 | value = newValue 51 | return oldValue 52 | } 53 | } 54 | } 55 | 56 | public extension Atomic where Value: SCNObservableInterface { 57 | 58 | var observer: Value.Observer? { 59 | get { value.observer } 60 | set { value.observer = newValue } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/Helpers/Multithreading/Dispatch/DispatchAtomic.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchAtomic.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 17.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | @propertyWrapper 29 | public final class DispatchAtomic: Atomic { 30 | 31 | private var _wrappedValue: Value 32 | 33 | public let queue: DispatchQueue 34 | 35 | public var wrappedValue: Value { 36 | get { value } 37 | set { value = newValue } 38 | } 39 | 40 | public var projectedValue: DispatchAtomic { self } 41 | 42 | public init(wrappedValue: Value) { 43 | self._wrappedValue = wrappedValue 44 | self.queue = DispatchQueue(label: "\(type(of: self))", attributes: [.concurrent]) 45 | } 46 | 47 | public init(wrappedValue: Value, queue: DispatchQueue) { 48 | self._wrappedValue = wrappedValue 49 | self.queue = queue 50 | } 51 | 52 | @discardableResult 53 | public func withValue(_ action: (Value) throws -> Result) rethrows -> Result { 54 | try queue.sync { try action(_wrappedValue) } 55 | } 56 | 57 | @discardableResult 58 | public func modify(_ action: (inout Value) throws -> Result) rethrows -> Result { 59 | try queue.sync(flags: .barrier) { try action(&_wrappedValue) } 60 | } 61 | 62 | public func asyncModify(_ action: @escaping (inout Value) -> Void) { 63 | queue.async(flags: .barrier) { action(&self._wrappedValue) } 64 | } 65 | } 66 | 67 | extension DispatchAtomic: SCNObservableInterface where Value: SCNObservableInterface { } 68 | -------------------------------------------------------------------------------- /Sources/Helpers/Multithreading/ReadWrite/ReadWriteAtomic.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReadWriteAtomic.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 17.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | @propertyWrapper 29 | public final class ReadWriteAtomic: Atomic { 30 | 31 | private let lock = ReadWriteLock() 32 | 33 | private var _wrappedValue: Value 34 | 35 | public var wrappedValue: Value { 36 | get { value } 37 | set { value = newValue } 38 | } 39 | 40 | public var projectedValue: ReadWriteAtomic { self } 41 | 42 | public init(wrappedValue: Value) { self._wrappedValue = wrappedValue } 43 | 44 | @discardableResult 45 | public func withValue(_ action: (Value) throws -> Result) rethrows -> Result { 46 | try lock.readLocked { try action(_wrappedValue) } 47 | } 48 | 49 | @discardableResult 50 | public func modify(_ action: (inout Value) throws -> Result) rethrows -> Result { 51 | try lock.writeLocked { try action(&_wrappedValue) } 52 | } 53 | } 54 | 55 | extension ReadWriteAtomic: SCNObservableInterface where Value: SCNObservableInterface { } 56 | -------------------------------------------------------------------------------- /Sources/Helpers/Multithreading/ReadWrite/ReadWriteLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReadWriteLock.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 17.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | public final class ReadWriteLock { 29 | 30 | private var readWriteLock: pthread_rwlock_t 31 | 32 | public init() { 33 | readWriteLock = pthread_rwlock_t() 34 | pthread_rwlock_init(&readWriteLock, nil) 35 | } 36 | 37 | deinit { pthread_rwlock_destroy(&readWriteLock) } 38 | 39 | public func readLock() { pthread_rwlock_rdlock(&readWriteLock) } 40 | 41 | public func writeLock() { pthread_rwlock_wrlock(&readWriteLock) } 42 | 43 | public func unlock() { pthread_rwlock_unlock(&readWriteLock) } 44 | 45 | public func tryRead() -> Bool { pthread_rwlock_tryrdlock(&readWriteLock) == 0 } 46 | 47 | public func tryWrite() -> Bool { pthread_rwlock_trywrlock(&readWriteLock) == 0 } 48 | } 49 | 50 | public extension ReadWriteLock { 51 | 52 | @discardableResult 53 | func readLocked(_ action: () throws -> Result) rethrows -> Result { 54 | readLock() 55 | defer { unlock() } 56 | return try action() 57 | } 58 | 59 | @discardableResult 60 | func writeLocked(_ action: () throws -> Result) rethrows -> Result { 61 | writeLock() 62 | defer { unlock() } 63 | return try action() 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Sources/Helpers/Multithreading/Unfair/UnfairAtomic.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnfairAtomic.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 29.12.2019. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | @propertyWrapper 29 | public final class UnfairAtomic: Atomic { 30 | 31 | private let lock = UnfairLock() 32 | 33 | private var _wrappedValue: Value 34 | 35 | public var wrappedValue: Value { 36 | get { value } 37 | set { value = newValue } 38 | } 39 | 40 | public var projectedValue: UnfairAtomic { self } 41 | 42 | public init(wrappedValue: Value) { self._wrappedValue = wrappedValue } 43 | 44 | @discardableResult 45 | public func withValue(_ action: (Value) throws -> Result) rethrows -> Result { 46 | try lock.locked { try action(_wrappedValue) } 47 | } 48 | 49 | @discardableResult 50 | public func modify(_ action: (inout Value) throws -> Result) rethrows -> Result { 51 | try lock.locked { try action(&_wrappedValue) } 52 | } 53 | } 54 | 55 | extension UnfairAtomic: SCNObservableInterface where Value: SCNObservableInterface { } 56 | -------------------------------------------------------------------------------- /Sources/Helpers/Multithreading/Unfair/UnfairLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnfairLock.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 29.12.2019. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | public final class UnfairLock { 29 | 30 | let unfairLock: os_unfair_lock_t 31 | 32 | public init() { 33 | unfairLock = .allocate(capacity: 1) 34 | unfairLock.initialize(to: os_unfair_lock()) 35 | } 36 | 37 | deinit { 38 | unfairLock.deinitialize(count: 1) 39 | unfairLock.deallocate() 40 | } 41 | 42 | public func `try`() -> Bool { os_unfair_lock_trylock(unfairLock) } 43 | 44 | public func lock() { os_unfair_lock_lock(unfairLock) } 45 | 46 | public func unlock() { os_unfair_lock_unlock(unfairLock) } 47 | } 48 | 49 | public extension UnfairLock { 50 | 51 | @discardableResult 52 | func locked(_ action: () throws -> Result) rethrows -> Result { 53 | lock() 54 | defer { unlock() } 55 | return try action() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Sources/Helpers/Property.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Property.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 29.12.2019. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | public final class Property { 29 | 30 | public internal(set) var value: Value { didSet { observer?(value) } } 31 | 32 | public var observer: ((Value) -> Void)? 33 | 34 | init(_ value: Value) { self.value = value } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/Helpers/Updater.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Updater.swift 3 | // Example 4 | // 5 | // Created by VG on 18.12.2020. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | final class Updater { 13 | 14 | lazy var displayLink: CADisplayLink = { 15 | let displayLink = CADisplayLink(target: self, selector: #selector(update)) 16 | displayLink.isPaused = true 17 | displayLink.add(to: .main, forMode: .common) 18 | return displayLink 19 | }() 20 | 21 | var preferredUpdatesPerSecond: Int { 22 | get { displayLink.preferredFramesPerSecond } 23 | set { displayLink.preferredFramesPerSecond = newValue } 24 | } 25 | 26 | var isPaused: Bool { 27 | get { displayLink.isPaused } 28 | set { displayLink.isPaused = newValue } 29 | } 30 | 31 | var onUpdate: (() -> Void)? 32 | 33 | func invalidate() { displayLink.invalidate() } 34 | 35 | @objc func update() { onUpdate?() } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/Helpers/Weak.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Weak.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 29.12.2019. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | @propertyWrapper 29 | final class Weak { 30 | 31 | private weak var _wrappedValue: AnyObject? 32 | 33 | var wrappedValue: Object? { 34 | get { _wrappedValue as? Object } 35 | set { _wrappedValue = newValue } 36 | } 37 | 38 | init(_ object: Object) { self._wrappedValue = object } 39 | 40 | init(wrappedValue: Object?) { self._wrappedValue = wrappedValue } 41 | 42 | func get() -> Object? { wrappedValue } 43 | } 44 | -------------------------------------------------------------------------------- /Sources/Helpers/WeakCollection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeakCollection.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 27.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | @propertyWrapper 29 | struct WeakCollection { 30 | 31 | private var _wrappedValue: [Weak] 32 | 33 | var wrappedValue: [Value] { 34 | get { _wrappedValue.lazy.compactMap { $0.get() } } 35 | set { _wrappedValue = newValue.map(Weak.init) } 36 | } 37 | 38 | init(wrappedValue: [Value]) { self._wrappedValue = wrappedValue.map(Weak.init) } 39 | 40 | mutating func compact() { _wrappedValue = { _wrappedValue }() } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/MediaSession/MediaSessionInput.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MediaSessionInput.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 24.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | import UIKit 29 | 30 | 31 | internal typealias MediaSessionInput_SampleBufferAudio = AudioMediaSessionInput & SampleBufferInput 32 | internal typealias MediaSessionInput_SampleBufferVideo = VideoMediaSessionInput & SampleBufferInput 33 | internal typealias MediaSessionInput_PixelBufferVideo = VideoMediaSessionInput & BufferInput 34 | 35 | 36 | internal 37 | protocol MediaSessionInput { 38 | 39 | func start() 40 | 41 | func stop() 42 | } 43 | 44 | internal 45 | protocol AudioMediaSessionInput: MediaSessionInput { 46 | 47 | func recommendedAudioSettingsForAssetWriter( 48 | writingTo outputFileType: AVFileType 49 | ) -> [String: Any] 50 | } 51 | 52 | internal 53 | protocol VideoMediaSessionInput: MediaSessionInput { 54 | 55 | var size: CGSize { get } 56 | 57 | var videoColorProperties: [String: String]? { get } 58 | 59 | var videoTransform: CGAffineTransform { get } 60 | 61 | var imageOrientation: UIImage.Orientation { get } 62 | } 63 | 64 | internal 65 | protocol SampleBufferInput: AnyObject { 66 | 67 | var output: ((CMSampleBuffer) -> Void)? { get set } 68 | } 69 | 70 | internal 71 | protocol BufferInput: AnyObject { 72 | 73 | var output: ((CVBuffer, CMTime) -> Void)? { get set } 74 | } 75 | -------------------------------------------------------------------------------- /Sources/MediaSession/MediaSessionOutput.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MediaSessionOutput.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 24.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | 29 | protocol MediaSessionOutput: AnyObject { 30 | 31 | } 32 | 33 | protocol AudioMediaSessionOutput: MediaSessionOutput { 34 | 35 | func appendAudioSampleBuffer(_ sampleBuffer: CMSampleBuffer) 36 | } 37 | 38 | protocol VideoMediaSessionOutput: MediaSessionOutput { 39 | 40 | func appendVideoSampleBuffer(_ sampleBuffer: CMSampleBuffer) 41 | 42 | func appendVideoPixelBuffer(_ pixelBuffer: CVPixelBuffer, at time: CMTime) 43 | } 44 | -------------------------------------------------------------------------------- /Sources/Outputs/VideoOutput/VideoOutput.Error.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoOutput.Error.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 19.04.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | extension VideoOutput { 29 | 30 | enum Error: Swift.Error { 31 | 32 | case cantAddVideoAssetWriterInput 33 | 34 | case cantAddAudioAssterWriterInput(audioSettings: [String: Any]) 35 | 36 | case cantStartWriting 37 | 38 | case unknown 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/PixelBuffer/MetalTexture.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalTexture.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 28.11.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | import Metal 29 | 30 | final class MetalTexture { 31 | 32 | struct Attributes: Hashable { 33 | 34 | var width: Int 35 | 36 | var height: Int 37 | 38 | var pixelFormat: MTLPixelFormat 39 | 40 | var planeIndex: Int = 0 41 | } 42 | 43 | let attributes: Attributes 44 | 45 | let pixelBuffer: PixelBuffer 46 | 47 | let cvMetalTexture: CVMetalTexture 48 | 49 | let mtlTexture: MTLTexture 50 | 51 | init( 52 | attributes: Attributes, 53 | pixelBuffer: PixelBuffer, 54 | cvMetalTexture: CVMetalTexture, 55 | mtlTexture: MTLTexture 56 | ) { 57 | self.attributes = attributes 58 | self.pixelBuffer = pixelBuffer 59 | self.cvMetalTexture = cvMetalTexture 60 | self.mtlTexture = mtlTexture 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/Protocols/Renderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Renderable.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 13.09.2020. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | import Metal 29 | 30 | public protocol Renderable { 31 | 32 | func render(atTime time: TimeInterval) 33 | 34 | func render(atTime time: TimeInterval, using commandQueue: MTLCommandQueue) 35 | } 36 | 37 | public extension Renderable { 38 | 39 | func render() { render(atTime: CACurrentMediaTime()) } 40 | 41 | func render(using commandQueue: MTLCommandQueue) { 42 | render(atTime: CACurrentMediaTime(), using: commandQueue) 43 | } 44 | 45 | func render(atTime time: TimeInterval, using commandQueue: MTLCommandQueue) { 46 | render(atTime: time) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/Protocols/TimeScalable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimeScalable.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 19.04.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | 29 | protocol TimeScalable { 30 | 31 | var timeScale: CMTimeScale { get } 32 | } 33 | 34 | extension TimeScalable { 35 | 36 | func timeFromSeconds(_ seconds: TimeInterval) -> CMTime { 37 | CMTime(seconds: seconds, preferredTimescale: timeScale) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Recordable/Extensions/ARSCNView+CleanRecordable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ARSCNView+CleanRecordable.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 25.05.2020. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import ARKit 28 | 29 | extension ARSCNView: CleanRecordable { 30 | 31 | public var cleanPixelBuffer: CVPixelBuffer? { session.currentFrame?.capturedImage } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Recordable/Extensions/SCNView+MetalRecordable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNView+MetalRecordable.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 30.12.2019. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import SceneKit 28 | 29 | extension SCNView: MetalRecordable { 30 | 31 | public var recordableLayer: RecordableLayer? { layer as? RecordableLayer } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Recordable/MetalRecordable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalRecordable.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 12.09.2020. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | public protocol MetalRecordable { 29 | 30 | var recordableLayer: RecordableLayer? { get } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/RecordableLayer/RecordableLayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RecordableLayer.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 30.12.2019. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | import AVFoundation 29 | 30 | public protocol RecordableLayer: AnyObject { 31 | 32 | var lastTexture: MTLTexture? { get } 33 | 34 | var device: MTLDevice? { get } 35 | 36 | var pixelFormat: MTLPixelFormat { get } 37 | 38 | var drawableSize: CGSize { get } 39 | 40 | var colorspace: CGColorSpace? { get } 41 | 42 | var framebufferOnly: Bool { get } 43 | 44 | var interfaceOrientation: UIInterfaceOrientation { get } 45 | 46 | func prepareForRecording() 47 | } 48 | 49 | public extension RecordableLayer { 50 | 51 | func prepareForRecording() { } 52 | } 53 | 54 | #if !targetEnvironment(simulator) 55 | 56 | public extension RecordableLayer where Self: CAMetalLayer { 57 | 58 | func prepareForRecording() { Self.swizzle() } 59 | } 60 | 61 | #else 62 | 63 | @available(iOS 13.0, *) 64 | public extension RecordableLayer where Self: CAMetalLayer { 65 | 66 | func prepareForRecording() { Self.swizzle() } 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /Sources/Recorder/CleanRecorder/CleanRecorder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CleanRecorder.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 25.05.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import SceneKit 28 | import CoreMedia 29 | 30 | public final class CleanRecorder: BaseRecorder, 31 | Renderable, SCNSceneRendererDelegate { 32 | 33 | let videoInput: VideoInput 34 | 35 | init(_ cleanRecordable: T, timeScale: CMTimeScale = 600) { 36 | let queue = DispatchQueue(label: "SCNRecorder.Processing.DispatchQueue", qos: .userInitiated) 37 | 38 | self.videoInput = VideoInput( 39 | cleanRecordable: cleanRecordable, 40 | timeScale: timeScale, 41 | queue: queue 42 | ) 43 | 44 | super.init(queue: queue, mediaSession: MediaSession(queue: queue, videoInput: videoInput)) 45 | } 46 | 47 | func _render(atTime time: TimeInterval) { 48 | do { try videoInput.render(atTime: time) } 49 | catch { self.error = error } 50 | } 51 | 52 | public func render(atTime time: TimeInterval) { 53 | assert(T.self != SCNView.self, "\(#function) must not be called for \(T.self)") 54 | _render(atTime: time) 55 | } 56 | 57 | public func renderer( 58 | _ renderer: SCNSceneRenderer, 59 | didRenderScene scene: SCNScene, 60 | atTime time: TimeInterval 61 | ) { _render(atTime: time) } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/SelfRecordable/Extensions/SCNView+SelfSceneRecordable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNView+SelfSceneRecordable.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 12.09.2020. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import SceneKit 28 | 29 | extension SCNView: SelfSceneRecordable { 30 | 31 | public func prepareForRecording() { 32 | Self.swizzle() 33 | 34 | recordableLayer?.prepareForRecording() 35 | 36 | guard sceneRecorder == nil else { return } 37 | injectRecorder() 38 | 39 | assert(sceneRecorder != nil) 40 | addDelegate(sceneRecorder!) 41 | 42 | fixFirstLaunchFrameDrop() 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sources/SelfRecordable/SelfSceneRecordable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SelfSceneRecordable.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 25.05.2020. 6 | // Copyright © 2020 GORA Studio. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import UIKit 28 | import SceneKit 29 | 30 | private var sceneRecorderKey: UInt8 = 0 31 | 32 | public protocol SelfSceneRecordable: SelfRecordable { 33 | 34 | var sceneRecorder: SceneRecorder? { get set } 35 | } 36 | 37 | extension SelfSceneRecordable { 38 | 39 | public var recorder: (BaseRecorder & Renderable)? { sceneRecorder } 40 | } 41 | 42 | extension SelfSceneRecordable { 43 | 44 | var sceneRecorderStorage: AssociatedStorage { 45 | AssociatedStorage(object: self, key: &sceneRecorderKey, policy: .OBJC_ASSOCIATION_RETAIN) 46 | } 47 | 48 | public var sceneRecorder: SceneRecorder? { 49 | get { sceneRecorderStorage.get() } 50 | set { sceneRecorderStorage.set(newValue) } 51 | } 52 | } 53 | 54 | extension SelfSceneRecordable where Self: MetalRecordable { 55 | 56 | public func injectRecorder() { 57 | assert(sceneRecorder == nil) 58 | 59 | do { sceneRecorder = try SceneRecorder(self) } 60 | catch { assertionFailure("\(error)") } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/VideoRecording.Info.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoRecording.Info.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 28.07.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | 29 | public extension VideoRecording { 30 | 31 | struct Info { 32 | 33 | public var url: URL 34 | 35 | public var fileType: AVFileType 36 | 37 | public var duration: TimeInterval 38 | 39 | init(_ videoRecording: VideoRecording) { 40 | url = videoRecording.url 41 | fileType = videoRecording.fileType 42 | duration = videoRecording.duration 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/VideoRecording.State.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoRecording.State.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 26.04.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | public extension VideoRecording { 29 | 30 | typealias State = VideoOutputState 31 | } 32 | -------------------------------------------------------------------------------- /Sources/VideoRecording.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoRecording.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 11/03/2019. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | 29 | public final class VideoRecording { 30 | 31 | @SCNObservable public internal(set) var duration: TimeInterval 32 | 33 | @SCNObservable public internal(set) var state: State 34 | 35 | public var url: URL { videoOutput.url } 36 | 37 | public var fileType: AVFileType { videoOutput.fileType } 38 | 39 | let videoOutput: VideoOutput 40 | 41 | init(videoOutput: VideoOutput) { 42 | self.state = videoOutput.state 43 | self.duration = videoOutput.duration 44 | self.videoOutput = videoOutput 45 | } 46 | 47 | public func resume() { videoOutput.resume() } 48 | 49 | public func pause() { videoOutput.pause() } 50 | 51 | public func finish(completionHandler handler: @escaping (_ info: Info) -> Void) { 52 | videoOutput.finish { handler(Info(self)) } 53 | } 54 | 55 | func cancel() { videoOutput.cancel() } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/VideoSettings.ScalingMode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoSettings.ScalingMode.swift 3 | // SCNRecorder 4 | // 5 | // Created by Vladislav Grigoryev on 20.07.2020. 6 | // Copyright © 2020 GORA Studio. https://gora.studio 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | import AVFoundation 28 | 29 | public extension VideoSettings { 30 | 31 | enum ScalingMode { 32 | 33 | /// Crop to remove edge processing region. 34 | /// Preserve aspect ratio of cropped source by reducing specified width or height if necessary. 35 | /// Will not scale a small source up to larger dimensions. 36 | // case fit 37 | 38 | /// Crop to remove edge processing region. 39 | /// Scale remainder to destination area. 40 | /// Does not preserve aspect ratio. 41 | case resize 42 | 43 | /// Preserve aspect ratio of the source, and fill remaining areas with black to fit destination dimensions. 44 | case resizeAspect 45 | 46 | /// Preserve aspect ratio of the source, and crop picture to fit destination dimensions. 47 | case resizeAspectFill 48 | } 49 | } 50 | 51 | extension VideoSettings.ScalingMode { 52 | 53 | var avScalingMode: String { 54 | switch self { 55 | // case .fit: return AVVideoScalingModeFit 56 | case .resize: return AVVideoScalingModeResize 57 | case .resizeAspect: return AVVideoScalingModeResizeAspect 58 | case .resizeAspectFill: return AVVideoScalingModeResizeAspectFill 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /images/sample2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gorastudio-git/SCNRecorder/795dc264708c814a4ce6041e605e125f2d663123/images/sample2.gif --------------------------------------------------------------------------------