1
Fork 0

Add timelapse viewing functionality

This commit is contained in:
Joshua Goins 2021-05-09 21:44:04 -04:00 committed by redstrate
parent 51575e1e5a
commit 7f95910528
6 changed files with 118 additions and 5 deletions

View file

@ -14,6 +14,7 @@
030F700E2415C6B500A43F01 /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030F700D2415C6B500A43F01 /* PreviewViewController.swift */; };
030F70112415C6B500A43F01 /* PreviewViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 030F700F2415C6B500A43F01 /* PreviewViewController.xib */; };
030F70162415C6B500A43F01 /* QuickLook.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 030F70082415C6B500A43F01 /* QuickLook.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
033F94F92648B8E200099FB7 /* TimelapseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 033F94F82648B8E200099FB7 /* TimelapseViewController.swift */; };
036AFBB8241687680075400A /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 036AFBB7241687680075400A /* ZIPFoundation */; };
036AFBBA24168C030075400A /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036AFBB924168C030075400A /* ViewController.swift */; };
036AFBE32417F0A00075400A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 036AFBE12417F0A00075400A /* Main.storyboard */; };
@ -87,6 +88,7 @@
030F70102415C6B500A43F01 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PreviewViewController.xib; sourceTree = "<group>"; };
030F70122415C6B500A43F01 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
030F70132415C6B500A43F01 /* Quicklook.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Quicklook.entitlements; sourceTree = "<group>"; };
033F94F82648B8E200099FB7 /* TimelapseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelapseViewController.swift; sourceTree = "<group>"; };
036AFBB924168C030075400A /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
036AFBE22417F0A00075400A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
036AFC0B241800350075400A /* Thumbnail.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Thumbnail.appex; sourceTree = BUILT_PRODUCTS_DIR; };
@ -181,6 +183,7 @@
037B4041241821D200392452 /* InfoViewController.swift */,
03CB382324191F620078B3E5 /* cbridge.c */,
03CB382224191F610078B3E5 /* ProcreateViewer-Bridging-Header.h */,
033F94F82648B8E200099FB7 /* TimelapseViewController.swift */,
);
path = ProcreateViewer;
sourceTree = "<group>";
@ -413,6 +416,7 @@
buildActionMask = 2147483647;
files = (
03CB3840241A5AED0078B3E5 /* Shared.swift in Sources */,
033F94F92648B8E200099FB7 /* TimelapseViewController.swift in Sources */,
036AFBBA24168C030075400A /* ViewController.swift in Sources */,
03CB382424191F620078B3E5 /* cbridge.c in Sources */,
030F6FF42415C5E300A43F01 /* Document.swift in Sources */,

View file

@ -6,8 +6,13 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations {
NSApplication.shared.keyWindow?.contentViewController?.performSegue(withIdentifier: "showInfo", sender: self)
}
@IBAction func showTimelapseAction(_ sender: Any) {
NSApplication.shared.keyWindow?.contentViewController?.performSegue(withIdentifier: "showTimelapse", sender: self)
}
func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool {
if(item.tag == 67) {
// Show timelapse and show info buttons
if(item.tag == 67 || item.tag == 68) {
return NSApplication.shared.keyWindow != nil
}

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.AVKitIBPlugin" version="17156"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17156"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -96,6 +98,12 @@
<action selector="showInfoAction:" target="Voe-Tx-rLC" id="3A0-GP-3ZY"/>
</connections>
</menuItem>
<menuItem title="Show Timelapse" tag="68" id="nSM-YZ-MTX">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showTimelapseAction:" target="Voe-Tx-rLC" id="kfN-ET-oSo"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
@ -184,7 +192,7 @@ Dk51bWJlciBvZiBMYXllcnM6A
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2oe-to-Rcz">
<rect key="frame" x="407" y="13" width="59" height="32"/>
<rect key="frame" x="414" y="14" width="53" height="32"/>
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="BnS-yc-3ej">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -218,6 +226,58 @@ DQ
<point key="canvasLocation" x="786" y="298.5"/>
</scene>
<!--Window Controller-->
<scene sceneID="IIQ-mF-530">
<objects>
<windowController id="qzy-T7-vHd" sceneMemberID="viewController">
<window key="window" title="Timelapse" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="px5-oy-UC5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="268" y="330" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1792" height="1095"/>
<view key="contentView" id="VVC-fD-7H3">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<connections>
<outlet property="delegate" destination="qzy-T7-vHd" id="pBE-dh-gi9"/>
</connections>
</window>
<connections>
<segue destination="2g9-GV-hNg" kind="relationship" relationship="window.shadowedContentViewController" id="Bfa-oy-KMO"/>
</connections>
</windowController>
<customObject id="qKM-fu-CcY" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="716" y="847"/>
</scene>
<!--Timelapse View Controller-->
<scene sceneID="6lP-oO-4ie">
<objects>
<viewController id="2g9-GV-hNg" customClass="TimelapseViewController" customModule="Procreate_Viewer" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="n7g-Sv-vdB">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<avPlayerView controlsStyle="minimal" videoGravity="resizeAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="zOe-qf-LSc">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
</avPlayerView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="zOe-qf-LSc" secondAttribute="trailing" id="5e2-Uh-miL"/>
<constraint firstAttribute="bottom" secondItem="zOe-qf-LSc" secondAttribute="bottom" id="Kfx-dj-9x8"/>
<constraint firstItem="zOe-qf-LSc" firstAttribute="top" secondItem="n7g-Sv-vdB" secondAttribute="top" id="rwV-Dr-EPg"/>
<constraint firstItem="zOe-qf-LSc" firstAttribute="leading" secondItem="n7g-Sv-vdB" secondAttribute="leading" id="uY5-WX-NhA"/>
</constraints>
</view>
<connections>
<outlet property="playerView" destination="zOe-qf-LSc" id="Iy7-O4-v4P"/>
</connections>
</viewController>
<customObject id="LO0-g9-QLL" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1339" y="769"/>
</scene>
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController storyboardIdentifier="Document Window Controller" id="jGA-0Y-lOj" sceneMemberID="viewController">
@ -250,6 +310,9 @@ DQ
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="chN-IE-x52"/>
<connections>
<segue destination="qzy-T7-vHd" kind="show" identifier="showTimelapse" id="x99-kP-axt"/>
</connections>
</imageView>
</subviews>
</view>
@ -260,7 +323,7 @@ DQ
</viewController>
<customObject id="2Tp-Fl-jBw" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="59" y="761"/>
<point key="canvasLocation" x="132" y="725"/>
</scene>
</scenes>
</document>

View file

@ -0,0 +1,37 @@
import Foundation
import Cocoa
import AVKit
import AVFoundation
import ZIPFoundation
class TimelapseViewController: NSViewController {
var document: Document?
@IBOutlet weak var playerView: AVPlayerView!
override func viewWillAppear() {
super.viewDidAppear()
guard let archive = Archive(data: (document?.data)!, accessMode: Archive.AccessMode.read) else {
return
}
let directory = NSTemporaryDirectory()
var entries: [AVPlayerItem] = []
for entry in archive.makeIterator() {
if entry.path.contains(VideoPath) {
let fileName = NSUUID().uuidString + ".mp4"
// This returns a URL? even though it is an NSURL class method
let fullURL = NSURL.fileURL(withPathComponents: [directory, fileName])!
try? archive.extract(entry, to: fullURL)
entries.append(AVPlayerItem(url: fullURL))
}
}
playerView?.player = AVQueuePlayer(items: entries)
}
}

View file

@ -14,6 +14,8 @@ class ViewController: NSViewController {
if(segue.identifier == "showInfo") {
// TODO: there HAS to be a better way to pass the Document class along...
(segue.destinationController as! InfoViewController).document = self.view.window?.windowController?.document as? Document
} else if(segue.identifier == "showTimelapse") {
((segue.destinationController as! NSWindowController).contentViewController as! TimelapseViewController).document = self.view.window?.windowController?.document as? Document
}
}
}

View file

@ -6,6 +6,8 @@ let NSKeyedArchiveVersion = 100000
let ThumbnailPath = "QuickLook/Thumbnail.png"
let DocumentArchivePath = "Document.archive"
let VideoPath = "video/segments/"
let DocumentClassName = "SilicaDocument"
let TrackedTimeKey = "SilicaDocumentTrackedTimeKey"
let LayersKey = "layers"