Remember Studio 2 LoRA stacks for each engine
This commit is contained in:
+17
-14
@@ -1,3 +1,4 @@
|
||||
import {restoreLoras,loraUse} from './lora-memory.mjs'
|
||||
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}) {
|
||||
@@ -7,7 +8,7 @@ export function resolveSize(aspect, source, fallback = {width:1344,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, xaigen = false) {
|
||||
export function bindClip(form, clip, xaigen = false, memory) {
|
||||
if (!clip?.id) return form
|
||||
const saved = clip.studio2 || clip.job || {}
|
||||
const settings = saved.settings || clip.settings || {}
|
||||
@@ -21,11 +22,11 @@ export function bindClip(form, clip, xaigen = false) {
|
||||
next.engine = xaigen && (saved.engine || clip.engine)==='ltx' ? 'ltx' : 'minimax'
|
||||
if (saved.identityStillId) next.identityStillId = saved.identityStillId
|
||||
for (const key of ['lockFace','lockOutfit']) if (typeof saved[key] === 'boolean') next[key] = saved[key]
|
||||
return next
|
||||
return restoreLoras(next,settings.loraStack,xaigen,memory)
|
||||
}
|
||||
export function restoreAsset(form, item) {
|
||||
export function restoreAsset(form, item, xaigen = false, memory) {
|
||||
if (item.kind==='clip' || item.studio2?.kind==='video') {
|
||||
const next=bindClip(form,item,form.engine==='ltx')
|
||||
const next=bindClip(form,item,xaigen,memory)
|
||||
const seed=item.studio2?.settings?.seed ?? item.settings?.seed ?? item.seed
|
||||
if (seed != null) next.settings.seed=seed
|
||||
next.settings.seedMode='random'
|
||||
@@ -34,20 +35,21 @@ export function restoreAsset(form, item) {
|
||||
const restored = restoreInput(item)
|
||||
const next = {...form,...restored,settings:{...form.settings,...restored.settings}}
|
||||
next.settings.seedMode='random'
|
||||
if (item.kind === 'clip' || item.studio2?.kind === 'video') return {...bindClip(next,item),mode:'extend'}
|
||||
next.engine=restored.engine==='krea'?'krea':'flux'
|
||||
next.mode=['generate','edit','compose','refine','iterate'].includes(restored.mode)?restored.mode:'edit'
|
||||
next.imageAId=item.id
|
||||
next.startClipId=''
|
||||
next.settings.aspect=item.studio2?.settings?.aspect || item.settings?.aspect || 'auto'
|
||||
return next
|
||||
return restoreLoras(next,item.studio2?.settings?.loraStack ?? item.settings?.loraStack,xaigen,memory)
|
||||
}
|
||||
export function extendSelected(form, clip, xaigen = false) {
|
||||
const next = { ...form, mode: 'extend', engine: xaigen && form.engine === 'ltx' ? 'ltx' : 'minimax' }
|
||||
export function extendSelected(form, clip, xaigen = false, memory) {
|
||||
const next = { ...form, settings:{...form.settings}, mode: 'extend', engine: xaigen && form.engine === 'ltx' ? 'ltx' : 'minimax' }
|
||||
const target = clip?.id ? clip : null
|
||||
if (!target?.id) return next
|
||||
if (!target?.id) return restoreLoras(next,loraUse(form)===loraUse(next)?form.settings?.loraStack:[],xaigen,memory)
|
||||
// Already bound to this clip: switching task must not stomp the user's overrides
|
||||
// (locks, CFG, etc.) by re-copying the clip's saved settings over them.
|
||||
if (form.startClipId === target.id) return next
|
||||
try { return bindClip(next, target, xaigen) }
|
||||
if (form.startClipId === target.id) return restoreLoras(next,loraUse(form)===loraUse(next)?form.settings?.loraStack:[],xaigen,memory)
|
||||
try { return bindClip(next, target, xaigen, memory) }
|
||||
catch { return { ...next, startClipId: target.id } }
|
||||
}
|
||||
export function changeSource(form) {
|
||||
@@ -56,11 +58,12 @@ export function changeSource(form) {
|
||||
|
||||
export function useAsHero(form, item) { return {...form,identityStillId:item.id} }
|
||||
export function useAsSource(form, item) { return {...form,imageAId:item.id} }
|
||||
export function restoreAll(form,item,xaigen=false) {
|
||||
export function restoreAll(form,item,xaigen=false,memory) {
|
||||
const restored=restoreInput(item),next={...form,...restored,settings:{...form.settings,...restored.settings,seedMode:'random'}}
|
||||
if(item.kind==='clip') return {...bindClip(next,item,xaigen),mode:'extend'}
|
||||
if(item.kind==='clip') return {...bindClip(next,item,xaigen,memory),mode:'extend'}
|
||||
next.mode=restored.mode==='iterate'?'edit':restored.mode || 'edit'
|
||||
next.engine=restored.engine==='krea'?'krea':'flux'
|
||||
next.imageAId=item.id
|
||||
next.startClipId=''
|
||||
return next
|
||||
return restoreLoras(next,item.studio2?.settings?.loraStack ?? item.settings?.loraStack,xaigen,memory)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import {filterLoraStackForUse} from '../../utils/loras.ts'
|
||||
|
||||
export function loraUse(form) {
|
||||
const video=['video','extend'].includes(form.mode)
|
||||
return video ? (form.engine==='ltx'?'ltx':'minimax') : (form.engine==='krea'?'krea':'flux')
|
||||
}
|
||||
|
||||
// One controller per bench. Storage is optional (SSR/private browsing still works).
|
||||
export function createLoraMemory(xaigen, storage) {
|
||||
const stacks={}
|
||||
let active=null
|
||||
const key=`studio2-lora-stacks:${xaigen?'xaigen':'aigen'}`
|
||||
try { Object.assign(stacks,JSON.parse(storage?.getItem(key)||'{}')) } catch {}
|
||||
const load=use=>filterLoraStackForUse(stacks[use],use,xaigen)
|
||||
const save=(use,stack)=>{
|
||||
stacks[use]=filterLoraStackForUse(stack,use,xaigen)
|
||||
try { storage?.setItem(key,JSON.stringify(stacks)) } catch {}
|
||||
}
|
||||
return {
|
||||
sync(form) {
|
||||
const use=loraUse(form)
|
||||
if(active!==use) {
|
||||
// Every stack edit is remembered by the bench watcher before a later switch.
|
||||
active=use
|
||||
form.settings.loraStack=load(use)
|
||||
}
|
||||
save(use,form.settings.loraStack)
|
||||
},
|
||||
restore(form,stack) {
|
||||
const use=loraUse(form)
|
||||
form.settings.loraStack=stack?.length ? filterLoraStackForUse(stack,use,xaigen) : load(use)
|
||||
active=use
|
||||
save(use,form.settings.loraStack)
|
||||
return form
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function restoreLoras(form, stack, xaigen=false, memory) {
|
||||
if(memory) return memory.restore(form,stack)
|
||||
form.settings.loraStack=filterLoraStackForUse(stack,loraUse(form),xaigen)
|
||||
return form
|
||||
}
|
||||
Reference in New Issue
Block a user