Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
2.8 kB · 62 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263// BackdropView.swift — living video backdrop (Seedance loop of the mascot// illy, bin/gen-backdrop.mjs) drawn aspect-fill at low opacity behind the UI.// Falls back to the faded static mascot if the video is absent. `mood`// nudges opacity so the wizard "leans in" while listening.import AppKitimport AVFoundation
final class BackdropView: NSView { enum Mood { case idle, listening } var mood: Mood = .idle { didSet { playerLayer.opacity = mood == .listening ? 0.24 : base } } private let base: Float = 0.16 private var player: AVQueuePlayer? private var looper: AVPlayerLooper? private let playerLayer = AVPlayerLayer() private let fallbackImage: NSImage?
override init(frame: NSRect) { fallbackImage = { let b = Bundle.module if let u = b.url(forResource: "clipwizard-mascot", withExtension: "png", subdirectory: "Assets") ?? b.url(forResource: "clipwizard-mascot", withExtension: "png"), let img = NSImage(contentsOf: u) { return img } return nil }() super.init(frame: frame) wantsLayer = true setupVideo() } required init?(coder: NSCoder) { fatalError() } override func hitTest(_ point: NSPoint) -> NSView? { nil }
private func setupVideo() { let b = Bundle.module guard let url = b.url(forResource: "clipwizard-backdrop", withExtension: "mp4", subdirectory: "Assets") ?? b.url(forResource: "clipwizard-backdrop", withExtension: "mp4") else { return } let item = AVPlayerItem(url: url) let queue = AVQueuePlayer() queue.isMuted = true looper = AVPlayerLooper(player: queue, templateItem: item) player = queue playerLayer.player = queue playerLayer.videoGravity = .resizeAspectFill playerLayer.opacity = base layer?.addSublayer(playerLayer) queue.play() } override func viewDidMoveToWindow() { super.viewDidMoveToWindow(); if window != nil { player?.play() } } override func layout() { super.layout() CATransaction.begin(); CATransaction.setDisableActions(true) playerLayer.frame = bounds CATransaction.commit() } override func draw(_ dirtyRect: NSRect) { guard player == nil, let img = fallbackImage else { return } let ar = img.size.width / img.size.height, var_ar = bounds.width / max(1, bounds.height) var r = bounds if ar > var_ar { let w = bounds.height * ar; r = NSRect(x: (bounds.width - w) * 0.5, y: 0, width: w, height: bounds.height) } else { let h = bounds.width / ar; r = NSRect(x: 0, y: (bounds.height - h) * 0.5, width: bounds.width, height: h) } img.draw(in: r, from: .zero, operation: .sourceOver, fraction: 0.10) }}