Model camera beats and independent hero identity locks

This commit is contained in:
Towsty
2026-09-10 23:48:25 -05:00
parent f312cff477
commit 3b071436a3
5 changed files with 146 additions and 24 deletions
+31
View File
@@ -0,0 +1,31 @@
import { restoreInput } from './contracts.mjs'
export const aspectOptions = [{id:'auto',label:'Automatic',hint:'Match start or hero still'},{id:'16:9',label:'16:9',hint:'1344 × 768 · padded'},{id:'9:16',label:'9:16',hint:'768 × 1344 · padded'},{id:'1:1',label:'1:1',hint:'960 × 960 · padded'}]
export function resolveSize(aspect, source, fallback = {width:1344,height:768}) {
const presets = {'16:9':[1344,768],'9:16':[768,1344],'1:1':[960,960]}
if (presets[aspect]) return {width:presets[aspect][0],height:presets[aspect][1]}
if (!source?.width || !source?.height) return {width:fallback.width || 1344,height:fallback.height || 768}
const factor = Math.min(1344/Math.max(source.width,source.height),768/Math.min(source.width,source.height))
return {width:Math.max(256,Math.round(source.width*factor/32)*32),height:Math.max(256,Math.round(source.height*factor/32)*32)}
}
export function bindClip(form, clip) {
if (!clip?.id) return form
const saved = clip.studio2 || {}, settings = saved.settings || clip.settings || clip
const next = {...form, startClipId:clip.id, settings:{...form.settings}}
for (const key of ['duration','aspect','width','height','fps','loraStack','turbo','steps','cfg']) {
if (settings[key] != null) next.settings[key] = structuredClone(settings[key])
}
next.engine = saved.engine || clip.engine || 'minimax'
if (saved.identityStillId) next.identityStillId = saved.identityStillId
// Missing legacy metadata must not reset a user's current choice.
for (const key of ['lockFace','lockOutfit']) if (typeof saved[key] === 'boolean') next[key] = saved[key]
return next
}
export function restoreAsset(form, item) {
const restored = restoreInput(item)
const next = {...form,...restored,settings:{...form.settings,...restored.settings}}
return item.kind === 'clip' || item.studio2?.kind === 'video' ? {...bindClip(next,item),mode:'extend'} : next
}
export function extendSelected(form, clip) {
// Switching task on the already bound clip must preserve the user's overrides.
return {...(clip?.id && form.startClipId !== clip.id ? bindClip(form,clip) : form),mode:'extend'}
}