diff --git a/Animoji.xcodeproj/project.pbxproj b/Animoji.xcodeproj/project.pbxproj new file mode 100644 index 0000000..78168b0 --- /dev/null +++ b/Animoji.xcodeproj/project.pbxproj @@ -0,0 +1,409 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 65AB4D281FF17D18005D684C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AB4D271FF17D18005D684C /* AppDelegate.swift */; }; + 65AB4D2A1FF17D18005D684C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AB4D291FF17D18005D684C /* ViewController.swift */; }; + 65AB4D2D1FF17D18005D684C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 65AB4D2B1FF17D18005D684C /* Main.storyboard */; }; + 65AB4D2F1FF17D18005D684C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 65AB4D2E1FF17D18005D684C /* Assets.xcassets */; }; + 65AB4D321FF17D18005D684C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 65AB4D301FF17D18005D684C /* LaunchScreen.storyboard */; }; + 65AB4D3C1FF17DB6005D684C /* AvatarKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65AB4D3B1FF17DB6005D684C /* AvatarKit.framework */; }; + 65AB4D441FF17EB1005D684C /* SBSPuppetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AB4D431FF17EB1005D684C /* SBSPuppetView.swift */; }; + 65AB4D4A1FF18686005D684C /* PuppetThumbnailCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AB4D491FF18686005D684C /* PuppetThumbnailCollectionViewCell.swift */; }; + 65AB4D4C1FF18C0F005D684C /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65AB4D4B1FF18C0F005D684C /* MainView.swift */; }; + 65D4C7431FF1D802009F75C8 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 65D4C7421FF1D802009F75C8 /* README.md */; }; + 65D4C7471FF1D920009F75C8 /* newScreenshot.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 65D4C7461FF1D920009F75C8 /* newScreenshot.jpg */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 65AB4D241FF17D18005D684C /* Animoji.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Animoji.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 65AB4D271FF17D18005D684C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 65AB4D291FF17D18005D684C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 65AB4D2C1FF17D18005D684C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 65AB4D2E1FF17D18005D684C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 65AB4D311FF17D18005D684C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 65AB4D331FF17D18005D684C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 65AB4D3B1FF17DB6005D684C /* AvatarKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AvatarKit.framework; path = Frameworks/AvatarKit.framework; sourceTree = ""; }; + 65AB4D3F1FF17E6D005D684C /* AVTPuppetView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AVTPuppetView.h; sourceTree = ""; }; + 65AB4D401FF17E6D005D684C /* AVTPuppet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AVTPuppet.h; sourceTree = ""; }; + 65AB4D411FF17E6D005D684C /* AVTAvatarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AVTAvatarView.h; sourceTree = ""; }; + 65AB4D431FF17EB1005D684C /* SBSPuppetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SBSPuppetView.swift; sourceTree = ""; }; + 65AB4D451FF17F49005D684C /* Animoji-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Animoji-Bridging-Header.h"; sourceTree = ""; }; + 65AB4D491FF18686005D684C /* PuppetThumbnailCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PuppetThumbnailCollectionViewCell.swift; sourceTree = ""; }; + 65AB4D4B1FF18C0F005D684C /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = ""; }; + 65D4C7421FF1D802009F75C8 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 65D4C7461FF1D920009F75C8 /* newScreenshot.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = newScreenshot.jpg; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 65AB4D211FF17D18005D684C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 65AB4D3C1FF17DB6005D684C /* AvatarKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 65AB4D1B1FF17D18005D684C = { + isa = PBXGroup; + children = ( + 65D4C7451FF1D913009F75C8 /* Github */, + 65AB4D261FF17D18005D684C /* Animoji */, + 65AB4D251FF17D18005D684C /* Products */, + 65AB4D3A1FF17DB5005D684C /* Frameworks */, + ); + sourceTree = ""; + }; + 65AB4D251FF17D18005D684C /* Products */ = { + isa = PBXGroup; + children = ( + 65AB4D241FF17D18005D684C /* Animoji.app */, + ); + name = Products; + sourceTree = ""; + }; + 65AB4D261FF17D18005D684C /* Animoji */ = { + isa = PBXGroup; + children = ( + 65AB4D421FF17EA1005D684C /* Model */, + 65AB4D391FF17D75005D684C /* AvatarKit */, + 65AB4D451FF17F49005D684C /* Animoji-Bridging-Header.h */, + 65AB4D271FF17D18005D684C /* AppDelegate.swift */, + 65AB4D291FF17D18005D684C /* ViewController.swift */, + 65AB4D2B1FF17D18005D684C /* Main.storyboard */, + 65AB4D2E1FF17D18005D684C /* Assets.xcassets */, + 65AB4D301FF17D18005D684C /* LaunchScreen.storyboard */, + 65AB4D331FF17D18005D684C /* Info.plist */, + ); + path = Animoji; + sourceTree = ""; + }; + 65AB4D391FF17D75005D684C /* AvatarKit */ = { + isa = PBXGroup; + children = ( + 65AB4D411FF17E6D005D684C /* AVTAvatarView.h */, + 65AB4D401FF17E6D005D684C /* AVTPuppet.h */, + 65AB4D3F1FF17E6D005D684C /* AVTPuppetView.h */, + ); + path = AvatarKit; + sourceTree = ""; + }; + 65AB4D3A1FF17DB5005D684C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 65AB4D3B1FF17DB6005D684C /* AvatarKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 65AB4D421FF17EA1005D684C /* Model */ = { + isa = PBXGroup; + children = ( + 65AB4D431FF17EB1005D684C /* SBSPuppetView.swift */, + 65AB4D491FF18686005D684C /* PuppetThumbnailCollectionViewCell.swift */, + 65AB4D4B1FF18C0F005D684C /* MainView.swift */, + ); + path = Model; + sourceTree = ""; + }; + 65D4C7451FF1D913009F75C8 /* Github */ = { + isa = PBXGroup; + children = ( + 65D4C7421FF1D802009F75C8 /* README.md */, + 65D4C7461FF1D920009F75C8 /* newScreenshot.jpg */, + ); + name = Github; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 65AB4D231FF17D18005D684C /* Animoji */ = { + isa = PBXNativeTarget; + buildConfigurationList = 65AB4D361FF17D18005D684C /* Build configuration list for PBXNativeTarget "Animoji" */; + buildPhases = ( + 65AB4D201FF17D18005D684C /* Sources */, + 65AB4D211FF17D18005D684C /* Frameworks */, + 65AB4D221FF17D18005D684C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Animoji; + productName = Animoji; + productReference = 65AB4D241FF17D18005D684C /* Animoji.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 65AB4D1C1FF17D18005D684C /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = "Daniel Illescas Romero"; + TargetAttributes = { + 65AB4D231FF17D18005D684C = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 0920; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 65AB4D1F1FF17D18005D684C /* Build configuration list for PBXProject "Animoji" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 65AB4D1B1FF17D18005D684C; + productRefGroup = 65AB4D251FF17D18005D684C /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 65AB4D231FF17D18005D684C /* Animoji */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 65AB4D221FF17D18005D684C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 65AB4D321FF17D18005D684C /* LaunchScreen.storyboard in Resources */, + 65D4C7471FF1D920009F75C8 /* newScreenshot.jpg in Resources */, + 65AB4D2F1FF17D18005D684C /* Assets.xcassets in Resources */, + 65D4C7431FF1D802009F75C8 /* README.md in Resources */, + 65AB4D2D1FF17D18005D684C /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 65AB4D201FF17D18005D684C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 65AB4D2A1FF17D18005D684C /* ViewController.swift in Sources */, + 65AB4D441FF17EB1005D684C /* SBSPuppetView.swift in Sources */, + 65AB4D281FF17D18005D684C /* AppDelegate.swift in Sources */, + 65AB4D4C1FF18C0F005D684C /* MainView.swift in Sources */, + 65AB4D4A1FF18686005D684C /* PuppetThumbnailCollectionViewCell.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 65AB4D2B1FF17D18005D684C /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 65AB4D2C1FF17D18005D684C /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 65AB4D301FF17D18005D684C /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 65AB4D311FF17D18005D684C /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 65AB4D341FF17D18005D684C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 65AB4D351FF17D18005D684C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 65AB4D371FF17D18005D684C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = PRK6268SLD; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Frameworks", + ); + INFOPLIST_FILE = Animoji/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.illescasDaniel.Animoji; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Animoji/Animoji-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 65AB4D381FF17D18005D684C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = PRK6268SLD; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Frameworks", + ); + INFOPLIST_FILE = Animoji/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.illescasDaniel.Animoji; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Animoji/Animoji-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 65AB4D1F1FF17D18005D684C /* Build configuration list for PBXProject "Animoji" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 65AB4D341FF17D18005D684C /* Debug */, + 65AB4D351FF17D18005D684C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 65AB4D361FF17D18005D684C /* Build configuration list for PBXNativeTarget "Animoji" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 65AB4D371FF17D18005D684C /* Debug */, + 65AB4D381FF17D18005D684C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 65AB4D1C1FF17D18005D684C /* Project object */; +} diff --git a/SBSAnimoji.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Animoji.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 70% rename from SBSAnimoji.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Animoji.xcodeproj/project.xcworkspace/contents.xcworkspacedata index e4cc86d..fc1fae2 100644 --- a/SBSAnimoji.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Animoji.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:Animoji.xcodeproj"> diff --git a/Animoji/Animoji-Bridging-Header.h b/Animoji/Animoji-Bridging-Header.h new file mode 100644 index 0000000..da7fc46 --- /dev/null +++ b/Animoji/Animoji-Bridging-Header.h @@ -0,0 +1,7 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "AVTAvatarView.h" +#import "AVTPuppet.h" +#import "AVTPuppetView.h" diff --git a/Animoji/AppDelegate.swift b/Animoji/AppDelegate.swift new file mode 100644 index 0000000..ee67b4c --- /dev/null +++ b/Animoji/AppDelegate.swift @@ -0,0 +1,47 @@ +// +// AppDelegate.swift +// Animoji +// +// Created by Daniel Illescas Romero on 25/12/2017. +// Copyright © 2017 Daniel Illescas Romero. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + self.window = UIWindow(frame: UIScreen.main.bounds) + self.window?.rootViewController = UINavigationController(rootViewController: ViewController()) + self.window?.makeKeyAndVisible() + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/Contents.json b/Animoji/Assets.xcassets/AppIcon.appiconset/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Animoji/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-1024.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-1024.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-1024.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-120.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-120.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-120.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-120.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-121.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-121.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-121.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-121.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-152.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-152.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-152.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-152.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-167.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-167.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-167.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-167.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-180.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-180.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-180.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-180.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-20.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-20.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-20.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-20.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-29.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-29.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-29.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-29.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-40.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-40.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-40.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-40.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-41.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-41.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-41.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-41.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-42.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-42.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-42.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-42.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-58.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-58.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-58.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-58.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-59.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-59.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-59.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-59.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-60.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-60.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-60.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-60.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-76.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-76.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-76.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-76.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-80.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-80.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-80.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-80.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-81.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-81.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-81.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-81.png diff --git a/SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-87.png b/Animoji/Assets.xcassets/AppIcon.appiconset/icon-87.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/AppIcon.appiconset/icon-87.png rename to Animoji/Assets.xcassets/AppIcon.appiconset/icon-87.png diff --git a/SBSAnimoji/Assets.xcassets/Contents.json b/Animoji/Assets.xcassets/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/Contents.json rename to Animoji/Assets.xcassets/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/delete.imageset/Contents.json b/Animoji/Assets.xcassets/delete.imageset/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/delete.imageset/Contents.json rename to Animoji/Assets.xcassets/delete.imageset/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/delete.imageset/delete.png b/Animoji/Assets.xcassets/delete.imageset/delete.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/delete.imageset/delete.png rename to Animoji/Assets.xcassets/delete.imageset/delete.png diff --git a/SBSAnimoji/Assets.xcassets/delete.imageset/delete@2x.png b/Animoji/Assets.xcassets/delete.imageset/delete@2x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/delete.imageset/delete@2x.png rename to Animoji/Assets.xcassets/delete.imageset/delete@2x.png diff --git a/SBSAnimoji/Assets.xcassets/delete.imageset/delete@3x.png b/Animoji/Assets.xcassets/delete.imageset/delete@3x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/delete.imageset/delete@3x.png rename to Animoji/Assets.xcassets/delete.imageset/delete@3x.png diff --git a/SBSAnimoji/Assets.xcassets/selection.imageset/Contents.json b/Animoji/Assets.xcassets/selection.imageset/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/selection.imageset/Contents.json rename to Animoji/Assets.xcassets/selection.imageset/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/selection.imageset/selection.png b/Animoji/Assets.xcassets/selection.imageset/selection.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/selection.imageset/selection.png rename to Animoji/Assets.xcassets/selection.imageset/selection.png diff --git a/SBSAnimoji/Assets.xcassets/selection.imageset/selection@2x.png b/Animoji/Assets.xcassets/selection.imageset/selection@2x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/selection.imageset/selection@2x.png rename to Animoji/Assets.xcassets/selection.imageset/selection@2x.png diff --git a/SBSAnimoji/Assets.xcassets/selection.imageset/selection@3x.png b/Animoji/Assets.xcassets/selection.imageset/selection@3x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/selection.imageset/selection@3x.png rename to Animoji/Assets.xcassets/selection.imageset/selection@3x.png diff --git a/SBSAnimoji/Assets.xcassets/share.imageset/Contents.json b/Animoji/Assets.xcassets/share.imageset/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/share.imageset/Contents.json rename to Animoji/Assets.xcassets/share.imageset/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/share.imageset/share.png b/Animoji/Assets.xcassets/share.imageset/share.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/share.imageset/share.png rename to Animoji/Assets.xcassets/share.imageset/share.png diff --git a/SBSAnimoji/Assets.xcassets/share.imageset/share@2x.png b/Animoji/Assets.xcassets/share.imageset/share@2x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/share.imageset/share@2x.png rename to Animoji/Assets.xcassets/share.imageset/share@2x.png diff --git a/SBSAnimoji/Assets.xcassets/share.imageset/share@3x.png b/Animoji/Assets.xcassets/share.imageset/share@3x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/share.imageset/share@3x.png rename to Animoji/Assets.xcassets/share.imageset/share@3x.png diff --git a/SBSAnimoji/Assets.xcassets/start-previewing.imageset/Contents.json b/Animoji/Assets.xcassets/start-previewing.imageset/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/start-previewing.imageset/Contents.json rename to Animoji/Assets.xcassets/start-previewing.imageset/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/start-previewing.imageset/play.png b/Animoji/Assets.xcassets/start-previewing.imageset/play.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/start-previewing.imageset/play.png rename to Animoji/Assets.xcassets/start-previewing.imageset/play.png diff --git a/SBSAnimoji/Assets.xcassets/start-previewing.imageset/play@2x.png b/Animoji/Assets.xcassets/start-previewing.imageset/play@2x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/start-previewing.imageset/play@2x.png rename to Animoji/Assets.xcassets/start-previewing.imageset/play@2x.png diff --git a/SBSAnimoji/Assets.xcassets/start-previewing.imageset/play@3x.png b/Animoji/Assets.xcassets/start-previewing.imageset/play@3x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/start-previewing.imageset/play@3x.png rename to Animoji/Assets.xcassets/start-previewing.imageset/play@3x.png diff --git a/SBSAnimoji/Assets.xcassets/start-recording.imageset/Contents.json b/Animoji/Assets.xcassets/start-recording.imageset/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/start-recording.imageset/Contents.json rename to Animoji/Assets.xcassets/start-recording.imageset/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/start-recording.imageset/record.png b/Animoji/Assets.xcassets/start-recording.imageset/record.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/start-recording.imageset/record.png rename to Animoji/Assets.xcassets/start-recording.imageset/record.png diff --git a/SBSAnimoji/Assets.xcassets/start-recording.imageset/record@2x.png b/Animoji/Assets.xcassets/start-recording.imageset/record@2x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/start-recording.imageset/record@2x.png rename to Animoji/Assets.xcassets/start-recording.imageset/record@2x.png diff --git a/SBSAnimoji/Assets.xcassets/start-recording.imageset/record@3x.png b/Animoji/Assets.xcassets/start-recording.imageset/record@3x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/start-recording.imageset/record@3x.png rename to Animoji/Assets.xcassets/start-recording.imageset/record@3x.png diff --git a/SBSAnimoji/Assets.xcassets/stop-previewing.imageset/Contents.json b/Animoji/Assets.xcassets/stop-previewing.imageset/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/stop-previewing.imageset/Contents.json rename to Animoji/Assets.xcassets/stop-previewing.imageset/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/stop-previewing.imageset/stop.png b/Animoji/Assets.xcassets/stop-previewing.imageset/stop.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/stop-previewing.imageset/stop.png rename to Animoji/Assets.xcassets/stop-previewing.imageset/stop.png diff --git a/SBSAnimoji/Assets.xcassets/stop-previewing.imageset/stop@2x.png b/Animoji/Assets.xcassets/stop-previewing.imageset/stop@2x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/stop-previewing.imageset/stop@2x.png rename to Animoji/Assets.xcassets/stop-previewing.imageset/stop@2x.png diff --git a/SBSAnimoji/Assets.xcassets/stop-previewing.imageset/stop@3x.png b/Animoji/Assets.xcassets/stop-previewing.imageset/stop@3x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/stop-previewing.imageset/stop@3x.png rename to Animoji/Assets.xcassets/stop-previewing.imageset/stop@3x.png diff --git a/SBSAnimoji/Assets.xcassets/stop-recording.imageset/Contents.json b/Animoji/Assets.xcassets/stop-recording.imageset/Contents.json old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/stop-recording.imageset/Contents.json rename to Animoji/Assets.xcassets/stop-recording.imageset/Contents.json diff --git a/SBSAnimoji/Assets.xcassets/stop-recording.imageset/stop.png b/Animoji/Assets.xcassets/stop-recording.imageset/stop.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/stop-recording.imageset/stop.png rename to Animoji/Assets.xcassets/stop-recording.imageset/stop.png diff --git a/SBSAnimoji/Assets.xcassets/stop-recording.imageset/stop@2x.png b/Animoji/Assets.xcassets/stop-recording.imageset/stop@2x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/stop-recording.imageset/stop@2x.png rename to Animoji/Assets.xcassets/stop-recording.imageset/stop@2x.png diff --git a/SBSAnimoji/Assets.xcassets/stop-recording.imageset/stop@3x.png b/Animoji/Assets.xcassets/stop-recording.imageset/stop@3x.png old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/Assets.xcassets/stop-recording.imageset/stop@3x.png rename to Animoji/Assets.xcassets/stop-recording.imageset/stop@3x.png diff --git a/SBSAnimoji/AvatarKit/AVTAvatarView.h b/Animoji/AvatarKit/AVTAvatarView.h old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/AvatarKit/AVTAvatarView.h rename to Animoji/AvatarKit/AVTAvatarView.h diff --git a/SBSAnimoji/AvatarKit/AVTPuppet.h b/Animoji/AvatarKit/AVTPuppet.h old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/AvatarKit/AVTPuppet.h rename to Animoji/AvatarKit/AVTPuppet.h diff --git a/SBSAnimoji/AvatarKit/AVTPuppetView.h b/Animoji/AvatarKit/AVTPuppetView.h old mode 100644 new mode 100755 similarity index 100% rename from SBSAnimoji/AvatarKit/AVTPuppetView.h rename to Animoji/AvatarKit/AVTPuppetView.h diff --git a/Animoji/Base.lproj/LaunchScreen.storyboard b/Animoji/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f83f6fd --- /dev/null +++ b/Animoji/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Animoji/Base.lproj/Main.storyboard b/Animoji/Base.lproj/Main.storyboard new file mode 100644 index 0000000..03c13c2 --- /dev/null +++ b/Animoji/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SBSAnimoji/Supporting files/Info.plist b/Animoji/Info.plist similarity index 96% rename from SBSAnimoji/Supporting files/Info.plist rename to Animoji/Info.plist index 3207892..d597b65 100644 --- a/SBSAnimoji/Supporting files/Info.plist +++ b/Animoji/Info.plist @@ -20,14 +20,10 @@ 1 LSRequiresIPhoneOS - NSCameraUsageDescription - Tracking your face - NSMicrophoneUsageDescription - Recording your voice - NSPhotoLibraryAddUsageDescription - Saving your video UILaunchStoryboardName LaunchScreen + UIMainStoryboardFile + Main UIRequiredDeviceCapabilities armv7 @@ -43,5 +39,11 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + NSCameraUsageDescription + Tracking your face + NSMicrophoneUsageDescription + Recording your voice + NSPhotoLibraryAddUsageDescription + Saving your video diff --git a/Animoji/Model/MainView.swift b/Animoji/Model/MainView.swift new file mode 100644 index 0000000..460cf25 --- /dev/null +++ b/Animoji/Model/MainView.swift @@ -0,0 +1,135 @@ +// +// MainView.swift +// Animoji +// +// Created by Daniel Illescas Romero on 25/12/2017. +// Copyright © 2017 Daniel Illescas Romero. All rights reserved. +// + +import UIKit + +@objc class MainView: UIView { + + var puppetView = SBSPuppetView() + var thumbnailsCollectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout()) + var recordButton = UIButton(type: .system) + var shareButton = UIButton(type: .system) + var deleteButton = UIButton(type: .system) + var previewButton = UIButton(type: .system) + var activityIndicatorView = UIActivityIndicatorView() + var durationLabel = UILabel() + var puppetViewSeparatorView = UIView() + + override init(frame: CGRect) { + super.init(frame: frame) + self.setupView() + self.setupLayout() + } + + func setupView() { + + self.backgroundColor = .white + + self.puppetView.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(self.puppetView) + + self.puppetViewSeparatorView.translatesAutoresizingMaskIntoConstraints = false + self.puppetViewSeparatorView.backgroundColor = UIColor(red: 224.0/255.0, green: 224.0/255.0, blue: 224.0/255.0, alpha: 1.0) + self.addSubview(self.puppetViewSeparatorView) + + let collectionViewLayout = UICollectionViewFlowLayout() + collectionViewLayout.scrollDirection = .vertical + collectionViewLayout.minimumInteritemSpacing = 14 + collectionViewLayout.minimumLineSpacing = 10 + + self.thumbnailsCollectionView.setCollectionViewLayout(collectionViewLayout, animated: true) + self.thumbnailsCollectionView.translatesAutoresizingMaskIntoConstraints = false + self.thumbnailsCollectionView.backgroundColor = .white + self.thumbnailsCollectionView.contentInset = UIEdgeInsets(top: 15, left: 7, bottom: 15, right: 7) + self.thumbnailsCollectionView.showsHorizontalScrollIndicator = false + self.addSubview(self.thumbnailsCollectionView) + + self.durationLabel.translatesAutoresizingMaskIntoConstraints = false + self.durationLabel.textAlignment = .right + self.durationLabel.font = .systemFont(ofSize: 14, weight: .medium) + self.durationLabel.isHidden = true + self.addSubview(self.durationLabel) + + self.deleteButton.translatesAutoresizingMaskIntoConstraints = false + self.deleteButton.isHidden = true + self.deleteButton.setImage(#imageLiteral(resourceName: "delete"), for: .normal) + self.addSubview(self.deleteButton) + + self.previewButton.translatesAutoresizingMaskIntoConstraints = false + self.previewButton.isHidden = true + self.previewButton.setImage(#imageLiteral(resourceName: "start-previewing"), for: .normal) + self.addSubview(self.previewButton) + + self.recordButton.translatesAutoresizingMaskIntoConstraints = false + self.recordButton.setImage(#imageLiteral(resourceName: "start-recording"), for: .normal) + self.addSubview(self.recordButton) + + self.shareButton.translatesAutoresizingMaskIntoConstraints = false + self.shareButton.isHidden = true + self.shareButton.setImage(#imageLiteral(resourceName: "share"), for: .normal) + self.addSubview(self.shareButton) + + self.activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false + self.activityIndicatorView.hidesWhenStopped = true + self.addSubview(self.activityIndicatorView) + } + + func setupLayout() { + + self.puppetView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true + self.puppetView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true + self.puppetView.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor).isActive = true + self.puppetView.heightAnchor.constraint(equalToConstant: 355).isActive = true + + self.puppetViewSeparatorView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true + self.puppetViewSeparatorView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true + self.puppetViewSeparatorView.topAnchor.constraint(equalTo: self.puppetView.bottomAnchor).isActive = true + self.puppetViewSeparatorView.heightAnchor.constraint(equalToConstant: 2).isActive = true + + self.thumbnailsCollectionView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true + self.thumbnailsCollectionView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true + self.thumbnailsCollectionView.topAnchor.constraint(equalTo: self.puppetViewSeparatorView.bottomAnchor).isActive = true + self.thumbnailsCollectionView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true + + self.durationLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true + self.durationLabel.topAnchor.constraint(equalTo: self.puppetView.topAnchor, constant: 15).isActive = true + + self.recordButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true + self.recordButton.bottomAnchor.constraint(equalTo: self.puppetView.bottomAnchor, constant: -20).isActive = true + + self.shareButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true + self.shareButton.bottomAnchor.constraint(equalTo: self.puppetView.bottomAnchor, constant: -20).isActive = true + + self.deleteButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true + self.deleteButton.topAnchor.constraint(equalTo: self.puppetView.topAnchor, constant: 15).isActive = true + + self.previewButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true + self.previewButton.topAnchor.constraint(equalTo: self.deleteButton.bottomAnchor, constant: 15).isActive = true + + self.activityIndicatorView.centerXAnchor.constraint(equalTo: self.shareButton.centerXAnchor).isActive = true + self.activityIndicatorView.centerYAnchor.constraint(equalTo: self.shareButton.centerYAnchor).isActive = true + } + + override func layoutSubviews() { + super.layoutSubviews() + + let itemsPerRow: CGFloat = 4 + let collectionView = self.thumbnailsCollectionView + let contentInset = collectionView.contentInset + + if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { + let availableWidth = self.bounds.size.width - contentInset.left - contentInset.right - (itemsPerRow - 1) * flowLayout.minimumInteritemSpacing + let itemLength = floor(availableWidth / itemsPerRow) + flowLayout.itemSize = CGSize(width: itemLength, height: itemLength) + } + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Animoji/Model/PuppetThumbnailCollectionViewCell.swift b/Animoji/Model/PuppetThumbnailCollectionViewCell.swift new file mode 100644 index 0000000..71c4f6d --- /dev/null +++ b/Animoji/Model/PuppetThumbnailCollectionViewCell.swift @@ -0,0 +1,51 @@ +// +// PuppetThumbnailCollectionViewCell.swift +// Animoji +// +// Created by Daniel Illescas Romero on 25/12/2017. +// Copyright © 2017 Daniel Illescas Romero. All rights reserved. +// + +import UIKit + +@objc class PuppetThumbnailCollectionViewCell: UICollectionViewCell, UICollectionViewDelegate { + + var thumbnailImageView = UIImageView() + var selectionImageView = UIImageView() + + override init(frame: CGRect) { + super.init(frame: CGRect.zero) + self.setupView() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupView() { + + self.backgroundColor = .white + + self.thumbnailImageView.translatesAutoresizingMaskIntoConstraints = false + self.thumbnailImageView.contentMode = .scaleAspectFit + self.contentView.addSubview(self.thumbnailImageView) + + self.selectionImageView.image = #imageLiteral(resourceName: "selection") + self.selectionImageView.translatesAutoresizingMaskIntoConstraints = false + self.selectionImageView.isHidden = true + self.contentView.addSubview(self.selectionImageView) + } + + override func layoutSubviews() { + super.layoutSubviews() + let thumbnailMargins = UIEdgeInsetsMake(7, 7, 7, 7) + self.thumbnailImageView.frame = UIEdgeInsetsInsetRect(self.contentView.bounds, thumbnailMargins) + self.selectionImageView.frame = self.contentView.bounds + } + + override var isSelected: Bool { + didSet { + self.selectionImageView.isHidden = !isSelected + } + } +} diff --git a/Animoji/Model/SBSPuppetView.swift b/Animoji/Model/SBSPuppetView.swift new file mode 100644 index 0000000..33a2cca --- /dev/null +++ b/Animoji/Model/SBSPuppetView.swift @@ -0,0 +1,67 @@ +// +// SBSPuppetView.swift +// Animoji +// +// Created by Daniel Illescas Romero on 25/12/2017. +// Copyright © 2017 Daniel Illescas Romero. All rights reserved. +// + +import UIKit + +@objc protocol SBSPuppetViewDelegate: NSObjectProtocol { + func puppetViewDidFinishPlaying(puppetView: SBSPuppetView) + func puppetViewDidStartRecording(puppetView: SBSPuppetView) + func puppetViewDidStopRecording(puppetView: SBSPuppetView) +} + +@objc class SBSPuppetView: AVTPuppetView { + + var sbsDelegate: SBSPuppetViewDelegate? + + override public func audioPlayerItemDidReachEnd(_ arg1: Any!) { + super.audioPlayerItemDidReachEnd(arg1) + if self.sbsDelegate?.responds(to: #selector(self.sbsDelegate?.puppetViewDidFinishPlaying(puppetView:))) == true { + self.sbsDelegate?.puppetViewDidFinishPlaying(puppetView: self) + } + } + + override func startRecording() { + super.startRecording() + + let recordingDuration = 60 // seconds + + let duration = recordingDuration * 60 + + let timesBuffer = NSMutableData(capacity: duration * 8) + let blendShapeBuffer = NSMutableData(capacity: duration * 204) + let transformData = NSMutableData(capacity: duration * 64) + + self.setValue(duration, forKey: "_recordingCapacity") + self.setValue(timesBuffer, forKey: "_rawTimesData") + self.setValue(blendShapeBuffer, forKey: "_rawBlendShapesData") + self.setValue(transformData, forKey: "_rawTransformsData") + + if let ivarRawTimes = class_getInstanceVariable(AVTPuppetView.self, "_rawTimes") { + object_setIvar(self, ivarRawTimes, timesBuffer?.mutableBytes) + } + + if let ivarBlendShapes = class_getInstanceVariable(AVTPuppetView.self, "_rawBlendShapes") { + object_setIvar(self, ivarBlendShapes, blendShapeBuffer?.mutableBytes) + } + + if let ivarRawTransforms = class_getInstanceVariable(AVTPuppetView.self, "_rawTransforms") { + object_setIvar(self, ivarRawTransforms, transformData?.mutableBytes) + } + + if self.sbsDelegate?.responds(to: #selector(self.sbsDelegate?.puppetViewDidStartRecording(puppetView:))) == true { + self.sbsDelegate?.puppetViewDidStartRecording(puppetView: self) + } + } + + override func stopRecording() { + super.stopRecording() + if self.sbsDelegate?.responds(to: #selector(self.sbsDelegate?.puppetViewDidStopRecording(puppetView:))) == true { + self.sbsDelegate?.puppetViewDidStopRecording(puppetView: self) + } + } +} diff --git a/Animoji/ViewController.swift b/Animoji/ViewController.swift new file mode 100644 index 0000000..4e50764 --- /dev/null +++ b/Animoji/ViewController.swift @@ -0,0 +1,212 @@ +// +// ViewController.swift +// Animoji +// +// Created by Daniel Illescas Romero on 25/12/2017. +// Copyright © 2017 Daniel Illescas Romero. All rights reserved. +// + +import UIKit + +@objc class ViewController: UIViewController, SBSPuppetViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate { + + var puppetNames = AVTPuppet.puppetNames() as? [String] + + var contentView: MainView? { + return self.view as? MainView + } + + var movieURL: URL? { + let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last + return documentURL?.appendingPathComponent("animoji.mov") + } + + var hasExportedMovie = Bool() + var isExporting = Bool() + var durationTimer = Timer() + + override func viewDidLoad() { + super.viewDidLoad() + + self.title = "Animoji" + self.view = MainView() + + self.contentView?.puppetView.sbsDelegate = self + + self.contentView?.thumbnailsCollectionView.dataSource = self + self.contentView?.thumbnailsCollectionView.delegate = self + self.contentView?.thumbnailsCollectionView.register(PuppetThumbnailCollectionViewCell.self, forCellWithReuseIdentifier: "thumbnail") + + self.contentView?.recordButton.addTarget(self, action: #selector(self.toggleRecording), for: .touchUpInside) + self.contentView?.deleteButton.addTarget(self, action: #selector(self.removeRecording), for: .touchUpInside) + self.contentView?.previewButton.addTarget(self, action: #selector(self.startPreview), for: .touchUpInside) + self.contentView?.shareButton.addTarget(self, action: #selector(self.share), for: .touchUpInside) + + if let name = self.puppetNames?[0] { + self.showPuppetName(puppetName: name) + } + self.contentView?.thumbnailsCollectionView.selectItem(at: IndexPath(row: 0, section: 0), animated: false, scrollPosition: []) + } + + deinit { + self.contentView?.puppetView.removeObserver(self, forKeyPath: "recording") + } + + @objc func durationTimerTriggered() { + let recordingDuration = ceil(self.contentView?.puppetView.recordingDuration() ?? 0.0) + let minutes = floor(recordingDuration / 60); + let seconds = recordingDuration.truncatingRemainder(dividingBy: 60); + self.contentView?.durationLabel.text = "\(minutes):\(seconds)" + } + + func removeExistingMovieFile() { + let fileManager = FileManager.default + if let movieURL = self.movieURL, fileManager.fileExists(atPath: movieURL.path) { + try? fileManager.removeItem(at: movieURL) + } + } + + // MARK: SBSPuppetViewDelegate + + public func puppetViewDidFinishPlaying(puppetView: SBSPuppetView) { + if !puppetView.recording { + self.stopPreview() + } + } + + public func puppetViewDidStartRecording(puppetView: SBSPuppetView) { + self.hasExportedMovie = false + self.removeExistingMovieFile() + self.contentView?.recordButton.setImage(#imageLiteral(resourceName: "stop-recording"), for: .normal) + self.contentView?.durationLabel.text = "00:00" + self.contentView?.durationLabel.isHidden = false + + self.durationTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.durationTimerTriggered), userInfo: nil, repeats: true) + + self.contentView?.thumbnailsCollectionView.isUserInteractionEnabled = false + + UIView.animate(withDuration: 0.3, animations: { + self.contentView?.thumbnailsCollectionView.alpha = 0.5 + }) + } + + public func puppetViewDidStopRecording(puppetView: SBSPuppetView) { + if self.isExporting { return } + self.durationTimer.invalidate() + self.contentView?.recordButton.isHidden = true + self.contentView?.shareButton.isHidden = false + self.contentView?.deleteButton.isHidden = false + self.contentView?.previewButton.isHidden = false + self.contentView?.durationLabel.isHidden = true + self.contentView?.recordButton.setImage(#imageLiteral(resourceName: "start-recording"), for: .normal) + self.contentView?.thumbnailsCollectionView.isUserInteractionEnabled = true + + UIView.animate(withDuration: 0.3, animations: { + self.contentView?.thumbnailsCollectionView.alpha = 1 + }) + self.startPreview() + } + + // MARK: UICollectionViewDataSource + + public func numberOfSections(in collectionView: UICollectionView) -> Int { + return 1 + } + + public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return self.puppetNames?.count ?? 0 + } + + public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + + if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "thumbnail", for: indexPath) as? PuppetThumbnailCollectionViewCell { + if let name = self.puppetNames?[indexPath.item] { + cell.thumbnailImageView.image = AVTPuppet.thumbnail(forPuppetNamed: name, options: nil) + return cell + } + } + return UICollectionViewCell() + } + + // MARK: UICollectionViewDelegate + + public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if let name = self.puppetNames?[indexPath.item] { + self.showPuppetName(puppetName: name) + } + } + + // MARK: Convenience + + @objc private func share() { + self.exportMovieIfNecessary { [unowned self] movieURL in + let activityViewController = UIActivityViewController(activityItems: [movieURL], applicationActivities: nil) + self.present(activityViewController, animated: true) + } + } + + private func exportMovieIfNecessary(completion: @escaping (URL) -> ()) { + + guard let movieURL = self.movieURL else { return } + + if self.hasExportedMovie { + completion(movieURL) + } else { + self.isExporting = true + self.contentView?.activityIndicatorView.startAnimating() + self.contentView?.deleteButton.isEnabled = false + self.contentView?.shareButton.isHidden = true + + self.contentView?.puppetView.exportMovie(toURL: movieURL, options: nil, completionHandler: { [unowned self] in + self.hasExportedMovie = true + self.contentView?.activityIndicatorView.stopAnimating() + self.contentView?.deleteButton.isEnabled = true + self.contentView?.shareButton.isHidden = false + self.isExporting = false + completion(movieURL) + }) + } + } + + @objc private func removeRecording() { + self.hasExportedMovie = false + self.removeExistingMovieFile() + self.contentView?.puppetView.stopRecording() + self.contentView?.puppetView.stopPreviewing() + self.contentView?.recordButton.isHidden = false + self.contentView?.deleteButton.isHidden = true + self.contentView?.previewButton.isHidden = true + self.contentView?.shareButton.isHidden = true + } + + @objc private func toggleRecording() { + if self.contentView?.puppetView.recording == true { + self.contentView?.puppetView.stopRecording() + } else { + self.contentView?.puppetView.startRecording() + } + } + + @objc private func startPreview() { + self.contentView?.previewButton.removeTarget(self, action: #selector(self.startPreview), for: .touchUpInside) + self.contentView?.previewButton.addTarget(self, action: #selector(self.stopPreview), for: .touchUpInside) + self.contentView?.previewButton.setImage(#imageLiteral(resourceName: "stop-previewing"), for: .normal) + self.contentView?.puppetView.stopPreviewing() + self.contentView?.puppetView.startPreviewing() + } + + @objc private func stopPreview() { + self.contentView?.previewButton.removeTarget(self, action: #selector(self.stopPreview), for: .touchUpInside) + self.contentView?.previewButton.addTarget(self, action: #selector(self.startPreview), for: .touchUpInside) + self.contentView?.previewButton.setImage(#imageLiteral(resourceName: "start-previewing"), for: .normal) + self.contentView?.puppetView.stopPreviewing() + } + + private func showPuppetName(puppetName: String) { + if let puppet = AVTPuppet.puppetNamed(puppetName, options: nil) as? AVTPuppet { + self.contentView?.puppetView.setValue(puppet, forKey: "avatarInstance") + } + } +} + + diff --git a/Frameworks/AvatarKit.framework/AvatarKit.tbd b/Frameworks/AvatarKit.framework/AvatarKit.tbd old mode 100644 new mode 100755 diff --git a/README.md b/README.md index 5a6ed27..bde4c17 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,9 @@ -# SBSAnimoji +## Animoji -Fooling around with Apples private framework AvatarKit, the framework used in Messages.app for recording Animoji videos. +[simonbs](https://github.com/simonbs)'s [SBSAnimoji](https://github.com/simonbs/SBSAnimoji) project fully converted to **Swift 4**. -![Screenshot](https://github.com/simonbs/SBSAnimoji/raw/master/screenshot.png) + -### What you get +### FIMXE: +- Recording is not working, when pressing the button the app crashes -- Record Animoji videos of up to 60 seconds. Previously 20 seconds. Thanks, [Khaos Tian](https://github.com/KhaosT)! -- Share your Animoji videos with the native share sheet. -- Export videos to your photo library from the native share sheet. -- An example of how to use Apples AvatarKit. - -### What you don't get - -- Error handling. Should you encounter an error, try restarting the app. -- Support for the simulator. Run the app on your phone instead. - -# Notice - -This project relies heavily on Apples private API and you should therefore not try to submit this code to App Store. diff --git a/SBSAnimoji.xcodeproj/project.pbxproj b/SBSAnimoji.xcodeproj/project.pbxproj deleted file mode 100644 index 9dc566e..0000000 --- a/SBSAnimoji.xcodeproj/project.pbxproj +++ /dev/null @@ -1,415 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - 7203856D1FB0FA1B00FDEDE6 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7203853C1FB0FA1A00FDEDE6 /* Localizable.strings */; }; - 7203856E1FB0FA1B00FDEDE6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7203853D1FB0FA1A00FDEDE6 /* main.m */; }; - 7203856F1FB0FA1B00FDEDE6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7203853F1FB0FA1A00FDEDE6 /* LaunchScreen.storyboard */; }; - 720385701FB0FA1B00FDEDE6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 720385611FB0FA1A00FDEDE6 /* Assets.xcassets */; }; - 720385711FB0FA1B00FDEDE6 /* MainView.m in Sources */ = {isa = PBXBuildFile; fileRef = 720385641FB0FA1A00FDEDE6 /* MainView.m */; }; - 720385721FB0FA1B00FDEDE6 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 720385661FB0FA1A00FDEDE6 /* MainViewController.m */; }; - 720385731FB0FA1B00FDEDE6 /* PuppetThumbnailCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 720385681FB0FA1A00FDEDE6 /* PuppetThumbnailCollectionViewCell.m */; }; - 720385741FB0FA1B00FDEDE6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7203856B1FB0FA1A00FDEDE6 /* AppDelegate.m */; }; - 720385771FB0FA2800FDEDE6 /* AvatarKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 720385761FB0FA2800FDEDE6 /* AvatarKit.framework */; }; - 72E21EE51FB101BC00F7C115 /* SBSPuppetView.m in Sources */ = {isa = PBXBuildFile; fileRef = 72E21EE41FB101BC00F7C115 /* SBSPuppetView.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 720385211FB0F9D900FDEDE6 /* SBSAnimoji.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SBSAnimoji.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7203853B1FB0FA1A00FDEDE6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 7203853C1FB0FA1A00FDEDE6 /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; }; - 7203853D1FB0FA1A00FDEDE6 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 720385401FB0FA1A00FDEDE6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 7203854B1FB0FA1A00FDEDE6 /* AVTAvatarView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVTAvatarView.h; sourceTree = ""; }; - 720385581FB0FA1A00FDEDE6 /* AVTPuppet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVTPuppet.h; sourceTree = ""; }; - 7203855B1FB0FA1A00FDEDE6 /* AVTPuppetView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVTPuppetView.h; sourceTree = ""; }; - 720385611FB0FA1A00FDEDE6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 720385631FB0FA1A00FDEDE6 /* MainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainView.h; sourceTree = ""; }; - 720385641FB0FA1A00FDEDE6 /* MainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainView.m; sourceTree = ""; }; - 720385651FB0FA1A00FDEDE6 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; - 720385661FB0FA1A00FDEDE6 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; - 720385671FB0FA1A00FDEDE6 /* PuppetThumbnailCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PuppetThumbnailCollectionViewCell.h; sourceTree = ""; }; - 720385681FB0FA1A00FDEDE6 /* PuppetThumbnailCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PuppetThumbnailCollectionViewCell.m; sourceTree = ""; }; - 7203856A1FB0FA1A00FDEDE6 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 7203856B1FB0FA1A00FDEDE6 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 720385761FB0FA2800FDEDE6 /* AvatarKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AvatarKit.framework; sourceTree = ""; }; - 72E21EE31FB101BC00F7C115 /* SBSPuppetView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBSPuppetView.h; sourceTree = ""; }; - 72E21EE41FB101BC00F7C115 /* SBSPuppetView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBSPuppetView.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7203851E1FB0F9D900FDEDE6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 720385771FB0FA2800FDEDE6 /* AvatarKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 720385181FB0F9D900FDEDE6 = { - isa = PBXGroup; - children = ( - 720385231FB0F9D900FDEDE6 /* SBSAnimoji */, - 720385751FB0FA2800FDEDE6 /* Frameworks */, - 720385221FB0F9D900FDEDE6 /* Products */, - ); - sourceTree = ""; - }; - 720385221FB0F9D900FDEDE6 /* Products */ = { - isa = PBXGroup; - children = ( - 720385211FB0F9D900FDEDE6 /* SBSAnimoji.app */, - ); - name = Products; - sourceTree = ""; - }; - 720385231FB0F9D900FDEDE6 /* SBSAnimoji */ = { - isa = PBXGroup; - children = ( - 720385611FB0FA1A00FDEDE6 /* Assets.xcassets */, - 720385691FB0FA1A00FDEDE6 /* Application */, - 720385411FB0FA1A00FDEDE6 /* AvatarKit */, - 720385621FB0FA1A00FDEDE6 /* Pages */, - 7203853E1FB0FA1A00FDEDE6 /* User interface */, - 7203853A1FB0FA1A00FDEDE6 /* Supporting files */, - ); - path = SBSAnimoji; - sourceTree = ""; - }; - 7203853A1FB0FA1A00FDEDE6 /* Supporting files */ = { - isa = PBXGroup; - children = ( - 7203853B1FB0FA1A00FDEDE6 /* Info.plist */, - 7203853C1FB0FA1A00FDEDE6 /* Localizable.strings */, - 7203853D1FB0FA1A00FDEDE6 /* main.m */, - ); - path = "Supporting files"; - sourceTree = ""; - }; - 7203853E1FB0FA1A00FDEDE6 /* User interface */ = { - isa = PBXGroup; - children = ( - 7203853F1FB0FA1A00FDEDE6 /* LaunchScreen.storyboard */, - ); - path = "User interface"; - sourceTree = ""; - }; - 720385411FB0FA1A00FDEDE6 /* AvatarKit */ = { - isa = PBXGroup; - children = ( - 7203854B1FB0FA1A00FDEDE6 /* AVTAvatarView.h */, - 720385581FB0FA1A00FDEDE6 /* AVTPuppet.h */, - 7203855B1FB0FA1A00FDEDE6 /* AVTPuppetView.h */, - ); - path = AvatarKit; - sourceTree = ""; - }; - 720385621FB0FA1A00FDEDE6 /* Pages */ = { - isa = PBXGroup; - children = ( - 72E21EE61FB1028C00F7C115 /* Main */, - ); - path = Pages; - sourceTree = ""; - }; - 720385691FB0FA1A00FDEDE6 /* Application */ = { - isa = PBXGroup; - children = ( - 7203856A1FB0FA1A00FDEDE6 /* AppDelegate.h */, - 7203856B1FB0FA1A00FDEDE6 /* AppDelegate.m */, - ); - path = Application; - sourceTree = ""; - }; - 720385751FB0FA2800FDEDE6 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 720385761FB0FA2800FDEDE6 /* AvatarKit.framework */, - ); - path = Frameworks; - sourceTree = ""; - }; - 72E21EE61FB1028C00F7C115 /* Main */ = { - isa = PBXGroup; - children = ( - 72E21EE31FB101BC00F7C115 /* SBSPuppetView.h */, - 72E21EE41FB101BC00F7C115 /* SBSPuppetView.m */, - 720385671FB0FA1A00FDEDE6 /* PuppetThumbnailCollectionViewCell.h */, - 720385681FB0FA1A00FDEDE6 /* PuppetThumbnailCollectionViewCell.m */, - 720385631FB0FA1A00FDEDE6 /* MainView.h */, - 720385641FB0FA1A00FDEDE6 /* MainView.m */, - 720385651FB0FA1A00FDEDE6 /* MainViewController.h */, - 720385661FB0FA1A00FDEDE6 /* MainViewController.m */, - ); - path = Main; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 720385201FB0F9D900FDEDE6 /* SBSAnimoji */ = { - isa = PBXNativeTarget; - buildConfigurationList = 720385371FB0F9DA00FDEDE6 /* Build configuration list for PBXNativeTarget "SBSAnimoji" */; - buildPhases = ( - 7203851D1FB0F9D900FDEDE6 /* Sources */, - 7203851E1FB0F9D900FDEDE6 /* Frameworks */, - 7203851F1FB0F9D900FDEDE6 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SBSAnimoji; - productName = SBSAnimoji; - productReference = 720385211FB0F9D900FDEDE6 /* SBSAnimoji.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 720385191FB0F9D900FDEDE6 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0910; - ORGANIZATIONNAME = SimonBS; - TargetAttributes = { - 720385201FB0F9D900FDEDE6 = { - CreatedOnToolsVersion = 9.1; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = 7203851C1FB0F9D900FDEDE6 /* Build configuration list for PBXProject "SBSAnimoji" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 720385181FB0F9D900FDEDE6; - productRefGroup = 720385221FB0F9D900FDEDE6 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 720385201FB0F9D900FDEDE6 /* SBSAnimoji */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7203851F1FB0F9D900FDEDE6 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7203856F1FB0FA1B00FDEDE6 /* LaunchScreen.storyboard in Resources */, - 7203856D1FB0FA1B00FDEDE6 /* Localizable.strings in Resources */, - 720385701FB0FA1B00FDEDE6 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7203851D1FB0F9D900FDEDE6 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7203856E1FB0FA1B00FDEDE6 /* main.m in Sources */, - 720385721FB0FA1B00FDEDE6 /* MainViewController.m in Sources */, - 720385711FB0FA1B00FDEDE6 /* MainView.m in Sources */, - 72E21EE51FB101BC00F7C115 /* SBSPuppetView.m in Sources */, - 720385731FB0FA1B00FDEDE6 /* PuppetThumbnailCollectionViewCell.m in Sources */, - 720385741FB0FA1B00FDEDE6 /* AppDelegate.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 7203853F1FB0FA1A00FDEDE6 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 720385401FB0FA1A00FDEDE6 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 720385351FB0F9DA00FDEDE6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.1; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 720385361FB0F9DA00FDEDE6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.1; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 720385381FB0F9DA00FDEDE6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 8NQFWJHC63; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Frameworks", - ); - INFOPLIST_FILE = "$(SRCROOT)/SBSAnimoji/Supporting files/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = dk.simonbs.SBSAnimoji; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Debug; - }; - 720385391FB0F9DA00FDEDE6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 8NQFWJHC63; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Frameworks", - ); - INFOPLIST_FILE = "$(SRCROOT)/SBSAnimoji/Supporting files/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = dk.simonbs.SBSAnimoji; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7203851C1FB0F9D900FDEDE6 /* Build configuration list for PBXProject "SBSAnimoji" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 720385351FB0F9DA00FDEDE6 /* Debug */, - 720385361FB0F9DA00FDEDE6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 720385371FB0F9DA00FDEDE6 /* Build configuration list for PBXNativeTarget "SBSAnimoji" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 720385381FB0F9DA00FDEDE6 /* Debug */, - 720385391FB0F9DA00FDEDE6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 720385191FB0F9D900FDEDE6 /* Project object */; -} diff --git a/SBSAnimoji/Application/AppDelegate.h b/SBSAnimoji/Application/AppDelegate.h deleted file mode 100644 index d15bd89..0000000 --- a/SBSAnimoji/Application/AppDelegate.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// AppDelegate.h -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - -@end - diff --git a/SBSAnimoji/Application/AppDelegate.m b/SBSAnimoji/Application/AppDelegate.m deleted file mode 100644 index e8093fe..0000000 --- a/SBSAnimoji/Application/AppDelegate.m +++ /dev/null @@ -1,24 +0,0 @@ -// -// AppDelegate.m -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import "AppDelegate.h" -#import "MainViewController.h" - -@interface AppDelegate () -@end - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[MainViewController alloc] init]]; - [self.window makeKeyAndVisible]; - return YES; -} - -@end diff --git a/SBSAnimoji/Pages/Main/MainView.h b/SBSAnimoji/Pages/Main/MainView.h deleted file mode 100644 index 911bac1..0000000 --- a/SBSAnimoji/Pages/Main/MainView.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// MainView.h -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import -#import "SBSPuppetView.h" - -@class AVTPuppetView; - -@interface MainView : UIView -@property (nonatomic, readonly) SBSPuppetView *puppetView; -@property (nonatomic, readonly) UICollectionView *thumbnailsCollectionView; -@property (nonatomic, readonly) UIButton *recordButton; -@property (nonatomic, readonly) UIButton *shareButton; -@property (nonatomic, readonly) UIButton *deleteButton; -@property (nonatomic, readonly) UIButton *previewButton; -@property (nonatomic, readonly) UIActivityIndicatorView *activityIndicatorView; -@property (nonatomic, readonly) UILabel *durationLabel; -@end diff --git a/SBSAnimoji/Pages/Main/MainView.m b/SBSAnimoji/Pages/Main/MainView.m deleted file mode 100644 index 0797aa3..0000000 --- a/SBSAnimoji/Pages/Main/MainView.m +++ /dev/null @@ -1,139 +0,0 @@ -// -// MainView.m -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import "MainView.h" -#import "AVTPuppetView.h" - -@interface MainView () -@property (nonatomic, strong) SBSPuppetView *puppetView; -@property (nonatomic, strong) UICollectionView *thumbnailsCollectionView; -@property (nonatomic, strong) UIButton *recordButton; -@property (nonatomic, strong) UIButton *shareButton; -@property (nonatomic, strong) UIButton *deleteButton; -@property (nonatomic, strong) UIButton *previewButton; -@property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView; -@property (nonatomic, strong) UILabel *durationLabel; -@property (nonatomic, strong) UIView *puppetViewSeparatorView; -@end - -@implementation MainView - -- (instancetype)init { - if (self = [super init]) { - [self setupView]; - [self setupLayout]; - } - return self; -} - -- (void)setupView { - self.backgroundColor = [UIColor whiteColor]; - - self.puppetView = [[SBSPuppetView alloc] init]; - self.puppetView.translatesAutoresizingMaskIntoConstraints = NO; - [self addSubview:self.puppetView]; - - self.puppetViewSeparatorView = [[UIView alloc] init]; - self.puppetViewSeparatorView.translatesAutoresizingMaskIntoConstraints = NO; - self.puppetViewSeparatorView.backgroundColor = [UIColor colorWithRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:1.0]; - [self addSubview:self.puppetViewSeparatorView]; - - UICollectionViewFlowLayout *collectionViewLayout = [[UICollectionViewFlowLayout alloc] init]; - collectionViewLayout.scrollDirection = UICollectionViewScrollDirectionVertical; - collectionViewLayout.minimumInteritemSpacing = 14; - collectionViewLayout.minimumLineSpacing = 10; - self.thumbnailsCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:collectionViewLayout]; - self.thumbnailsCollectionView.translatesAutoresizingMaskIntoConstraints = NO; - self.thumbnailsCollectionView.backgroundColor = [UIColor whiteColor]; - self.thumbnailsCollectionView.contentInset = UIEdgeInsetsMake(15, 7, 15, 7); - self.thumbnailsCollectionView.showsHorizontalScrollIndicator = NO; - [self addSubview:self.thumbnailsCollectionView]; - - self.durationLabel = [[UILabel alloc] init]; - self.durationLabel.translatesAutoresizingMaskIntoConstraints = NO; - self.durationLabel.textAlignment = NSTextAlignmentRight; - self.durationLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; - self.durationLabel.hidden = YES; - [self addSubview:self.durationLabel]; - - self.deleteButton = [UIButton buttonWithType:UIButtonTypeSystem]; - self.deleteButton.translatesAutoresizingMaskIntoConstraints = NO; - self.deleteButton.hidden = YES; - [self.deleteButton setImage:[UIImage imageNamed:@"delete"] forState:UIControlStateNormal]; - [self addSubview:self.deleteButton]; - - self.previewButton = [UIButton buttonWithType:UIButtonTypeSystem]; - self.previewButton.translatesAutoresizingMaskIntoConstraints = NO; - self.previewButton.hidden = YES; - [self.previewButton setImage:[UIImage imageNamed:@"start-previewing"] forState:UIControlStateNormal]; - [self addSubview:self.previewButton]; - - self.recordButton = [UIButton buttonWithType:UIButtonTypeSystem]; - self.recordButton.translatesAutoresizingMaskIntoConstraints = NO; - [self.recordButton setImage:[UIImage imageNamed:@"start-recording"] forState:UIControlStateNormal]; - [self addSubview:self.recordButton]; - - self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem]; - self.shareButton.translatesAutoresizingMaskIntoConstraints = NO; - self.shareButton.hidden = YES; - [self.shareButton setImage:[UIImage imageNamed:@"share"] forState:UIControlStateNormal]; - [self addSubview:self.shareButton]; - - self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - self.activityIndicatorView.translatesAutoresizingMaskIntoConstraints = NO; - self.activityIndicatorView.hidesWhenStopped = YES; - [self addSubview:self.activityIndicatorView]; -} - -- (void)setupLayout { - [self.puppetView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor].active = YES; - [self.puppetView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor].active = YES; - [self.puppetView.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES; - [self.puppetView.heightAnchor constraintEqualToConstant:335].active = YES; - - [self.puppetViewSeparatorView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor].active = YES; - [self.puppetViewSeparatorView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor].active = YES; - [self.puppetViewSeparatorView.topAnchor constraintEqualToAnchor:self.puppetView.bottomAnchor].active = YES; - [self.puppetViewSeparatorView.heightAnchor constraintEqualToConstant:2].active = YES; - - [self.thumbnailsCollectionView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor].active = YES; - [self.thumbnailsCollectionView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor].active = YES; - [self.thumbnailsCollectionView.topAnchor constraintEqualToAnchor:self.puppetViewSeparatorView.bottomAnchor].active = YES; - [self.thumbnailsCollectionView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES; - - [self.durationLabel.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant: -20].active = YES; - [self.durationLabel.topAnchor constraintEqualToAnchor:self.puppetView.topAnchor constant: 15].active = YES; - - [self.recordButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant: -20].active = YES; - [self.recordButton.bottomAnchor constraintEqualToAnchor:self.puppetView.bottomAnchor constant: -20].active = YES; - - [self.shareButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant: -20].active = YES; - [self.shareButton.bottomAnchor constraintEqualToAnchor:self.puppetView.bottomAnchor constant: -20].active = YES; - - [self.deleteButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant: -20].active = YES; - [self.deleteButton.topAnchor constraintEqualToAnchor:self.puppetView.topAnchor constant: 15].active = YES; - - [self.previewButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant: -20].active = YES; - [self.previewButton.topAnchor constraintEqualToAnchor:self.deleteButton.bottomAnchor constant: 15].active = YES; - - [self.activityIndicatorView.centerXAnchor constraintEqualToAnchor:self.shareButton.centerXAnchor].active = YES; - [self.activityIndicatorView.centerYAnchor constraintEqualToAnchor:self.shareButton.centerYAnchor].active = YES; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - CGFloat itemsPerRow = 4; - UICollectionView *collectionView = self.thumbnailsCollectionView; - UIEdgeInsets contentInset = self.thumbnailsCollectionView.contentInset; - UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)collectionView.collectionViewLayout; - CGFloat availableWidth = self.bounds.size.width - contentInset.left - contentInset.right - (itemsPerRow - 1) * flowLayout.minimumInteritemSpacing; - CGFloat itemLength = floor(availableWidth / itemsPerRow); - flowLayout.itemSize = CGSizeMake(itemLength, itemLength); -} - -@end diff --git a/SBSAnimoji/Pages/Main/MainViewController.h b/SBSAnimoji/Pages/Main/MainViewController.h deleted file mode 100644 index b019996..0000000 --- a/SBSAnimoji/Pages/Main/MainViewController.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// MainViewController.h -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import - -@interface MainViewController : UIViewController - -@end - diff --git a/SBSAnimoji/Pages/Main/MainViewController.m b/SBSAnimoji/Pages/Main/MainViewController.m deleted file mode 100644 index f29d919..0000000 --- a/SBSAnimoji/Pages/Main/MainViewController.m +++ /dev/null @@ -1,240 +0,0 @@ -// -// MainViewController.m -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import "MainViewController.h" -#import "MainView.h" -#import "AVTPuppet.h" -#import "AVTPuppetView.h" -#import "PuppetThumbnailCollectionViewCell.h" - -@interface MainViewController () -@property (nonatomic, readonly) MainView *contentView; -@property (nonatomic, strong) NSTimer *durationTimer; -@property (nonatomic, strong) NSArray *puppetNames; -@property (nonatomic, assign) BOOL hasExportedMovie; -@property (nonatomic, assign, getter=isExporting) BOOL exporting; -@end - -@implementation MainViewController - -// Pragma mark: - Lifecycle - -- (instancetype)init { - if (self = [super init]) { - self.title = NSLocalizedString(@"MAIN_TITLE", @""); - self.puppetNames = [AVTPuppet puppetNames]; - } - return self; -} - -- (void)dealloc { - [self.contentView.puppetView removeObserver:self forKeyPath:@"recording"]; -} - -- (MainView *)contentView { - return (MainView *)self.view; -} - -- (void)loadView { - self.view = [[MainView alloc] init]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - self.contentView.puppetView.sbsDelegate = self; - self.contentView.thumbnailsCollectionView.dataSource = self; - self.contentView.thumbnailsCollectionView.delegate = self; - [self.contentView.thumbnailsCollectionView registerClass:[PuppetThumbnailCollectionViewCell class] forCellWithReuseIdentifier:@"thumbnail"]; - [self.contentView.recordButton addTarget:self action:@selector(toggleRecording) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView.deleteButton addTarget:self action:@selector(removeRecording) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView.previewButton addTarget:self action:@selector(startPreview) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView.shareButton addTarget:self action:@selector(share) forControlEvents:UIControlEventTouchUpInside]; - [self showPuppetNamed:self.puppetNames[0]]; - [self.contentView.thumbnailsCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone]; -} - -// Pragma mark: - Private - -- (void)share { - __weak typeof(self) weakSelf = self; - [self exportMovieIfNecessary:^(NSURL *movieURL) { - if (movieURL == nil) { - return; - } - NSArray *activityItems = @[ movieURL ]; - UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil]; - [weakSelf presentViewController:activityViewController animated:true completion:nil]; - }]; -} - -- (void)exportMovieIfNecessary:(void(^)(NSURL *))completion { - NSURL *movieURL = [self movieURL]; - if (self.hasExportedMovie) { - completion(movieURL); - } else { - self.exporting = YES; - [self.contentView.activityIndicatorView startAnimating]; - self.contentView.deleteButton.enabled = NO; - self.contentView.shareButton.hidden = YES; - __weak typeof(self) weakSelf = self; - [self.contentView.puppetView exportMovieToURL:movieURL options:nil completionHandler:^{ - weakSelf.hasExportedMovie = YES; - [weakSelf.contentView.activityIndicatorView stopAnimating]; - weakSelf.contentView.deleteButton.enabled = YES; - weakSelf.contentView.shareButton.hidden = NO; - weakSelf.exporting = NO; - completion(movieURL); - }]; - } -} - -- (void)removeRecording { - self.hasExportedMovie = NO; - [self removeExistingMovieFile]; - [self.contentView.puppetView stopRecording]; - [self.contentView.puppetView stopPreviewing]; - self.contentView.recordButton.hidden = NO; - self.contentView.deleteButton.hidden = YES; - self.contentView.previewButton.hidden = YES; - self.contentView.shareButton.hidden = YES; -} - -- (void)toggleRecording { - if (self.contentView.puppetView.isRecording) { - [self.contentView.puppetView stopRecording]; - } else { - [self.contentView.puppetView startRecording]; - } -} - -- (void)durationTimerTriggered { - int recordingDuration = ceil(self.contentView.puppetView.recordingDuration); - int minutes = floor(recordingDuration / 60); - int seconds = recordingDuration % 60; - NSString *strMinutes; - NSString *strSeconds; - if (minutes < 10) { - strMinutes = [NSString stringWithFormat:@"0%d", minutes]; - } else { - strMinutes = [NSString stringWithFormat:@"%d", minutes]; - } - if (seconds < 10) { - strSeconds = [NSString stringWithFormat:@"0%d", seconds]; - } else { - strSeconds = [NSString stringWithFormat:@"%d", seconds]; - } - self.contentView.durationLabel.text = [NSString stringWithFormat:@"%@:%@", strMinutes, strSeconds]; -} - -- (void)removeExistingMovieFile { - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSURL *movieURL = [self movieURL]; - if ([fileManager fileExistsAtPath:movieURL.path]) { - NSError *error = nil; - [fileManager removeItemAtURL:movieURL error:&error]; - if (error) { - NSLog(@"%@", error); - } - } -} - -- (void)startPreview { - [self.contentView.previewButton removeTarget:self action:@selector(startPreview) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView.previewButton addTarget:self action:@selector(stopPreview) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView.previewButton setImage:[UIImage imageNamed:@"stop-previewing"] forState:UIControlStateNormal]; - [self.contentView.puppetView stopPreviewing]; - [self.contentView.puppetView startPreviewing]; -} - -- (void)stopPreview { - [self.contentView.previewButton removeTarget:self action:@selector(stopPreview) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView.previewButton addTarget:self action:@selector(startPreview) forControlEvents:UIControlEventTouchUpInside]; - [self.contentView.previewButton setImage:[UIImage imageNamed:@"start-previewing"] forState:UIControlStateNormal]; - [self.contentView.puppetView stopPreviewing]; -} - -- (NSURL *)movieURL { - NSURL *documentURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; - return [documentURL URLByAppendingPathComponent:@"animoji.mov"]; -} - -- (void)showPuppetNamed:(NSString *)puppetName { - AVTPuppet *puppet = [AVTPuppet puppetNamed:puppetName options:nil]; - [self.contentView.puppetView setAvatarInstance:(AVTAvatarInstance *)puppet]; -} - -// Pragma mark: - SBSPuppetViewDelegate - -- (void)puppetViewDidFinishPlaying:(SBSPuppetView *)puppetView { - if (!puppetView.isRecording) { - [self stopPreview]; - } -} - -- (void)puppetViewDidStartRecording:(SBSPuppetView *)puppetView { - self.hasExportedMovie = NO; - [self removeExistingMovieFile]; - [self.contentView.recordButton setImage:[UIImage imageNamed:@"stop-recording"] forState:UIControlStateNormal]; - self.contentView.durationLabel.text = @"00:00"; - self.contentView.durationLabel.hidden = NO; - self.durationTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(durationTimerTriggered) userInfo:nil repeats:YES]; - self.contentView.thumbnailsCollectionView.userInteractionEnabled = NO; - [UIView animateWithDuration:0.3 animations:^{ - self.contentView.thumbnailsCollectionView.alpha = 0.5; - }]; -} - -- (void)puppetViewDidStopRecording:(SBSPuppetView *)puppetView { - if (self.isExporting) { - // The callback is called when we start exporting. - // It's not intuitive but internally, AVTPuppetView is - // calling stopRecording which then triggers this callback. - return; - } - [self.durationTimer invalidate]; - self.durationTimer = nil; - self.contentView.recordButton.hidden = YES; - self.contentView.shareButton.hidden = NO; - self.contentView.deleteButton.hidden = NO; - self.contentView.previewButton.hidden = NO; - self.contentView.durationLabel.hidden = YES; - [self.contentView.recordButton setImage:[UIImage imageNamed:@"start-recording"] forState:UIControlStateNormal]; - self.contentView.thumbnailsCollectionView.userInteractionEnabled = YES; - [UIView animateWithDuration:0.3 animations:^{ - self.contentView.thumbnailsCollectionView.alpha = 1; - }]; - [self startPreview]; -} - -// Pragma mark: - UICollectionViewDataSource - -- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { - return 1; -} - -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { - return [self.puppetNames count]; -} - -- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath { - PuppetThumbnailCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"thumbnail" forIndexPath:indexPath]; - NSString *puppetName = self.puppetNames[indexPath.item]; - cell.thumbnailImageView.image = [AVTPuppet thumbnailForPuppetNamed:puppetName options:nil]; - return cell; -} - -// Pragma mark: - UICollectionViewDelegate - -- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - NSString *puppetName = self.puppetNames[indexPath.item]; - if (puppetName != nil) { - [self showPuppetNamed:puppetName]; - } -} - -@end diff --git a/SBSAnimoji/Pages/Main/PuppetThumbnailCollectionViewCell.h b/SBSAnimoji/Pages/Main/PuppetThumbnailCollectionViewCell.h deleted file mode 100644 index 779829b..0000000 --- a/SBSAnimoji/Pages/Main/PuppetThumbnailCollectionViewCell.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// PuppetThumbnailCollectionViewCell.h -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import - -@interface PuppetThumbnailCollectionViewCell : UICollectionViewCell -@property (nonatomic, readonly) UIImageView *thumbnailImageView; -@end diff --git a/SBSAnimoji/Pages/Main/PuppetThumbnailCollectionViewCell.m b/SBSAnimoji/Pages/Main/PuppetThumbnailCollectionViewCell.m deleted file mode 100644 index 1da36c9..0000000 --- a/SBSAnimoji/Pages/Main/PuppetThumbnailCollectionViewCell.m +++ /dev/null @@ -1,52 +0,0 @@ -// -// PuppetThumbnailCollectionViewCell.m -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import "PuppetThumbnailCollectionViewCell.h" - -@interface PuppetThumbnailCollectionViewCell () -@property (nonatomic, strong) UIImageView *thumbnailImageView; -@property (nonatomic, strong) UIImageView *selectionImageView; -@end - -@implementation PuppetThumbnailCollectionViewCell - -- (instancetype)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:CGRectZero]) { - [self setupView]; - } - return self; -} - -- (void)setupView { - self.backgroundColor = [UIColor whiteColor]; - - self.thumbnailImageView = [[UIImageView alloc] init]; - self.thumbnailImageView.translatesAutoresizingMaskIntoConstraints = NO; - self.thumbnailImageView.contentMode = UIViewContentModeScaleAspectFit; - [self.contentView addSubview:self.thumbnailImageView]; - - self.selectionImageView = [[UIImageView alloc] init]; - self.selectionImageView.image = [UIImage imageNamed:@"selection"]; - self.selectionImageView.translatesAutoresizingMaskIntoConstraints = NO; - self.selectionImageView.hidden = YES; - [self.contentView addSubview:self.selectionImageView]; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - UIEdgeInsets thumbnailMargins = UIEdgeInsetsMake(7, 7, 7, 7); - self.thumbnailImageView.frame = UIEdgeInsetsInsetRect(self.contentView.bounds, thumbnailMargins); - self.selectionImageView.frame = self.contentView.bounds; -} - -- (void)setSelected:(BOOL)selected { - [super setSelected:selected]; - self.selectionImageView.hidden = !selected; -} - -@end diff --git a/SBSAnimoji/Pages/Main/SBSPuppetView.h b/SBSAnimoji/Pages/Main/SBSPuppetView.h deleted file mode 100644 index 828963c..0000000 --- a/SBSAnimoji/Pages/Main/SBSPuppetView.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// SBSPuppetView.h -// SBSAnimoji -// -// Created by Simon Støvring on 06/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import "AVTPuppetView.h" - -@class SBSPuppetView; - -@protocol SBSPuppetViewDelegate -- (void)puppetViewDidFinishPlaying:(SBSPuppetView *)puppetView; -- (void)puppetViewDidStartRecording:(SBSPuppetView *)puppetView; -- (void)puppetViewDidStopRecording:(SBSPuppetView *)puppetView; -@end - -@interface SBSPuppetView : AVTPuppetView -@property (nonatomic, weak) id sbsDelegate; -@end diff --git a/SBSAnimoji/Pages/Main/SBSPuppetView.m b/SBSAnimoji/Pages/Main/SBSPuppetView.m deleted file mode 100644 index 2ff4533..0000000 --- a/SBSAnimoji/Pages/Main/SBSPuppetView.m +++ /dev/null @@ -1,64 +0,0 @@ -// -// SBSPuppetView.m -// SBSAnimoji -// -// Created by Simon Støvring on 06/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import "SBSPuppetView.h" -#import - -#define MAX_RECORDING_DURATION 60 // Seconds - -@implementation SBSPuppetView - -- (void)audioPlayerItemDidReachEnd:(id)arg1 { - [super audioPlayerItemDidReachEnd:arg1]; - if ([self.sbsDelegate respondsToSelector:@selector(puppetViewDidFinishPlaying:)]) { - [self.sbsDelegate puppetViewDidFinishPlaying:self]; - } -} - -- (void)startRecording { - [super startRecording]; - - int duration = MAX_RECORDING_DURATION * 60; - - NSMutableData *timesBuffer = [NSMutableData dataWithCapacity: duration * 8]; - NSMutableData *blendShapeBuffer = [NSMutableData dataWithCapacity: duration * 204]; - NSMutableData *transformData = [NSMutableData dataWithCapacity: duration * 64]; - - [self setValue:[NSNumber numberWithInt:duration] forKey:@"_recordingCapacity"]; - [self setValue:timesBuffer forKey:@"_rawTimesData"]; - [self setValue:blendShapeBuffer forKey:@"_rawBlendShapesData"]; - [self setValue:transformData forKey:@"_rawTransformsData"]; - - { - Ivar ivar = class_getInstanceVariable([AVTPuppetView class], "_rawTimes"); - object_setIvar(self, ivar, [timesBuffer mutableBytes]); - } - - { - Ivar ivar = class_getInstanceVariable([AVTPuppetView class], "_rawBlendShapes"); - object_setIvar(self, ivar, [blendShapeBuffer mutableBytes]); - } - - { - Ivar ivar = class_getInstanceVariable([AVTPuppetView class], "_rawTransforms"); - object_setIvar(self, ivar, [transformData mutableBytes]); - } - - if ([self.sbsDelegate respondsToSelector:@selector(puppetViewDidStartRecording:)]) { - [self.sbsDelegate puppetViewDidStartRecording:self]; - } -} - -- (void)stopRecording { - [super stopRecording]; - if ([self.sbsDelegate respondsToSelector:@selector(puppetViewDidStopRecording:)]) { - [self.sbsDelegate puppetViewDidStopRecording:self]; - } -} - -@end diff --git a/SBSAnimoji/Supporting files/Localizable.strings b/SBSAnimoji/Supporting files/Localizable.strings deleted file mode 100644 index 751fe87..0000000 --- a/SBSAnimoji/Supporting files/Localizable.strings +++ /dev/null @@ -1,10 +0,0 @@ -/* - Localizable.strings - SBSAnimoji - - Created by Simon Støvring on 05/11/2017. - Copyright © 2017 SimonBS. All rights reserved. -*/ - -"MAIN_TITLE" = "SBSAnimoji"; - diff --git a/SBSAnimoji/Supporting files/main.m b/SBSAnimoji/Supporting files/main.m deleted file mode 100644 index 9dbd51c..0000000 --- a/SBSAnimoji/Supporting files/main.m +++ /dev/null @@ -1,16 +0,0 @@ -// -// main.m -// SBSAnimoji -// -// Created by Simon Støvring on 05/11/2017. -// Copyright © 2017 SimonBS. All rights reserved. -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/SBSAnimoji/User interface/Base.lproj/LaunchScreen.storyboard b/SBSAnimoji/User interface/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 95b057b..0000000 --- a/SBSAnimoji/User interface/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/newScreenshot.jpg b/newScreenshot.jpg new file mode 100644 index 0000000..5c06971 Binary files /dev/null and b/newScreenshot.jpg differ diff --git a/screenshot.png b/screenshot.png deleted file mode 100644 index 245d91e..0000000 Binary files a/screenshot.png and /dev/null differ