diff --git a/.github/workflows/build-docc.yml b/.github/workflows/build-docc.yml new file mode 100644 index 0000000..0910408 --- /dev/null +++ b/.github/workflows/build-docc.yml @@ -0,0 +1,45 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy DocC + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: macos-13 + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v3 + - name: Build DocC + run: | + xcodebuild docbuild -scheme RealityToolkit -derivedDataPath /tmp/docbuild -destination 'generic/platform=iOS'; + $(xcrun --find docc) process-archive \ + transform-for-static-hosting /tmp/docbuild/Build/Products/Debug-iphoneos/RealityToolkit.doccarchive \ + --hosting-base-path RealityToolkit \ + --output-path docs; + echo "" > docs/index.html + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + # Upload docs directory + path: 'docs' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v1 diff --git a/Package.swift b/Package.swift index 4e57062..d24f394 100644 --- a/Package.swift +++ b/Package.swift @@ -1,11 +1,11 @@ -// swift-tools-version:5.3 +// swift-tools-version:5.5 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "RealityToolkit", - platforms: [.iOS(.v14), .macOS(.v11)], + platforms: [.iOS(.v15), .macOS(.v12)], products: [ .library(name: "RealityToolkit", targets: ["RealityToolkit"]) ], diff --git a/Sources/RealityToolkit/BoldMaterial.swift b/Sources/RealityToolkit/BoldMaterial.swift new file mode 100644 index 0000000..07b1a0f --- /dev/null +++ b/Sources/RealityToolkit/BoldMaterial.swift @@ -0,0 +1,44 @@ +// +// BoldMaterial.swift +// +// +// Created by Max Cobb on 06/05/2023. +// + +import RealityKit +#if canImport(AppKit) +import AppKit.NSColor +#elseif canImport(UIKit.UIColor) +import UIKit.UIColor +#endif + +typealias BoldMaterial = PhysicallyBasedMaterial + +extension BoldMaterial { + /// An initialiser for making a ``BoldMaterial``. BoldMaterial is essentially just a PhysicallyBasedMaterial, + /// but with some properties that make non-responsive to lighting, and the colours pop more vividly than an UnlitMaterial. + /// - Parameters: + /// - color: Color to set for the Bold material. + public init(color: Material.Color) { + self.init(color: color, texture: nil) + } + + /// An initialiser for making a ``BoldMaterial``. BoldMaterial is essentially just a PhysicallyBasedMaterial, + /// but with some properties that make non-responsive to lighting, and the colours pop more vividly than an UnlitMaterial. + /// - Parameters: + /// - texture: Texture to set for the Bold material. + public init(texture: MaterialParameters.Texture) { + self.init(color: nil, texture: texture) + } + internal init(color: Material.Color?, texture: MaterialParameters.Texture?) { + self.init() + self.baseColor = .init(tint: .black) + self.sheen = .init(tint: .black) + if let color = color { + self.emissiveColor = .init(color: color, texture: texture) + } else { + self.emissiveColor = .init(texture: texture) + } + self.emissiveIntensity = 2 + } +} diff --git a/Sources/RealityToolkit/RealityToolkit+LoadingAssets.swift b/Sources/RealityToolkit/RealityToolkit+LoadingAssets.swift index f290b59..eaea0b7 100644 --- a/Sources/RealityToolkit/RealityToolkit+LoadingAssets.swift +++ b/Sources/RealityToolkit/RealityToolkit+LoadingAssets.swift @@ -35,7 +35,6 @@ public extension RealityToolkit { internal static func loadResourceCompletion( contentsOf url: URL ) async throws -> TextureResource { - if Thread.isMainThread { return try TextureResource.load(contentsOf: url) } return try await MainActor.run { try TextureResource.load(contentsOf: url) } } } @@ -61,12 +60,11 @@ public extension RealityToolkit { static func loadEntity( contentsOf url: URL, withName resourceName: String? = nil, saveTo destination: URL? = nil, useCache: Bool = true, - using loadMethod: @escaping ((_ contentsOf: URL, _: String?) throws -> Entity) = Entity.load + using loadMethod: @escaping (@MainActor(_ contentsOf: URL, _: String?) throws -> Entity) = Entity.load ) async throws -> Entity { let localUrl = try await RealityToolkit.downloadRemoteFile( contentsOf: url, saveTo: destination, useCache: useCache ) - if Thread.isMainThread { return try loadMethod(localUrl, resourceName) } return try await MainActor.run { try loadMethod(localUrl, resourceName) } } diff --git a/Sources/RealityToolkit/RealityToolkit.swift b/Sources/RealityToolkit/RealityToolkit.swift index ede248f..249ca97 100644 --- a/Sources/RealityToolkit/RealityToolkit.swift +++ b/Sources/RealityToolkit/RealityToolkit.swift @@ -35,37 +35,32 @@ import OSLog public static func downloadRemoteFile( contentsOf url: URL, saveTo destination: URL? = nil, useCache: Bool = true ) async throws -> URL { - if !url.absoluteString.hasPrefix("http") { - RealityToolkit.RUIPrint("URL is already local. To move the file, call `FileManager.default.moveItem`") - if FileManager.default.fileExists(atPath: url.path) { return url } - RealityToolkit.RUIPrint("File at local URL does not exist.") - throw LoadRemoteError.localURLProvided - } - let filename = url.lastPathComponent - var endLocation = destination ?? FileManager.default.temporaryDirectory - if endLocation.hasDirectoryPath { - endLocation.appendPathComponent(filename) - } - if FileManager.default.fileExists(atPath: endLocation.path) { - if useCache { - return endLocation - } - do { - try FileManager.default.removeItem(atPath: endLocation.path) - } catch let err { - RealityToolkit.RUIPrint("Could not remove item: \(err)") - throw LoadRemoteError.cannotDelete - } + if !url.absoluteString.hasPrefix("http") { + RealityToolkit.RUIPrint("URL is already local. To move the file, call `FileManager.default.moveItem`") + if FileManager.default.fileExists(atPath: url.path) { return url } + RealityToolkit.RUIPrint("File at local URL does not exist.") + throw LoadRemoteError.localURLProvided + } + let filename = url.lastPathComponent + var endLocation = destination ?? FileManager.default.temporaryDirectory + if endLocation.hasDirectoryPath { + endLocation.appendPathComponent(filename) + } + if FileManager.default.fileExists(atPath: endLocation.path) { + if useCache { + return endLocation } - if #available(iOS 15.0, macOS 12.0, *) { - let (moveFrom, _) = try await URLSession.shared.download(from: url) - try FileManager.default.moveItem( - atPath: moveFrom.path, toPath: endLocation.path - ) - } else { - let data = try Data(contentsOf: url) - try data.write(to: endLocation) + do { + try FileManager.default.removeItem(atPath: endLocation.path) + } catch let err { + RealityToolkit.RUIPrint("Could not remove item: \(err)") + throw LoadRemoteError.cannotDelete } - return endLocation } + let (moveFrom, _) = try await URLSession.shared.download(from: url) + try FileManager.default.moveItem( + atPath: moveFrom.path, toPath: endLocation.path + ) + return endLocation + } } diff --git a/Tests/RealityToolkitTests/DownloadTests.swift b/Tests/RealityToolkitTests/DownloadTests.swift index 6354cd9..f9b01da 100644 --- a/Tests/RealityToolkitTests/DownloadTests.swift +++ b/Tests/RealityToolkitTests/DownloadTests.swift @@ -12,7 +12,6 @@ import RealityKit import RealityFoundation import Combine -@available(iOS 15.0, macOS 12.0, *) final class Download_Tests: XCTestCase { var downloadsFolder: URL = { @@ -31,6 +30,7 @@ final class Download_Tests: XCTestCase { return folder }() + @MainActor func testDownloadImg() async throws { let saveToParam = self.downloadsFolder.appendingPathComponent("test_image.png") let testImg = "https://www.freepnglogos.com/uploads/google-logo-png/" + @@ -69,6 +69,7 @@ final class Download_Tests: XCTestCase { XCTFail("The download should have failed") } + @MainActor func testDownloadUsdz() async throws { let testImg = "https://developer.apple.com/augmented-reality/quick-look/models/retrotv/tv_retro.usdz" let remoteFileLoaded = try await RealityToolkit.downloadRemoteFile(