Skip to content

Commit

Permalink
Release 0.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
runner authored and runner committed Jan 26, 2024
1 parent 0c1e228 commit 31615d7
Show file tree
Hide file tree
Showing 33 changed files with 1,229 additions and 12 deletions.
24 changes: 12 additions & 12 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,33 +32,33 @@ let package = Package(

.binaryTarget(
name: "ObjcExceptionBridging",
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/143945292.zip",
checksum: "87a40cd9a405efc0d0bc9f1546797b0ceed16d7c3b77c1e29329199d0eb93d8a"
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/147881910.zip",
checksum: "3ea6db856a16ad0c9ed07fb317972cbe60a734bda04a6ed08f230b335801a292"
),
.binaryTarget(
name: "_HVAVCamera",
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/143945297.zip",
checksum: "226e0686bc528d189e98de23738253cd076c0138dbfc45f068a487291bb842ca"
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/147881912.zip",
checksum: "255dad91d994e6378b15c89c9be0ed50c3ded14012c6e9bb267104407d56f038"
),
.binaryTarget(
name: "_HVCameraExterior",
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/143945311.zip",
checksum: "0aa0304ec230d192a1363d4f397a79a0cffac0a3035368e4285d5c22d603d089"
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/147881918.zip",
checksum: "ab95a26c936b94281c9dbeca1563e517dd9bdfe4e8f147fff3a82440accf18a0"
),
.binaryTarget(
name: "_HVCore",
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/143945328.zip",
checksum: "78b4b271c8952c8c5ae8b465d64b4495275b5d0e82645adc4ce142e76f7787e4"
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/147881921.zip",
checksum: "6bf6d00ab5cc10dc5cc7d624f9e0a2d83d357a0c37a255a9f3a74a26f2047624"
),
.binaryTarget(
name: "_HVCVPixelBufferHelper",
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/143945310.zip",
checksum: "db5ae82b1edd3d961b066004688b88d5259b9d44053ad7e8e0df14fb0733b527"
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/147881915.zip",
checksum: "2e1733fb2a2fa1f19b52640c6b879970dc0851f3789fb33baa05ae0b8110d938"
),
.binaryTarget(
name: "_XCGLogger",
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/143945331.zip",
checksum: "5fd1d60ba3df614319e72f56723bc3ddb90539aca5868277994669cf783c2021"
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/147881923.zip",
checksum: "de60603daf0f6223325c1624460fdcdc079b0b9f60d71a96802ba69191f3b402"
),
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ``_HVCameraExterior``

The HOVER capture experience

@Metadata {
@PageImage(
purpose: icon,
source: "hvcamera-icon",
alt: "An icon representing the HVCamera framework.")
@PageColor(blue)
}

## Overview

The HOVER Capture SDK provides on-device functionality to facilitate HOVER 3D model creation. Specifically, it provides:

- Sensor interaction for data acquisition
- On-device data processing and transformation
- Visual elements and user guidance to guide data acquisition and improve captured data
- On-device local persistence
- Robust data uploads to the HOVER backend

Once the data has been captured and uploaded from the SDK, the HOVER backend will begin the 3D model processing.

## Essentials

@Links(visualStyle: compactGrid) {
- <doc:GettingStarted>
- <doc:BasicSDK>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# GettingStarted

Initialize the SDK, create a capture session and begin the capture flow UI.

@Metadata {
@PageImage(
purpose: card,
source: "hvcamera-icon",
alt: "A stylized house.")
@PageImage(
purpose: icon,
source: "hover-logo",
alt: "An icon representing the HOVER logo framework.")
@PageColor(blue)
}

## Overview

The SDK is akin to an embedded app within a host app. It will run and attach its own `View`s to the `ViewController`, and run as a self-contained black box until the capture session is complete.
This article will walk through the steps required to use the SDK within a host app.

### Initializing the SDK

The SDK should be initialized as early as possible in the app lifecycle. This is because the SDK does some background processing to set up required structures and upload any remaining captured data from past jobs that have yet to complete.
As such, the SDK should (ideally) be initialized in host application’s `applicationDidFinishLaunching` method, so that the SDK can continue uploading any files that remain to be uploaded. This helps expedite 3D model generation, as we need all the captured images and metadata to begin the 3D reconstruction process.

```swift
import HVCamera
class AppDelegate: UIResponder, UIApplicationDelegate {
// ...

@MainActor
private func applicationDidFinishLaunching(_ notification: Notification) {
HVCameraExterior.sharedInstance.initialize()
}
}
```

While running this in `applicationDidFinishLaunching` would be ideal, at a minimum it should be run at some point prior to starting a capture session.

### Creating a Capture Session

The host app can launch the SDK in any way it sees fit, as long as there is an active `ViewController` running somewhere in the app. Here is a minimal example of launching the SDK capture flow on a button click using `SwiftUI`:

```swift
import HVCamera
import SwiftUI

struct FooView: View {
let jobInfo: CaptureJobInformation
let sessionSettings: HVCameraSettings

// ... populate settings, etc.

var body: some View {
Button("Start Capture") {
let captureTask = Task {
do {
try await HVCameraExterior.sharedInstance.startCaptureSession(settings: sessionSettings, info: jobInfo)
try await HVCameraExterior.sharedInstance.startCaptureFlow()
} catch let error as HVSessionError {
// TODO: handle the known errors here
print("Known capture flow error: \(error.localizedDescription)")
} catch {
// TODO: handle unknown errors, who knows what to do
print("Unknown Capture Flow Error: \(error.localizedDescription)")
}
captureSessionCompleted()
}
}
}

func captureSessionCompleted() {
// perform any next steps for post-capture session work
}
}
```

Note that the SDK executes asynchronously, and the task that calls ``startCaptureSession`` will suspend until the capture flow completes. As such, there's a very linear flow to interacting with the SDK, and once the call's `await` returns, the host app knows the SDK's capture session is complete (as seen with the `captureSessionCompleted` function above). If the capture session encountered a fatal error, it will raise the error as an exception.

#### Cancelling a Capture Session

Since we execute asynchronously within a Swift ``Task``, we also honor its cancellation functionality and stop the capture session and capture flow UI if the task is cancelled.

```swift
let captureTask = Task {
do {
try await HVCameraExterior.sharedInstance.startCaptureSession(settings: sessionSettings, info: jobInfo)
try await HVCameraExterior.sharedInstance.startCaptureFlow()
} catch let error as HVSessionError {
switch error.kind {
case .UserCancelled:
print("We've been cancelled!")
}
}
}

// You can cancel the task (and thereby, the capture flow + capture session) like this:
DispatchQueue.main.asyncAfter(deadline: .now() + 10, execute: {
captureTask.cancel()
})
```

#### Monitoring Job Status

Since the capture flow proceeds asynchronously, the host app may want to monitor the local job status as the capture proceeds. There are a few methods for obtaining Job status:

1. on-demand: The ``HVCameraExterior`` class exposes a public method ``_HVCameraExterior.getClientJobStatus(for:)``. This is an `async` method that will return what the requested `Job`'s current status as a ``JobStatus``. If the requested ``Job`` doesn't exist locally, then it will raise a ``HVJobError`` exception.
2. streaming: The ``HVCameraExterior`` class also exposes a public method ``getJobStateObservable`` that returns a `Combine` publisher for the requested `Job`. The publisher will emit ``JobStatus`` instances whenever there's a change in the `Job`'s status. Additionally, ``startCaptureSession`` will return what the current `Job`'s status is when called, so together with `getJobStateObservable` you can track the whole status history for the `Job` (n.b. the initial state won't be published for a `Job`, so to get the complete status history you need to use the initial state returned from ``_HVCameraExterior.startCaptureSession`` in conjunction with the publisher from `getJobStateObservable`). The initial Job state will generally be ``JobStatus.Created`` if newly created, or ``JobStatus.Draft`` if resuming an existing Job.

For example, adapting the previous example to monitor the `Job` status and build a complete `JobStatus` history for the capture session, you can do:

```swift
import HVCamera
import SwiftUI

struct FooView: View {
let jobInfo: CaptureJobInformation
let sessionSettings: HVCameraSettings

// if you you want monitor multiple job's statuses
@State private var jobCancellables = [JobIdentifier: AnyCancellable]()
@State private var jobStatusHistory = [JobIdentifier: [JobStatus]]()

// ... populate settings, etc.

var body: some View {
Button("Start Capture") {
let captureTask = Task {
do {
let jobState = try await HVCameraExterior.sharedInstance.startCaptureSession(settings: sessionSettings, info: jobInfo)
jobStatusHistory[jobInfo.identifier]?.append(jobStatus)
// check if we have a listener for the job already, so we don't make duplicate listeners each time the view is created
if jobCancellables[jobInfo.identifier] == nil {
let cancellable = HVCameraExterior.sharedInstance.getJobStateObservable(for: jobInfo.identifier).sink(receiveValue: { (jobState: JobStatus) in
// NOTE: you can t ake various actions here based on the status change
if case let .UploadProgress(_, uploadStatus) = jobState {
print("Job@State: \(jobState) --> File@State: \(String(describing: uploadStatus))")
} else if case let .Error(_, error) = jobState {
print("Job@State: \(jobState) --> Error: \(error)")
} else {
print("Job@State: \(jobState)")
}
jobStatusHistory[jobInfo.identifier]?.append(jobStatus)
})
jobCancellables[jobInfo.identifier] = cancellable
}
try await HVCameraExterior.sharedInstance.startCaptureFlow()
} catch let error as HVSessionError {
// TODO: handle the known errors here
print("Known capture flow error: \(error.localizedDescription)")
} catch {
// TODO: handle unknown errors, who knows what to do
print("Unknown Capture Flow Error: \(error.localizedDescription)")
}
captureSessionCompleted()
}
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import SwiftUI

struct HVTheme {
// ...
public init(
primary: Color? = nil,
onPrimary: Color? = nil,
primaryContainer: Color? = nil,
onPrimaryContainer: Color? = nil,
secondary: Color? = nil,
onSecondary: Color? = nil,
subtleElements: Color? = nil,
error: Color? = nil,
onError: Color? = nil,
surface: Color? = nil,
onSurface: Color? = nil,
textPrimary: Color? = nil,
textSecondary: Color? = nil,
textPrimaryDark: Color? = nil,
footerCTABackground: Color? = nil,
toolbarBack: Image? = nil,
toolbarClose: Image? = nil,
permissionCameraHeader: String? = nil,
permissionCameraBody: String? = nil,
permissionCameraConfirm: String? = nil,
permissionCameraDeniedButtonText: String? = nil,
permissionLocationHeader: String? = nil,
permissionLocationBody: String? = nil,
permissionLocationConfirm: String? = nil,
galleryDeleteConfirmHeader: String? = nil,
galleryDeleteConfirmBody: String? = nil,
successIcon: Image? = nil,
successMessage: String? = nil,
successNextSteps: String? = nil,
cameraCaptureBackground: Color? = nil,
toolbarBackground: Color? = nil,
toolbarHeader: Color? = nil,
toolbarIcon: Color? = nil,
textLink: Color? = nil,
illustrationMainStroke: Color? = nil,
illustrationSubStroke: Color? = nil,
gridItemBorder: Color? = nil,
gridItemBackground: Color? = nil,
gridItemBorderRadius: CGFloat? = nil,
primaryButtonBackground: HVColorStateList? = nil,
primaryButtonText: HVColorStateList? = nil,
primaryButtonShadowBackground: HVColorStateList? = nil,
buttonCornerRadius: CGFloat? = nil,
secondaryButtonBackground: HVColorStateList? = nil,
secondaryButtonText: HVColorStateList? = nil,
secondaryButtonShadowBackground: HVColorStateList? = nil,
secondaryButtonStrokeColor: HVColorStateList? = nil,
secondaryButtonStrokeWidth: CGFloat? = nil,
toolbarLogo: (() -> AnyView)? = nil
) {
// ...
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import SwiftUI

public struct HVColorStateList {
// ...
public init(active: Color? = nil, pressed: Color? = nil, inactive: Color? = nil) {
// ...
}
}

struct HVTheme {
// ...
public init(
primary: Color? = nil,
onPrimary: Color? = nil,
primaryContainer: Color? = nil,
onPrimaryContainer: Color? = nil,
secondary: Color? = nil,
onSecondary: Color? = nil,
subtleElements: Color? = nil,
error: Color? = nil,
onError: Color? = nil,
surface: Color? = nil,
onSurface: Color? = nil,
textPrimary: Color? = nil,
textSecondary: Color? = nil,
textPrimaryDark: Color? = nil,
footerCTABackground: Color? = nil,
toolbarBack: Image? = nil,
toolbarClose: Image? = nil,
permissionCameraHeader: String? = nil,
permissionCameraBody: String? = nil,
permissionCameraConfirm: String? = nil,
permissionCameraDeniedButtonText: String? = nil,
permissionLocationHeader: String? = nil,
permissionLocationBody: String? = nil,
permissionLocationConfirm: String? = nil,
galleryDeleteConfirmHeader: String? = nil,
galleryDeleteConfirmBody: String? = nil,
successIcon: Image? = nil,
successMessage: String? = nil,
successNextSteps: String? = nil,
cameraCaptureBackground: Color? = nil,
toolbarBackground: Color? = nil,
toolbarHeader: Color? = nil,
toolbarIcon: Color? = nil,
textLink: Color? = nil,
illustrationMainStroke: Color? = nil,
illustrationSubStroke: Color? = nil,
gridItemBorder: Color? = nil,
gridItemBackground: Color? = nil,
gridItemBorderRadius: CGFloat? = nil,
primaryButtonBackground: HVColorStateList? = nil,
primaryButtonText: HVColorStateList? = nil,
primaryButtonShadowBackground: HVColorStateList? = nil,
buttonCornerRadius: CGFloat? = nil,
secondaryButtonBackground: HVColorStateList? = nil,
secondaryButtonText: HVColorStateList? = nil,
secondaryButtonShadowBackground: HVColorStateList? = nil,
secondaryButtonStrokeColor: HVColorStateList? = nil,
secondaryButtonStrokeWidth: CGFloat? = nil,
toolbarLogo: (() -> AnyView)? = nil
) {
// ...
}
}
Loading

0 comments on commit 31615d7

Please sign in to comment.