Skip to content

Commit

Permalink
0.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tattn committed Feb 15, 2023
1 parent 45eaa86 commit 7696e8d
Show file tree
Hide file tree
Showing 16 changed files with 637 additions and 73 deletions.
20 changes: 18 additions & 2 deletions app/xcode/Sources/VCamLocalization/Generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ public enum L10n {
public static let enable = LocalizedString(lookupKey: "enable")
/// Convert VRM 0.x to VRM 1.x
public static let enableAutoConvertingToVRM1 = LocalizedString(lookupKey: "enableAutoConvertingToVRM1")
/// Enable VSync
public static let enableVSync = LocalizedString(lookupKey: "enableVSync")
/// English
public static let english = LocalizedString(lookupKey: "english")
/// Entire Display
Expand All @@ -144,6 +146,14 @@ public enum L10n {
public static func existsNewAppVersion(_ p1: Any) -> ArgumentsLocalizedString {
ArgumentsLocalizedString("existsNewAppVersion %@", "existsNewAppVersion \(String(describing: p1))", String(describing: p1))
}
/// Experiment
public static let experiment = LocalizedString(lookupKey: "experiment")
/// The supporter version of the app can be downloaded from the following link:
public static let experimentAdvertisement = LocalizedString(lookupKey: "experimentAdvertisement")
/// These are experimental features and may have bugs.
public static let experimentDisclaimer = LocalizedString(lookupKey: "experimentDisclaimer")
/// These features are available for our supporters, thank you for your supporting!
public static let experimentThanks = LocalizedString(lookupKey: "experimentThanks")
/// Horizontal sensitivity
public static let eyesHorizontalSensitivity = LocalizedString(lookupKey: "eyesHorizontalSensitivity")
/// Vertical sensitivity
Expand All @@ -160,12 +170,14 @@ public enum L10n {
public static let filter = LocalizedString(lookupKey: "filter")
/// Finger
public static let finger = LocalizedString(lookupKey: "finger")
/// Flip screen
/// Flip screen of the virtual camera
public static let flipScreen = LocalizedString(lookupKey: "flipScreen")
/// FPS (tracking)
public static let fpsCamera = LocalizedString(lookupKey: "fpsCamera")
/// FPS (screen)
public static let fpsScreen = LocalizedString(lookupKey: "fpsScreen")
/// General
public static let general = LocalizedString(lookupKey: "general")
/// Hand
public static let hand = LocalizedString(lookupKey: "hand")
/// Height
Expand Down Expand Up @@ -252,6 +264,8 @@ public enum L10n {
public static let object = LocalizedString(lookupKey: "object")
/// Open preferences
public static let openPreference = LocalizedString(lookupKey: "openPreference")
/// Open VCam
public static let openVCam = LocalizedString(lookupKey: "openVCam")
/// Optimize meshes (Recommended)
public static let optimizeMeshes = LocalizedString(lookupKey: "optimizeMeshes")
/// Paste
Expand Down Expand Up @@ -296,6 +310,8 @@ public enum L10n {
public static let remove = LocalizedString(lookupKey: "remove")
/// Remove VCam from the capture
public static let removeVCamFromCapture = LocalizedString(lookupKey: "removeVCamFromCapture")
/// Rendering
public static let rendering = LocalizedString(lookupKey: "rendering")
/// Rendering Quality
public static let renderingQuality = LocalizedString(lookupKey: "renderingQuality")
/// Reset Avatar Position
Expand Down Expand Up @@ -382,7 +398,7 @@ public enum L10n {
public static func useEmotionBy(_ p1: Any) -> ArgumentsLocalizedString {
ArgumentsLocalizedString("useEmotionBy %@", "useEmotionBy \(String(describing: p1))", String(describing: p1))
}
/// Use vowel estimation by camera [β]
/// Use vowel estimation by camera
public static let useVowelEstimation = LocalizedString(lookupKey: "useVowelEstimation")
/// Video Capture
public static let videoCapture = LocalizedString(lookupKey: "videoCapture")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"done" = "Done";
"edit" = "Edit";
"pick" = "Pick";
"general" = "General";
"apply" = "Apply";
"remove" = "Remove";
"duplicate" = "Duplicate";
Expand Down Expand Up @@ -100,7 +101,7 @@
"optimizeMeshes" = "Optimize meshes (Recommended)";
"enableAutoConvertingToVRM1" = "Convert VRM 0.x to VRM 1.x";
"helpMesh" = "Reduce the load on the app by merging meshes, etc. If you have problems viewing the model, turn it off and reload the model.";
"flipScreen" = "Flip screen";
"flipScreen" = "Flip screen of the virtual camera";
"addToMacOSMenuBar" = "Add icon in macOS menu bar";
"background" = "Background";
"lipSyncSensitivity" = "Lip-sync sensitivity (mic)";
Expand All @@ -116,13 +117,19 @@
"qualityGood" = "Good";
"qualityBeautiful" = "Beautiful";
"qualityFantastic" = "Fantastic";
"rendering" = "Rendering";
"experiment" = "Experiment";
"experimentDisclaimer" = "These are experimental features and may have bugs.";
"experimentThanks" = "These features are available for our supporters, thank you for your supporting!";
"experimentAdvertisement" = "The supporter version of the app can be downloaded from the following link:";
"enableVSync" = "Enable VSync";

// MARK: - Tracking

"micOrCamera" = "Mic or Camera";
"helpCalibrate" = "If the movement is out of sync with the actual movement, press this button while facing forward to the camera and looking at the camera.";
"useEmotionBy %@" = "Use emotion by %@ [β] (Use high power)";
"useVowelEstimation" = "Use vowel estimation by camera [β]";
"useVowelEstimation" = "Use vowel estimation by camera";
"isNotFound %@" = "%@ is not found";
"lipSync" = "Lip-sync";
"trackEyes" = "Track eyes";
Expand Down Expand Up @@ -225,6 +232,7 @@
"help" = "Help";
"anyProblem" = "Any problem?";
"quitVCam" = "Quit VCam";
"openVCam" = "Open VCam";

"editAvatar" = "Edit Avatar";
"recalibrate" = "Recalibrate";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"done" = "完了";
"edit" = "編集";
"pick" = "選択";
"general" = "一般";
"apply" = "適用";
"remove" = "削除";
"duplicate" = "複製";
Expand Down Expand Up @@ -100,7 +101,7 @@
"optimizeMeshes" = "モデルのメッシュを最適化する (推奨)";
"enableAutoConvertingToVRM1" = "VRM0.x系のアバターを1.0系に自動変換する";
"helpMesh" = "メッシュの結合等によりアプリの負荷を大幅に下げられます。モデルの表示に問題がある場合はオフにした後、モデルを再読込してください。";
"flipScreen" = "画面を左右反転する";
"flipScreen" = "仮想カメラの画面を左右反転する";
"addToMacOSMenuBar" = "macOSのメニューバーに追加する";
"background" = "背景";
"lipSyncSensitivity" = "リップシンクの感度 (マイク)";
Expand All @@ -116,13 +117,19 @@
"qualityGood" = "良品質";
"qualityBeautiful" = "高品質";
"qualityFantastic" = "最高品質";
"rendering" = "レンダリング";
"experiment" = "実験的な機能";
"experimentDisclaimer" = "これらは実験的な機能のため、不具合がある可能性があります。";
"experimentThanks" = "これらの機能はサポーター向けに提供しています。VCamのサポート、ありがとうございます!";
"experimentAdvertisement" = "これらの機能はサポーター向けに提供しています。サポーター版は以下からDLできます。";
"enableVSync" = "VSyncを有効にする";

// MARK: - Tracking

"micOrCamera" = "マイクまたはカメラ";
"helpCalibrate" = "実際の動きとずれている場合は、カメラに対して正面を向いた状態でカメラ目線でこのボタンを押してください";
"useEmotionBy %@" = "表情を%@で推定して反映する [β] (負荷増)";
"useVowelEstimation" = "カメラで母音を推定する [β]";
"useVowelEstimation" = "カメラで母音を推定する";
"isNotFound %@" = "%@が見つかりません";
"lipSync" = "リップシンク";
"trackEyes" = "目をトラッキングする";
Expand Down Expand Up @@ -224,7 +231,8 @@
"resetAvatarPosition" = "アバターの位置をリセット";
"help" = "ヘルプ";
"anyProblem" = "困った時は?";
"quitVCam" = "VCam を終了";
"quitVCam" = "VCamを終了";
"openVCam" = "VCamを開く";

"editAvatar" = "アバターの編集";
"recalibrate" = "再キャリブレーション";
Expand Down
22 changes: 12 additions & 10 deletions app/xcode/Sources/VCamUI/AppUpdater+UI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import VCamLocalization

struct AppUpdateInformationView: View {
let release: AppUpdater.LatestRelease
let window: NSWindow

@AppStorage(key: .skipThisVersion) var skipThisVersion

@Environment(\.nsWindow) var nsWindow

var body: some View {
VStack(alignment: .leading) {
Text(L10n.existsNewAppVersion(release.version.description).key, bundle: .localize)
Expand All @@ -35,7 +36,7 @@ struct AppUpdateInformationView: View {
HStack {
Button {
skipThisVersion = release.version.description
window.close()
nsWindow?.close()
} label: {
Text(L10n.skipThisVersion.key, bundle: .localize)
}
Expand All @@ -62,9 +63,15 @@ struct AppUpdateInformationView: View {
}
}
.padding()
.background(.thinMaterial)
.frame(width: 600, height: 400)
}
}

extension AppUpdateInformationView: MacWindow {
static var windowTitle: String { L10n.update.text }
}

extension AppUpdater {
@MainActor
public func presentUpdateAlert() async {
Expand All @@ -77,20 +84,15 @@ extension AppUpdater {
_ = alert.runModal()
return
}
presentWindow(title: L10n.update.text, id: nil, size: .init(width: 600, height: 400)) { window in
AppUpdateInformationView(release: release, window: window)
.background(.thinMaterial)
}

MacWindowManager.shared.open(AppUpdateInformationView(release: release))
}

@MainActor
public func presentUpdateAlertIfAvailable() async {
guard let release = try? await check(), UserDefaults.standard.value(for: .skipThisVersion) < release.version else {
return // already latest or error
}
presentWindow(title: L10n.update.text, id: nil, size: .init(width: 600, height: 400)) { window in
AppUpdateInformationView(release: release, window: window)
.background(.thinMaterial)
}
MacWindowManager.shared.open(AppUpdateInformationView(release: release))
}
}
19 changes: 19 additions & 0 deletions app/xcode/Sources/VCamUI/Extensions/NSWindowKey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// NSWindowKey.swift
//
//
// Created by Tatsuya Tanaka on 2023/02/14.
//

import SwiftUI

private struct NSWindowKey: EnvironmentKey {
static let defaultValue: NSWindow? = nil
}

extension EnvironmentValues {
var nsWindow: NSWindow? {
get { self[NSWindowKey.self] }
set { self[NSWindowKey.self] = newValue }
}
}
64 changes: 64 additions & 0 deletions app/xcode/Sources/VCamUI/MacWindowManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// MacWindowManager.swift
//
//
// Created by Tatsuya Tanaka on 2023/02/14.
//

import AppKit
import SwiftUI
import VCamEntity

public protocol MacWindow: View {
static var windowTitle: String { get }
}

public final class MacWindowManager {
public static let shared = MacWindowManager()

private var openWindows: [String: NSWindow] = [:]

public func open<T: MacWindow>(_ windowView: T) {
let id = String(describing: T.self)
if let window = openWindows[id] {
window.makeKeyAndOrderFront(nil)
return
}

let window = NSWindow(
contentRect: .init(origin: .zero, size: .init(width: 1, height: 400)),
styleMask: [.titled, .closable, .fullSizeContentView],
backing: .buffered,
defer: false
)
window.isReleasedWhenClosed = false
window.contentView = NSHostingView(
rootView: WindowContainer(content: windowView)
.environment(\.nsWindow, window)
)
window.title = T.windowTitle
window.makeKeyAndOrderFront(nil)
window.center()
openWindows[id] = window

var observation: Any?
observation = NotificationCenter.default.addObserver(forName: NSWindow.willCloseNotification, object: nil, queue: .main) { notification in
guard notification.object as? NSWindow == window else { return }
Self.shared.openWindows.removeValue(forKey: id)
if let observation {
NotificationCenter.default.removeObserver(observation)
}
}
}
}

private struct WindowContainer<Content: View>: View {
let content: Content

@AppStorage(key: .locale) var locale

var body: some View {
content
.environment(\.locale, Locale(identifier: locale))
}
}
29 changes: 18 additions & 11 deletions app/xcode/Sources/VCamUI/RootContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,44 @@

import SwiftUI

public struct RootContentView<VCamUI: View, MenuBottomView: View>: View, Equatable {
public init(vcamUI: VCamUI, menuBottomView: MenuBottomView, unityView: NSView, interactable: Bool) {
public struct RootContentView<VCamUI: View, MenuBottomView: View, Toolbar: View>: View {
public init(vcamUI: VCamUI, menuBottomView: MenuBottomView, toolbar: Toolbar, unityView: NSView, interactable: Bool) {
self.vcamUI = vcamUI
self.menuBottomView = menuBottomView
self.toolbar = toolbar
self.unityView = unityView
self.interactable = interactable
}

let vcamUI: VCamUI
let menuBottomView: MenuBottomView
let toolbar: Toolbar
let unityView: NSView
let interactable: Bool

@State var isPopover = false

public var body: some View {
if interactable {
HStack {
HStack(spacing: 0) {
VCamMenu(
bottomView: menuBottomView.frame(height: 200)
bottomView: menuBottomView.frame(height: 280)
)
.onTapGesture {
unityView.window?.makeFirstResponder(nil)
}
.disabled(!interactable)

VSplitView {
UnityView(unityView: unityView)
.equatable()
.layoutPriority(1)
HStack(alignment: .bottom, spacing: 0) {
toolbar
UnityView(unityView: unityView)
.equatable()
.frame(maxWidth: .infinity)
}
.frame(maxWidth: .infinity)
.layoutPriority(1)

vcamUI
.onTapGesture {
unityView.window?.makeFirstResponder(nil)
Expand All @@ -47,10 +57,6 @@ public struct RootContentView<VCamUI: View, MenuBottomView: View>: View, Equatab
.layoutPriority(1)
}
}

public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.interactable == rhs.interactable
}
}

struct UnityView: View, Equatable {
Expand Down Expand Up @@ -83,6 +89,7 @@ struct RootContentView_Previews: PreviewProvider {
RootContentView(
vcamUI: Color.red,
menuBottomView: Color.blue,
toolbar: Color.yellow,
unityView: NSView(),
interactable: true
)
Expand Down
Loading

0 comments on commit 7696e8d

Please sign in to comment.