Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
2.6 kB · 59 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960// 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.import AppKitimport AVFoundation
final class BackdropView: NSView { private var player: AVQueuePlayer? private var looper: AVPlayerLooper? private let playerLayer = AVPlayerLayer() private let fallbackImage: NSImage? private let idleOpacity: Float = 0.55
override init(frame: NSRect) { fallbackImage = { let b = Bundle.module if let u = b.url(forResource: "datewizard-mascot", withExtension: "png", subdirectory: "Assets") ?? b.url(forResource: "datewizard-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: "datewizard-backdrop", withExtension: "mp4", subdirectory: "Assets") ?? b.url(forResource: "datewizard-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 = idleOpacity 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, varAr = bounds.width / max(1, bounds.height) var r = bounds if ar > varAr { 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) }}