17 Commits

Author SHA1 Message Date
AFathi 054d23ca50 added SceneKit rendering 2018-04-20 20:50:04 -04:00
AFathi 7fb760dab0 added light rendering config in objc example 2018-04-04 13:26:38 -04:00
AFathi 6693e32ecf update 2018-04-04 13:23:22 -04:00
AFathi b79af89eb6 update 2018-04-04 13:22:16 -04:00
Ahmed Fathi Bekhit b0b7f41904 Merge pull request #33 from miliPolo/master
bug fix: ARKit Shadows
2018-03-15 15:57:15 -04:00
Alexyang 105e8360e4 bug fix
Video Recorded or Photo Doesn't Show ARKit Shadows
2018-03-15 19:56:42 +08:00
Ahmed Fathi Bekhit 71f2f27d11 Update README.md 2018-02-08 17:28:48 -05:00
Ahmed Fathi Bekhit 6d1624c730 Update README.md 2018-02-07 18:46:44 -05:00
Ahmed Fathi Bekhit 6aa443b3d9 Update README.md 2018-01-14 16:22:10 -05:00
Ahmed Fathi Bekhit 30087d53d3 Update README.md 2018-01-14 01:19:33 -05:00
Ahmed Fathi Bekhit c7ad4295a1 Update README.md 2018-01-12 16:37:18 -05:00
Ahmed Fathi Bekhit f9cabf3ea4 Update README.md 2018-01-12 14:47:37 -05:00
Ahmed Fathi Bekhit 85f1f00a91 Update README.md 2018-01-12 14:45:11 -05:00
Ahmed Fathi Bekhit a14ef8d6cc Update README.md 2018-01-12 14:44:32 -05:00
AFathi 0c4bae5fb6 Added Obj-C Implementation steps 2018-01-12 14:39:08 -05:00
Ahmed Fathi Bekhit f5c87b097c Update README.md 2018-01-12 14:13:49 -05:00
Ahmed Fathi Bekhit 4af1d53984 Update README.md 2018-01-12 14:10:29 -05:00
29 changed files with 283 additions and 97 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ internal extension UIScreen {
`isiPhone10` is a boolean that returns if the device is iPhone X or not.
*/
internal var isiPhone10: Bool {
return self.nativeBounds.size == CGSize(width: 1125, height: 2436)
return self.nativeBounds.size == CGSize(width: 1125, height: 2436) || self.nativeBounds.size == CGSize(width: 2436, height: 1125)
}
}
@available(iOS 11.0, *)
+1 -1
View File
@@ -37,7 +37,7 @@ internal class GIFGenerator {
guard let path = self.currentGIFPath else{return}
guard let destination = CGImageDestinationCreateWithURL(path as CFURL, kUTTypeGIF, images.count, nil) else{finished?(false, nil);return}
print(destination)
logAR.message("\(destination)")
CGImageDestinationSetProperties(destination, gifSettings as CFDictionary)
for image in images {
if let imageRef = image.cgImage {
+15
View File
@@ -27,9 +27,12 @@ internal struct RenderAR {
}else if let view = view as? ARSKView {
guard let rawBuffer = view.session.currentFrame?.capturedImage else{return nil}
return rawBuffer
}else if let _ = view as? SCNView {
return buffer
}
return nil
}
internal var bufferSize:CGSize? {
guard let raw = rawBuffer else{return nil};
var width = CVPixelBufferGetWidth(raw);
@@ -98,6 +101,18 @@ internal struct RenderAR {
}
guard let buffer = renderedFrame!.buffer else{return nil};
return buffer;
}else if let _ = view as? SCNView {
let size = UIScreen.main.bounds.size
var renderedFrame:UIImage?
pixelsQueue.sync {
renderedFrame = renderEngine.snapshot(atTime: self.time, with: size, antialiasingMode: .none);
}
if let _ = renderedFrame {
}else{
renderedFrame = renderEngine.snapshot(atTime: time, with: size, antialiasingMode: .none);
}
guard let buffer = renderedFrame!.buffer else{return nil};
return buffer;
}
return nil;
}
+16
View File
@@ -80,6 +80,22 @@ fileprivate var recentAngle = 0
parentVC = vc
}
@objc init?(SceneKit:SCNView) {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
ViewAR.orientation = .portrait
guard let vc = SceneKit.parent else {
return
}
parentVC = vc
}
@objc fileprivate func deviceDidRotate() {
guard var views = parentVC?.view.subviews else {
return
+41 -2
View File
@@ -87,6 +87,17 @@ fileprivate var renderer:RenderAR!
A boolean that enables or disables clearing cached media after exporting to Camera Roll. Default is `true`.
*/
@objc public var deleteCacheWhenExported:Bool = true
/**
A boolean that enables or disables using envronment light rendering. Default is `false`.
*/
@objc public var enableAdjsutEnvironmentLighting:Bool = false {
didSet{
if (renderEngine != nil) {
renderEngine.autoenablesDefaultLighting = enableAdjsutEnvironmentLighting
}
}
}
//MARK: - Public initialization methods
/**
@@ -117,6 +128,16 @@ fileprivate var renderer:RenderAR!
logAR.message("Error occurred while loading SK Video Assets : \(error). Please download \"video.scnassets\" from\nwww.ahmedbekhit.com/ARVideoKitAssets")
}
}
/**
Initialize 🌞🍳 `RecordAR` with an `SCNView` 🚀.
*/
@objc override public init?(SceneKit: SCNView) {
super.init(SceneKit: SceneKit)
view = SceneKit
setup()
}
//MARK: - Internal threads
internal let writerQueue = DispatchQueue(label:"com.ahmedbekhit.WriterQueue")
internal let gifWriterQueue = DispatchQueue(label: "com.ahmedbekhit.GIFWriterQueue", attributes: .concurrent)
@@ -131,6 +152,8 @@ fileprivate var renderer:RenderAR!
return view.parent!
}else if let view = view as? ARSKView {
return view.parent!
}else if let view = view as? SCNView {
return view.parent!
}
return nil
}
@@ -169,6 +192,7 @@ fileprivate var renderer:RenderAR!
let vidPath = "\(documentsDirectory)/\(formatter.string(from: date))ARVideo.mp4"
return URL(fileURLWithPath: vidPath, isDirectory: false)
}
//MARK: - Internal Video Setup
internal func setup() {
if let view = view as? ARSCNView {
@@ -200,6 +224,16 @@ fileprivate var renderer:RenderAR!
gpuLoop.preferredFramesPerSecond = fps.rawValue
gpuLoop.add(to: .main, forMode: .commonModes)
status = .readyToRecord
}else if let view = view as? SCNView {
guard let mtlDevice = MTLCreateSystemDefaultDevice() else {logAR.message("ERROR:- This device does not support Metal");return}
renderEngine = SCNRenderer(device: mtlDevice, options: nil)
renderEngine.scene = view.scene
gpuLoop = CADisplayLink(target: self, selector: #selector(renderFrame))
gpuLoop.preferredFramesPerSecond = fps.rawValue
gpuLoop.add(to: .main, forMode: .commonModes)
status = .readyToRecord
}
@@ -222,6 +256,8 @@ fileprivate var renderer:RenderAR!
NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterBackground), name: Notification.Name.UIApplicationWillResignActive, object: nil)
}
//MARK: - Public methods for capturing videos, photos, Live Photos, and GIFs
@@ -656,6 +692,10 @@ fileprivate var renderer:RenderAR!
ViewAR.orientation = .portrait
view.session.run(configuration)
}else if let _ = view as? SCNView {
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
ViewAR.orientation = .portrait
}
onlyRenderWhileRec = onlyRenderWhileRecording
@@ -676,12 +716,11 @@ internal extension RecordAR {
@objc internal func renderFrame() {
//frame rendering
if self.onlyRenderWhileRec && !isRecording && !isRecordingGIF {return}
guard let buffer = renderer.buffer else{return}
guard let rawBuffer = renderer.rawBuffer else{logAR.message("ERROR:- An error occurred while rendering the camera's main buffers.");return}
guard let size = renderer.bufferSize else{logAR.message("ERROR:- An error occurred while rendering the camera buffer.");return}
renderer.ARcontentMode = contentMode
self.writerQueue.sync {
var time:CMTime {return CMTimeMakeWithSeconds(renderer.time, 1000000);}
@@ -19,8 +19,8 @@
FB36BD9420085C7B00002808 /* Scene.m in Sources */ = {isa = PBXBuildFile; fileRef = FB36BD9120085C7B00002808 /* Scene.m */; };
FB36BD9520085C7B00002808 /* Scene.sks in Resources */ = {isa = PBXBuildFile; fileRef = FB36BD9320085C7B00002808 /* Scene.sks */; };
FB36BD98200869D200002808 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = FB36BD97200869D200002808 /* LICENSE */; };
FB36BD9F20086A1600002808 /* ARVideoKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB36BD9E20086A0B00002808 /* ARVideoKit.framework */; };
FB36BDA020086A1600002808 /* ARVideoKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FB36BD9E20086A0B00002808 /* ARVideoKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
FBE12A5320093EF800B0BB61 /* ARVideoKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB36BD9E20086A0B00002808 /* ARVideoKit.framework */; };
FBE12A5420093EF800B0BB61 /* ARVideoKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FB36BD9E20086A0B00002808 /* ARVideoKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -31,7 +31,7 @@
remoteGlobalIDString = FBD604DA1FA969DD00EC9804;
remoteInfo = ARVideoKit;
};
FB36BDA120086A1600002808 /* PBXContainerItemProxy */ = {
FBE12A5520093EF800B0BB61 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = FB36BD9920086A0A00002808 /* ARVideoKit.xcodeproj */;
proxyType = 1;
@@ -41,13 +41,13 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
FB36BD61200816E400002808 /* Embed Frameworks */ = {
FBE12A5720093EF800B0BB61 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
FB36BDA020086A1600002808 /* ARVideoKit.framework in Embed Frameworks */,
FBE12A5420093EF800B0BB61 /* ARVideoKit.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -82,7 +82,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FB36BD9F20086A1600002808 /* ARVideoKit.framework in Frameworks */,
FBE12A5320093EF800B0BB61 /* ARVideoKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -205,12 +205,12 @@
FB36BD382008166700002808 /* Sources */,
FB36BD392008166700002808 /* Frameworks */,
FB36BD3A2008166700002808 /* Resources */,
FB36BD61200816E400002808 /* Embed Frameworks */,
FBE12A5720093EF800B0BB61 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
FB36BDA220086A1600002808 /* PBXTargetDependency */,
FBE12A5620093EF800B0BB61 /* PBXTargetDependency */,
);
name = "ARKit-Video";
productName = "ARKit-Video";
@@ -299,10 +299,10 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
FB36BDA220086A1600002808 /* PBXTargetDependency */ = {
FBE12A5620093EF800B0BB61 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = ARVideoKit;
targetProxy = FB36BDA120086A1600002808 /* PBXContainerItemProxy */;
targetProxy = FBE12A5520093EF800B0BB61 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
@@ -436,7 +436,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = P5DZ3XQ9FJ;
INFOPLIST_FILE = "ARKit-Video/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -452,7 +452,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = P5DZ3XQ9FJ;
INFOPLIST_FILE = "ARKit-Video/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -10,6 +10,7 @@
#import <SceneKit/SceneKit.h>
#import <ARKit/ARKit.h>
#import <CoreMedia/CoreMedia.h>
#import <Photos/Photos.h>
@import ARVideoKit;
@interface SCNViewController : UIViewController
@@ -10,6 +10,7 @@
#import <SpriteKit/SpriteKit.h>
#import <ARKit/ARKit.h>
#import <CoreMedia/CoreMedia.h>
#import <Photos/Photos.h>
@import ARVideoKit;
@interface SKViewController : UIViewController
@@ -50,6 +50,9 @@
// Configure RecordAR to store media files in local app directory
recorder.deleteCacheWhenExported = NO;
// Configure the envronment light rendering.
recorder.enableAdjsutEnvironmentLighting = YES;
}
-(void)viewWillAppear:(BOOL)animated {
@@ -70,7 +73,11 @@
[self.sceneView.session pause];
if(recorder.status == RecordARStatusRecording) {
[recorder stopAndExport:NULL];
[recorder stopAndExport:^(NSURL*_Nonnull filePath, PHAuthorizationStatus status, BOOL ready) {
if (status == PHAuthorizationStatusAuthorized) {
NSLog(@"Video Exported Successfully!");
}
}];
}
recorder.onlyRenderWhileRecording = YES;
@@ -116,7 +123,11 @@
[sender setTitle:@"Record" forState: UIControlStateNormal];
[self.pauseBtn setTitle:@"Pause" forState: UIControlStateNormal];
self.pauseBtn.enabled = NO;
[recorder stopAndExport:NULL];
[recorder stopAndExport:^(NSURL*_Nonnull filePath, PHAuthorizationStatus status, BOOL ready) {
if (status == PHAuthorizationStatusAuthorized) {
NSLog(@"Video Exported Successfully!");
}
}];
}
}else if (sender.tag == 1) {
//Record with duration
@@ -131,7 +142,11 @@
[self.pauseBtn setTitle:@"Pause" forState: UIControlStateNormal];
self.pauseBtn.enabled = NO;
self.recordBtn.enabled = YES;
[recorder stopAndExport:NULL];
[recorder stopAndExport:^(NSURL*_Nonnull filePath, PHAuthorizationStatus status, BOOL ready) {
if (status == PHAuthorizationStatusAuthorized) {
NSLog(@"Video Exported Successfully!");
}
}];
}
}else if (sender.tag == 2) {
//Pause
@@ -120,7 +120,12 @@
[sender setTitle:@"Record" forState: UIControlStateNormal];
[self.pauseBtn setTitle:@"Pause" forState: UIControlStateNormal];
self.pauseBtn.enabled = NO;
[recorder stopAndExport:NULL];
//URL, PHAuthorizationStatus, Bool
[recorder stopAndExport:^(NSURL*_Nonnull filePath, PHAuthorizationStatus status, BOOL ready) {
if (status == PHAuthorizationStatusAuthorized) {
NSLog(@"Video Exported Successfully!");
}
}];
}
}else if (sender.tag == 1) {
//Record with duration
+63
View File
@@ -0,0 +1,63 @@
# Objective-C Example
This folder provides you an example project written in Objective-C that demonstrates the use of [**ARVideoKit**](https://github.com/AFathi/ARVideoKit) framework.
## Implementation
1. Import the `ARVideoKit` into the application delegate implementation file `AppDelegate.m` and a `UIViewController` class with an `ARKit` scene.
```
@import ARVideoKit;
```
2. In the application delegate implementation file `AppDelegate.m`, add this 👇 in order to allow the framework access and identify the supported device orientations. **Recommended** if the application supports landscape orientations.
```
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return ViewAR.orientation;
}
```
3. In the selected `UIViewController` class, create a [`RecordAR`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR) global variable by adding the following in the interface section of the implementation file (e.g `ViewController.m`).
```
@interface ViewController ()
{
RecordAR *recorder;
}
```
4. Initialize [`RecordAR`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR) with [`ARSCNView`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arscenekitarscnview) or [`ARSKView`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arspritekitarskview). **Recommended** to initialize in `(void)viewDidLoad`.
Initializing RecordAR with `ARSCNView`
```
recorder = [[RecordAR alloc] initWithARSceneKit:self.sceneView];
```
Initializing RecordAR with `ARSKView`
```
recorder = [[RecordAR alloc] initWithARSpriteKit:self.SKSceneView];
```
5. Call the [`prepare()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-prepare_-configurationarconfiguration) method in `(void)viewWillAppear:(BOOL)animated`
```
ARWorldTrackingConfiguration *configuration = [ARWorldTrackingConfiguration new];
[recorder prepare:configuration];
```
6. Call the [`rest()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-rest) method in `(void)viewWillDisappear:(BOOL)animated`
```
[recorder rest];
```
7. Call the [`record()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-record) method in the proper method to start recording.
```
- (IBAction)startRecording:(UIButton *)sender {
if (recorder.status == RecordARStatusReadyToRecord) {
[recorder record];
}
}
```
8. Call the [`stopAndExport()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-stopandexport_-finished-_-videopath-url-_-permissionstatusphauthorizationstatus-_-exportedbool---swiftvoid--nil) method in the proper method to stop recording.
```
- (IBAction)stopRecording:(UIButton *)sender {
if (recorder.status == RecordARStatusRecording) {
[recorder stopAndExport:NULL];
}
}
```
@@ -10,6 +10,7 @@
FB2E368C1FAE2A510035B8D6 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = FB2E368B1FAE2A510035B8D6 /* LICENSE */; };
FB36BDB020086BBB00002808 /* ARVideoKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB36BDAF20086BB000002808 /* ARVideoKit.framework */; };
FB36BDB120086BBB00002808 /* ARVideoKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FB36BDAF20086BB000002808 /* ARVideoKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
FB3B51A620489CBA000377AE /* overlay_2d_img.png in Resources */ = {isa = PBXBuildFile; fileRef = FB3B51A520489CB9000377AE /* overlay_2d_img.png */; };
FB9B5D2E1FC49E3E005DDD60 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB9B5D2D1FC49E3E005DDD60 /* MainViewController.swift */; };
FBDCC5E71FABDFC600E3184D /* Scene.sks in Resources */ = {isa = PBXBuildFile; fileRef = FBDCC5E51FABDFC500E3184D /* Scene.sks */; };
FBDCC5E81FABDFC600E3184D /* Scene.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBDCC5E61FABDFC500E3184D /* Scene.swift */; };
@@ -56,6 +57,7 @@
/* Begin PBXFileReference section */
FB2E368B1FAE2A510035B8D6 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
FB36BDAA20086BB000002808 /* ARVideoKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ARVideoKit.xcodeproj; path = ../../ARVideoKit.xcodeproj; sourceTree = "<group>"; };
FB3B51A520489CB9000377AE /* overlay_2d_img.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = overlay_2d_img.png; sourceTree = "<group>"; };
FB9B5D2D1FC49E3E005DDD60 /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
FBDCC5E51FABDFC500E3184D /* Scene.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Scene.sks; sourceTree = "<group>"; };
FBDCC5E61FABDFC500E3184D /* Scene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scene.swift; sourceTree = "<group>"; };
@@ -144,20 +146,12 @@
path = SK;
sourceTree = "<group>";
};
FBE12A4B20086C9400B0BB61 /* Framework */ = {
isa = PBXGroup;
children = (
);
path = Framework;
sourceTree = "<group>";
};
FBE134AD1FAAD3DD00BEC469 = {
isa = PBXGroup;
children = (
FB2E368B1FAE2A510035B8D6 /* LICENSE */,
FB36BDAA20086BB000002808 /* ARVideoKit.xcodeproj */,
FBE134B81FAAD3DD00BEC469 /* ARVideoKit-Example */,
FBE12A4B20086C9400B0BB61 /* Framework */,
FBE134B71FAAD3DD00BEC469 /* Products */,
);
sourceTree = "<group>";
@@ -173,6 +167,7 @@
FBE134B81FAAD3DD00BEC469 /* ARVideoKit-Example */ = {
isa = PBXGroup;
children = (
FB3B51A520489CB9000377AE /* overlay_2d_img.png */,
FBE134B91FAAD3DD00BEC469 /* AppDelegate.swift */,
FBA0AA0D1FAD9E4B006C481B /* View Controllers */,
FBA0AA0C1FAD9E2C006C481B /* Storyboards */,
@@ -264,6 +259,7 @@
FBE134C11FAAD3DD00BEC469 /* Assets.xcassets in Resources */,
FBDCC6401FAC2CD900E3184D /* art.scnassets in Resources */,
FBE134BF1FAAD3DD00BEC469 /* Main.storyboard in Resources */,
FB3B51A620489CBA000377AE /* overlay_2d_img.png in Resources */,
FBDCC5E71FABDFC600E3184D /* Scene.sks in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -426,7 +422,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = P5DZ3XQ9FJ;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@@ -448,7 +444,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = P5DZ3XQ9FJ;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="N8h-YD-r0X">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="N8h-YD-r0X">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -88,6 +88,10 @@
<arscnView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IMN-9B-haO">
<rect key="frame" x="0.0" y="10" width="375" height="667"/>
</arscnView>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="overlay_2d_img.png" translatesAutoresizingMaskIntoConstraints="NO" id="fyP-vk-9kb">
<rect key="frame" x="0.0" y="10" width="375" height="657"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="AR w/ SceneKit" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fCR-qg-FqO">
<rect key="frame" x="97" y="20" width="181" height="65"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.65000000000000002" colorSpace="custom" customColorSpace="sRGB"/>
@@ -235,6 +239,7 @@
</view>
<nil key="simulatedTopBarMetrics"/>
<connections>
<outlet property="overlayImg" destination="fyP-vk-9kb" id="VJg-xp-ImM"/>
<outlet property="pauseBtn" destination="pCi-Bx-pwj" id="Vbx-Qf-GiU"/>
<outlet property="recordBtn" destination="1R6-Xa-VsB" id="xFW-bY-b3A"/>
<outlet property="sceneView" destination="IMN-9B-haO" id="6l9-yC-XES"/>
@@ -242,7 +247,7 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="54" y="866"/>
<point key="canvasLocation" x="53.600000000000001" y="865.81709145427294"/>
</scene>
<!--SKViewController-->
<scene sceneID="emy-Ex-RPU">
@@ -409,7 +414,10 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="9if-am-XF6" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="54" y="134"/>
<point key="canvasLocation" x="53.600000000000001" y="133.5832083958021"/>
</scene>
</scenes>
<resources>
<image name="overlay_2d_img.png" width="1080" height="1920"/>
</resources>
</document>
@@ -13,6 +13,7 @@ import Photos
class SCNViewController: UIViewController, ARSCNViewDelegate, RenderARDelegate, RecordARDelegate {
@IBOutlet weak var overlayImg: UIImageView!
@IBOutlet var sceneView: ARSCNView!
@IBOutlet var recordBtn: UIButton!
@IBOutlet var pauseBtn: UIButton!
@@ -36,6 +37,9 @@ class SCNViewController: UIViewController, ARSCNViewDelegate, RenderARDelegate,
// Set the scene to the view
sceneView.scene = scene
sceneView.scene.rootNode.scale = SCNVector3(0.2, 0.2, 0.2)
//
sceneView.automaticallyUpdatesLighting = true
sceneView.autoenablesDefaultLighting = true
// Initialize ARVideoKit recorder
recorder = RecordAR(ARSceneKit: sceneView)
@@ -54,6 +58,9 @@ class SCNViewController: UIViewController, ARSCNViewDelegate, RenderARDelegate,
// Configure ARKit content mode. Default is .auto
recorder?.contentMode = .aspectFill
//record or photo add environment light rendering, Default is false
recorder?.enableAdjsutEnvironmentLighting = true
// Set the UIViewController orientations
recorder?.inputViewOrientations = [.landscapeLeft, .landscapeRight, .portrait]
// Configure RecordAR to store media files in local app directory
Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

+53
View File
@@ -0,0 +1,53 @@
# Swift Example
This folder provides you an example project written in Swift that demonstrates the use of [**ARVideoKit**](https://github.com/AFathi/ARVideoKit) framework.
## Implementation
1. `import ARVideoKit` in the application delegate `AppDelegate.swift` and a `UIViewController` with an `ARKit` scene.
2. In the application delegate `AppDelegate.swift`, add this 👇 in order to allow the framework access and identify the supported device orientations. **Recommended** if the application supports landscape orientations.
```
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return ViewAR.orientation
}
```
3. In the selected `UIViewController` class, create an optional type [`RecordAR`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR) global variable.
```
var recorder:RecordAR?
```
4. Initialize [`RecordAR`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR) with [`ARSCNView`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arscenekitarscnview) or [`ARSKView`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arspritekitarskview). **Recommended** to initialize in `viewDidLoad()`.
Initializing RecordAR with `ARSCNView`
```
recorder = RecordAR(ARSceneKit: sceneView)
```
Initializing RecordAR with `ARSKView`
```
recorder = RecordAR(ARSpriteKit: SKSceneView)
```
5. Call the [`prepare()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-prepare_-configurationarconfiguration) method in `viewWillAppear(_ animated: Bool)`
```
let configuration = ARWorldTrackingConfiguration()
recorder?.prepare(configuration)
```
6. Call the [`rest()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-rest) method in `viewWillDisappear(_ animated: Bool)`
```
recorder?.rest()
```
7. Call the [`record()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-record) method in the proper method to start recording.
```
@IBAction func startRecording(_ sender: UIButton) {
recorder?.record()
}
```
8. Call the [`stopAndExport()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-stopandexport_-finished-_-videopath-url-_-permissionstatusphauthorizationstatus-_-exportedbool---swiftvoid--nil) method in the proper method to stop recording.
```
@IBAction func stopRecording(_ sender: UIButton) {
recorder?.stopAndExport()
}
```
Binary file not shown.
@@ -285,6 +285,7 @@ enum RecordARMicrophoneStatus : NSInteger;
enum RecordARMicrophonePermission : NSInteger;
@class ARSCNView;
@class ARSKView;
@class SCNView;
@class UIImage;
/// This class renders the <code>ARSCNView</code> or <code>ARSKView</code> content with the devices camera stream to generate a video 📹, photo 🌄, live photo 🎇 or GIF 🎆.
@@ -334,10 +335,14 @@ SWIFT_CLASS("_TtC10ARVideoKit8RecordAR") SWIFT_AVAILABILITY(ios,introduced=11.0)
@property (nonatomic) BOOL adjustGIFForSharing;
/// A boolean that enables or disables clearing cached media after exporting to Camera Roll. Default is <code>true</code>.
@property (nonatomic) BOOL deleteCacheWhenExported;
/// A boolean that enables or disables using envronment light rendering. Default is <code>false</code>.
@property (nonatomic) BOOL enableAdjsutEnvironmentLighting;
/// Initialize 🌞🍳 <code>RecordAR</code> with an <code>ARSCNView</code> 🚀.
- (nullable instancetype)initWithARSceneKit:(ARSCNView * _Nonnull)ARSceneKit OBJC_DESIGNATED_INITIALIZER;
/// Initialize 🌞🍳 <code>RecordAR</code> with an <code>ARSKView</code> 👾.
- (nullable instancetype)initWithARSpriteKit:(ARSKView * _Nonnull)ARSpriteKit OBJC_DESIGNATED_INITIALIZER;
/// Initialize 🌞🍳 <code>RecordAR</code> with an <code>SCNView</code> 🚀.
- (nullable instancetype)initWithSceneKit:(SCNView * _Nonnull)SceneKit OBJC_DESIGNATED_INITIALIZER;
/// A method that renders a photo 🌄 and returns it as <code>UIImage</code>.
- (UIImage * _Nonnull)photo SWIFT_WARN_UNUSED_RESULT;
/// A method that renders a <code>PHLivePhoto</code> 🎇 and returns <code>PHLivePhotoPlus</code> in the completion handler.
+1 -1
View File
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Ahmed Fathi Bekhit - me@ahmedbekhit.com
Copyright 2017 Ahmed Fathi Bekhit, www.ahmedbekhit.com, me@ahmedbekhit.com
ARVideoKit is licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+24 -62
View File
@@ -1,4 +1,5 @@
# ARVideoKit
![intro image](http://www.ahmedbekhit.com/tutorials/ARVideoKit_prev_1.png)
An iOS Framework that enables developers to capture videos 📹, photos 🌄, Live Photos 🎇, and GIFs 🎆 with ARKit content.
In other words, you **NO LONGER** have to ~screen record~/~screenshot~ to capture videos 📹 and photos 🌄 of your awesome ARKit apps!
@@ -10,19 +11,20 @@ In other words, you **NO LONGER** have to ~screen record~/~screenshot~ to captur
| [Preview](#preview) | Displays 2 GIF images captured using the supported [`gif`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-gifforduration-durationtimeinterval-exportbool-_-finished-_-statusbool-_-gifpath-url-_-permissionstatusphauthorizationstatus-_-exportedbool---swiftvoid--nil) method in `ARVideoKit`|
| [Key Features](#key-features) | Lists the key features `ARVideoKit` offers |
| [Compatibility](#compatibility) | Describes the `ARVideoKit` device and iOS compatibality |
| [Example Project](#example-project) | Explains how to run the example project provided in this repository |
| [Example Projects](#example-projects) | Explains how to run the example project provided in this repository |
| [Installation](#installation) | Describes the [Manual](#manual) option to install `ARVideoKit` |
| [Implementation](#implementation) | Lists the [steps needed](#implementation), [notes](#note), and [reference](#youre-all-set-) for more options |
| [Implementation](#implementation) | Lists the [steps needed](#implementation) for Objective-C & Swift, [notes](#note), and [reference](#youre-all-set-) for more options |
| [Publishing to the App Store](#publishing-to-the-app-store) | Describes the steps **required** before submitting an application using `ARVideoKit` to the App Store. |
|[![Donate](https://www.paypalobjects.com/webstatic/en_US/i/btn/png/btn_donate_92x26.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ahmedfbekhit@gmail.com&item_name=Support+ARVideoKit+Developer&item_number=ARVideoKit+Framework+Donations&amount=0%2e00&currency_code=USD) | [Donations](#donate) will support me to keep maintaining `ARVideoKit` ❤️|
| [Contributions](#contributions) | Describes how you can contribute to this project |
| [License](#license) | Describes `ARVideoKit` license |
| [AppCoda Tutorial](https://www.appcoda.com/record-arkit-video/) | Check out the detailed tutorial about implementing `ARVideoKit` with SpriteKit ☺️ |
| [AppCoda Tutorial](https://www.appcoda.com/record-arkit-video/) | Check out a detailed tutorial about implementing `ARVideoKit` with SpriteKit ☺️ |
## Preview
|👾 [Initialized with SpriteKit](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arspritekitarskview)👇 ‍‍ |🚀 [Initialized with SceneKit](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arscenekitarscnview) 👇 ‍‍‍‍‍‍ ‍‍ ‍‍ ‍‍‍‍‍‍ |
|👾 [Initialized with SpriteKit](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arspritekitarskview)👇|🚀 [Initialized with SceneKit](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arscenekitarscnview) 👇|
|--------------|--------------|
![SpriteKit Preview](http://www.ahmedbekhit.com/SK_PREV.gif) ![SceneKit Preview](http://www.ahmedbekhit.com/SCN_PREVIEW.gif)
| ![SpriteKit Preview](http://www.ahmedbekhit.com/SK_PREV.gif) | ![SceneKit Preview](http://www.ahmedbekhit.com/SCN_PREVIEW.gif)|
## Key Features
✅ Capture [Photos](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-photo---uiimage) from [`ARSCNView`](https://developer.apple.com/documentation/arkit/arscnview) and [`ARSKView`](https://developer.apple.com/documentation/arkit/arskview)
@@ -42,66 +44,21 @@ In other words, you **NO LONGER** have to ~screen record~/~screenshot~ to captur
- iOS 11
- Swift 3.2 or higher
## Example Project
To try the example project, simply clone this repository and open `ARVideoKit-Example.xcodeproj` project file.
## Example Projects
To try the example project, simply clone this repository and open the `Examples` folder to choose between the Objective-C and Swift project files.
It's **recommended** to test `SKViewController` by assigning it as the initial view controller.
![is initial VC](http://ahmedbekhit.com/isinitialVC.png)
## Installation
### Manual
Drag the `ARVideoKit.framework` file as an embedded binary of your project targets. `ARVideoKit.framework` can be found in the `/Framework/` folder of this repository.
Drag the `ARVideoKit.framework` file as an embedded binary of your project targets. `ARVideoKit.framework` can be found in the `/Framework Build/` folder of this repository.
![Tutorial](http://www.ahmedbekhit.com/arvideokit_install_new.gif)
Or you may drag `ARVideoKit.xcodeproj` into your project and click the **+** button in the embedded binaries section of your project's target.
![example embed framework](http://www.ahmedbekhit.com/embeddedBinary.png)
## Implementation
1. `import ARVideoKit` in the application delegate `AppDelegate.swift` and a `UIViewController` with an `ARKit` scene.
2. In the application delegate `AppDelegate.swift`, add this 👇 in order to allow the framework access and identify the supported device orientations. **Recommended** if the application supports landscape orientations.
```
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return ViewAR.orientation
}
```
3. In the selected `UIViewController` class, create an optional type [`RecordAR`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR) global variable.
```
var recorder:RecordAR?
```
4. Initialize [`RecordAR`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR) with [`ARSCNView`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arscenekitarscnview) or [`ARSKView`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#init-arspritekitarskview). **Recommended** to initialize in `viewDidLoad()`.
Initializing RecordAR with `ARSCNView`
```
recorder = RecordAR(ARSceneKit: sceneView)
```
Initializing RecordAR with `ARSKView`
```
recorder = RecordAR(ARSpriteKit: SKSceneView)
```
5. Call the [`prepare()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-prepare_-configurationarconfiguration) method in `viewWillAppear(_ animated: Bool)`
```
let configuration = ARWorldTrackingConfiguration()
recorder?.prepare(configuration)
```
6. Call the [`rest()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-rest) method in `viewWillDisappear(_ animated: Bool)`
```
recorder?.rest()
```
7. Call the [`record()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-record) method in the proper method to start recording.
```
@IBAction func startRecording(_ sender: UIButton) {
recorder?.record()
}
```
8. Call the [`stopAndExport()`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR#func-stopandexport_-finished-_-videopath-url-_-permissionstatusphauthorizationstatus-_-exportedbool---swiftvoid--nil) method in the proper method to stop recording.
```
@IBAction func stopRecording(_ sender: UIButton) {
recorder?.stopAndExport()
}
```
### Swift
[Click here to check the Swift implementation steps.](https://github.com/AFathi/ARVideoKit/tree/master/Examples/Swift)
### Objective-C
[Click here to check the Objective-C implementation steps.](https://github.com/AFathi/ARVideoKit/tree/master/Examples/Objective-C)
### NOTE
Make sure you add the usage description of the `camera`, `microphone`, and `photo library` in the app's `Info.plist`.
@@ -123,7 +80,7 @@ Check [`RecordAR`](https://github.com/AFathi/ARVideoKit/wiki/RecordAR) documenta
## Publishing to the App Store
Before publishing to the App Store make sure to add the [ARVideoKit License](#license) to your app licences list.
Additionally, you MUST **strip out the simulator architectures** from the framework before pushing an application to the App Store.
Additionally, if you are using the binary build from `Framework Build` or the latest release, you MUST **strip out the simulator architectures** from the framework before pushing an application to the App Store.
To do so, follow those steps:
@@ -151,6 +108,11 @@ Donations will support me to keep maintining **ARVideoKit Framework** ❤️
[![Donate](https://www.paypalobjects.com/webstatic/en_US/i/btn/png/btn_donate_92x26.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ahmedfbekhit@gmail.com&item_name=Support+ARVideoKit+Developer&item_number=ARVideoKit+Framework+Donations&amount=0%2e00&currency_code=USD)
## Contributions
If you have an idea for a new **ARVideoKit** feature/functionality and want to add it to this repository, feel free to fork the project and create a pull request!
Also, feel free to create an issue if you have any suggestions or need any help ☺️
## [License](LICENSE)
Copyright 2017 Ahmed Fathi Bekhit, www.ahmedbekhit.com, me@ahmedbekhit.com