-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
1,625 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// | ||
// UniBridge+.swift | ||
// | ||
// | ||
// Created by Tatsuya Tanaka on 2022/05/23. | ||
// | ||
|
||
import Foundation | ||
import VCamEntity | ||
import SwiftUI | ||
import VCamBridge | ||
|
||
extension UniState { | ||
public init(_ state: CustomState) { | ||
get = state.get | ||
set = state.set | ||
name = state.name | ||
reloadThrottle = state.reloadThrottle | ||
} | ||
|
||
public struct CustomState { | ||
public init(get: @escaping () -> Value, set: @escaping (Value) -> Void, name: String = "", reloadThrottle: Bool = false) { | ||
self.get = get | ||
self.set = set | ||
self.name = name | ||
self.reloadThrottle = reloadThrottle | ||
} | ||
|
||
public var get: () -> Value | ||
public var set: (Value) -> Void | ||
public var name = "" | ||
public var reloadThrottle = false | ||
} | ||
} | ||
|
||
extension UniState<ScreenResolution>.CustomState { | ||
public static var typedScreenResolution: Self { | ||
let rawValue = UniState<[Int32]>(.screenResolution, name: "screenResolution", as: [Int32].self) | ||
return .init { | ||
let size = rawValue.wrappedValue | ||
guard size.count == 2 else { return .init(width: 1920, height: 1280) } // an empty array after disposal | ||
return ScreenResolution(width: Int(size[0]), height: Int(size[1])) | ||
} set: { | ||
let isLandscape = MainTexture.shared.isLandscape | ||
rawValue.wrappedValue = [Int32($0.size.width), Int32($0.size.height)] | ||
if isLandscape != MainTexture.shared.isLandscape { | ||
SceneManager.shared.changeAspectRatio() | ||
} | ||
} | ||
} | ||
} | ||
|
||
extension UniBridge { | ||
public var canvasCGSize: CGSize { | ||
let size = canvasSize | ||
guard size.count == 2 else { return .init(width: 1920, height: 1280) } // an empty array after disposal | ||
return .init(width: CGFloat(size[0]), height: CGFloat(size[1])) | ||
} | ||
|
||
public static var cachedBlendShapes: [String] = [] | ||
public var cachedBlendShapes: [String] { | ||
Self.cachedBlendShapes | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// UniSet.swift | ||
// | ||
// | ||
// Created by Tatsuya Tanaka on 2023/03/01. | ||
// | ||
|
||
import SwiftUI | ||
import VCamEntity | ||
import VCamBridge | ||
|
||
@propertyWrapper public struct UniSet<Value: Hashable>: DynamicProperty { | ||
public init(_ type: UniBridge.BoolType, name: String) where Value == Bool { | ||
let mapper = UniBridge.shared.boolMapper | ||
self.set = mapper.set(type) | ||
self.name = name | ||
} | ||
|
||
private let set: (Value) -> Void | ||
private var name = "" | ||
|
||
public var wrappedValue: Action<Value> { | ||
.init(set: set) | ||
} | ||
|
||
public struct Action<T> { | ||
let set: (T) -> Void | ||
|
||
public func callAsFunction(_ value: T) { | ||
set(value) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// | ||
// RenderTextureManager.swift | ||
// | ||
// | ||
// Created by Tatsuya Tanaka on 2022/03/20. | ||
// | ||
|
||
import SwiftUI | ||
import VCamBridge | ||
import VCamLogger | ||
|
||
public final class RenderTextureManager { | ||
public static let shared = RenderTextureManager() | ||
|
||
private var recorders: [Int32: any RenderTextureRenderer] = [:] | ||
private let ciContext = CIContext(mtlDevice: MTLCreateSystemDefaultDevice()!) | ||
|
||
public func add(_ recorder: any RenderTextureRenderer) -> Int32 { | ||
let id = Int32.random(in: 0..<Int32.max) | ||
set(recorder, id: id) | ||
return id | ||
} | ||
|
||
public func set(_ recorder: any RenderTextureRenderer, id: Int32) { | ||
uniDebugLog("Set rendertexture: \(id)") | ||
recorders[id] = recorder | ||
} | ||
|
||
public func drawer(id: Int32) -> (any RenderTextureRenderer)? { | ||
recorders[id] | ||
} | ||
|
||
public func setRenderTexture(_ texture: any MTLTexture, id: Int32) { | ||
uniDebugLog("setRenderTexture: \(id) in \(recorders.keys)") | ||
guard let recorder = recorders[id] else { | ||
uniDebugLog("setRenderTexture: no recorder \(id)") | ||
return | ||
} | ||
Logger.log("\(texture.width)x\(texture.height), \(type(of: recorder))") | ||
|
||
recorder.setRenderTexture { [self] image in | ||
let width = image.extent.width | ||
let height = image.extent.height | ||
if recorder.updateTextureSizeIfNeeded(imageWidth: width, imageHeight: height) { | ||
Logger.log("updateTextureSizeIfNeeded") | ||
// iPhone's screen size initially becomes 0x0, so reconfigure when a texture is retrieved. | ||
if let object = SceneObjectManager.shared.objects.find(byId: id), let texture = object.type.croppableTexture { | ||
texture.crop = recorder.cropRect | ||
texture.region = .init(origin: .zero, size: .invalid) | ||
recorder.disableRenderTexture() | ||
Task { @MainActor in | ||
SceneObjectManager.shared.update(object) | ||
} | ||
return | ||
} | ||
} | ||
|
||
let (camWidth, camHeight) = (Int(width * recorder.cropRect.width), Int(width * recorder.cropRect.height)) | ||
if texture.width == camWidth, texture.height == camHeight { | ||
let croppedImage = recorder.cropped(of: image) | ||
ciContext.render(croppedImage, to: texture, commandBuffer: nil, bounds: croppedImage.extent, colorSpace: .sRGB) | ||
} else { | ||
Logger.log("setRenderTexture change size: \(texture.width) == \(camWidth), \(texture.height) == \(camHeight), \(width)") | ||
// Update the texture size | ||
recorder.disableRenderTexture() | ||
Task { @MainActor in | ||
UniBridge.shared.updateRenderTexture([Int32(id), Int32(camWidth), Int32(camHeight)]) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func remove(id: Int32) { | ||
guard let recorder = recorders[id] else { return } | ||
recorder.stopRendering() | ||
recorders.removeValue(forKey: id) | ||
} | ||
|
||
func removeAll() { | ||
let ids = [Int32](recorders.keys) | ||
for id in ids { | ||
remove(id: id) | ||
} | ||
} | ||
|
||
public func pause() { | ||
for recorder in recorders.values { | ||
recorder.pauseRendering() | ||
} | ||
} | ||
|
||
public func resume() { | ||
for recorder in recorders.values { | ||
recorder.resumeRendering() | ||
} | ||
} | ||
} |
Oops, something went wrong.