Restore pre/post text when using clips as input or extending.
Extend no longer blanks wrappers when a part omitted them, Use as input inherits family pre/post, and non-image stills stay on Video instead of being forced into Image mode. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+66
-20
@@ -2261,7 +2261,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { composePromptParts, formatPromptParts, restorePromptParts } from '~/utils/promptParts'
|
import { composePromptParts, formatPromptParts, resolvePromptWrappers, restorePromptParts } from '~/utils/promptParts'
|
||||||
import { parseEditPasses, looksLikeShotScript } from '~/utils/parseRecommend'
|
import { parseEditPasses, looksLikeShotScript } from '~/utils/parseRecommend'
|
||||||
import { parseImageBatchScript, parseShotScript } from '~/utils/parseShots'
|
import { parseImageBatchScript, parseShotScript } from '~/utils/parseShots'
|
||||||
import type { DirectorScript } from '~/utils/directorScripts'
|
import type { DirectorScript } from '~/utils/directorScripts'
|
||||||
@@ -4325,16 +4325,39 @@ function insertKeepPrompt(item: KeepPrompt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyPromptRestore(saved: string, stored?: { prompt?: string; promptPre?: string; promptPost?: string } | null) {
|
function applyPromptRestore(saved: string, stored?: { prompt?: string; promptPre?: string; promptPost?: string } | null) {
|
||||||
const parts = restorePromptParts(saved, {
|
const wrappers = resolvePromptWrappers(stored || undefined)
|
||||||
pre: stored?.promptPre,
|
const mid = String(saved || stored?.prompt || '').trim()
|
||||||
prompt: saved,
|
const parts = restorePromptParts(mid, {
|
||||||
post: stored?.promptPost
|
pre: wrappers.promptPre || stored?.promptPre,
|
||||||
|
prompt: mid,
|
||||||
|
post: wrappers.promptPost || stored?.promptPost
|
||||||
})
|
})
|
||||||
promptPre.value = parts.pre
|
promptPre.value = parts.pre
|
||||||
prompt.value = parts.prompt
|
prompt.value = parts.prompt
|
||||||
promptPost.value = parts.post
|
promptPost.value = parts.post
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function promptPartsForClip(
|
||||||
|
clip: LibraryClip | null | undefined,
|
||||||
|
midFallback = ''
|
||||||
|
) {
|
||||||
|
const family = clip ? familyPartsFor(clip) : []
|
||||||
|
const wrappers = resolvePromptWrappers(
|
||||||
|
clip || undefined,
|
||||||
|
family[0],
|
||||||
|
{
|
||||||
|
promptPre: promptPre.value,
|
||||||
|
promptPost: promptPost.value
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const mid = String(clip?.prompt || midFallback || '').trim()
|
||||||
|
return restorePromptParts(mid, {
|
||||||
|
pre: wrappers.promptPre,
|
||||||
|
prompt: mid,
|
||||||
|
post: wrappers.promptPost
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function queuedExtensionFrom(
|
function queuedExtensionFrom(
|
||||||
item: { prompt?: string; promptPre?: string; promptPost?: string; duration?: number; loraName?: string; loraStack?: LoraStackItem[] },
|
item: { prompt?: string; promptPre?: string; promptPost?: string; duration?: number; loraName?: string; loraStack?: LoraStackItem[] },
|
||||||
duration: number,
|
duration: number,
|
||||||
@@ -5533,6 +5556,7 @@ async function restoreStudioPayload(kind: string, payload: {
|
|||||||
refinementDenoise?: number
|
refinementDenoise?: number
|
||||||
promptPre?: string
|
promptPre?: string
|
||||||
promptPost?: string
|
promptPost?: string
|
||||||
|
promptMid?: string
|
||||||
globalLocks?: string
|
globalLocks?: string
|
||||||
permanenceRefs?: PermanenceRef[]
|
permanenceRefs?: PermanenceRef[]
|
||||||
shotPermanenceRefs?: PermanenceRef[][]
|
shotPermanenceRefs?: PermanenceRef[][]
|
||||||
@@ -5568,9 +5592,15 @@ async function restoreStudioPayload(kind: string, payload: {
|
|||||||
|| Object.prototype.hasOwnProperty.call(item, 'promptPost')
|
|| Object.prototype.hasOwnProperty.call(item, 'promptPost')
|
||||||
)
|
)
|
||||||
applyVideoWorkflow(payload.workflow)
|
applyVideoWorkflow(payload.workflow)
|
||||||
|
const mid = String(payload.promptMid || '').trim() || String(payload.prompt || '').trim()
|
||||||
applyPromptRestore(queuedAsCards || !extensions.length
|
applyPromptRestore(queuedAsCards || !extensions.length
|
||||||
? (payload.prompt || '')
|
? mid
|
||||||
: [payload.prompt.trim(), ...extensions.map((item, index) => `shot ${index + 2}\n${item.prompt.trim()}`)].join('\n\n'), payload)
|
: [mid, ...extensions.map((item, index) => `shot ${index + 2}\n${String(item.prompt || '').trim()}`)].join('\n\n'), {
|
||||||
|
...payload,
|
||||||
|
prompt: mid,
|
||||||
|
promptPre: payload.promptPre,
|
||||||
|
promptPost: payload.promptPost
|
||||||
|
})
|
||||||
clipName.value = payload.name || ''
|
clipName.value = payload.name || ''
|
||||||
seedInput.value = String(payload.seed || '')
|
seedInput.value = String(payload.seed || '')
|
||||||
restoreAdvanced({
|
restoreAdvanced({
|
||||||
@@ -5944,7 +5974,13 @@ async function rerun(item: LibraryClip, collection = false) {
|
|||||||
const parts = familyPartsFor(item)
|
const parts = familyPartsFor(item)
|
||||||
const target = collection ? parts[0] || item : item
|
const target = collection ? parts[0] || item : item
|
||||||
const restoreAll = collection && parts.length > 1
|
const restoreAll = collection && parts.length > 1
|
||||||
applyPromptRestore(restoreAll ? familyScript(parts) : target.prompt, target)
|
const ordered = chronologicalParts(parts)
|
||||||
|
const wrappers = resolvePromptWrappers(target, ordered[0])
|
||||||
|
applyPromptRestore(restoreAll ? familyScript(parts) : target.prompt, {
|
||||||
|
prompt: restoreAll ? familyScript(parts) : target.prompt,
|
||||||
|
promptPre: wrappers.promptPre || target.promptPre,
|
||||||
|
promptPost: wrappers.promptPost || target.promptPost
|
||||||
|
})
|
||||||
clipName.value = restoreAll
|
clipName.value = restoreAll
|
||||||
? (familyBaseName(collectionTitle({ head: target, parts })) || target.name || '')
|
? (familyBaseName(collectionTitle({ head: target, parts })) || target.name || '')
|
||||||
: (target.name || '')
|
: (target.name || '')
|
||||||
@@ -5959,7 +5995,6 @@ async function rerun(item: LibraryClip, collection = false) {
|
|||||||
if (typeof target.sound === 'boolean') withSound.value = target.sound
|
if (typeof target.sound === 'boolean') withSound.value = target.sound
|
||||||
shotScriptMode.value = restoreAll
|
shotScriptMode.value = restoreAll
|
||||||
identityRefs.value.forEach((_, index) => clearIdentityRef(index))
|
identityRefs.value.forEach((_, index) => clearIdentityRef(index))
|
||||||
const ordered = chronologicalParts(parts)
|
|
||||||
globalLocks.value = ordered.find(part => part.globalLocks)?.globalLocks || target.globalLocks || ''
|
globalLocks.value = ordered.find(part => part.globalLocks)?.globalLocks || target.globalLocks || ''
|
||||||
familyPermanenceRefs.value = ordered[0]?.permanenceRefs || target.permanenceRefs || []
|
familyPermanenceRefs.value = ordered[0]?.permanenceRefs || target.permanenceRefs || []
|
||||||
const familyIds = new Set(familyPermanenceRefs.value.map(ref => ref.stillId))
|
const familyIds = new Set(familyPermanenceRefs.value.map(ref => ref.stillId))
|
||||||
@@ -5974,11 +6009,18 @@ async function rerun(item: LibraryClip, collection = false) {
|
|||||||
restoreAll ? ordered : undefined
|
restoreAll ? ordered : undefined
|
||||||
)
|
)
|
||||||
extensionQueue.value = restoreAll
|
extensionQueue.value = restoreAll
|
||||||
? parts.slice(1).map(part => queuedExtensionFrom(
|
? parts.slice(1).map(part => {
|
||||||
part,
|
const shotWrappers = resolvePromptWrappers(part, ordered[0], target)
|
||||||
clipGenerateDuration(part),
|
return queuedExtensionFrom(
|
||||||
loraStacksEqual(readLoraStack(part), readLoraStack(ordered[0] || target)) ? [] : readLoraStack(part)
|
{
|
||||||
))
|
...part,
|
||||||
|
promptPre: shotWrappers.promptPre || part.promptPre,
|
||||||
|
promptPost: shotWrappers.promptPost || part.promptPost
|
||||||
|
},
|
||||||
|
clipGenerateDuration(part),
|
||||||
|
loraStacksEqual(readLoraStack(part), readLoraStack(ordered[0] || target)) ? [] : readLoraStack(part)
|
||||||
|
)
|
||||||
|
})
|
||||||
: []
|
: []
|
||||||
try {
|
try {
|
||||||
const initialTextToVideo = textToVideo.value && !target.parentClipId && !(target.chainIndex)
|
const initialTextToVideo = textToVideo.value && !target.parentClipId && !(target.chainIndex)
|
||||||
@@ -6144,13 +6186,11 @@ async function openExtend(item?: LibraryClip) {
|
|||||||
}
|
}
|
||||||
currentClipId.value = id
|
currentClipId.value = id
|
||||||
extendClipId.value = id
|
extendClipId.value = id
|
||||||
const clip = clips.value.find(entry => entry.id === id)
|
const clip = clips.value.find(entry => entry.id === id) || item || null
|
||||||
if (clip) ensureFamilyExpanded(clip)
|
if (clip) ensureFamilyExpanded(clip)
|
||||||
const parts = restorePromptParts(clip?.prompt || prompt.value, {
|
// Prefer clip wrappers, then family head, then the main form — never blank pre/post
|
||||||
pre: clip ? (clip.promptPre || '') : promptPre.value,
|
// just because this part did not re-store them.
|
||||||
prompt: clip?.prompt || prompt.value,
|
const parts = promptPartsForClip(clip, prompt.value)
|
||||||
post: clip ? (clip.promptPost || '') : promptPost.value
|
|
||||||
})
|
|
||||||
extendPromptPre.value = parts.pre
|
extendPromptPre.value = parts.pre
|
||||||
extendPrompt.value = parts.prompt
|
extendPrompt.value = parts.prompt
|
||||||
extendPromptPost.value = parts.post
|
extendPromptPost.value = parts.post
|
||||||
@@ -6297,6 +6337,12 @@ function applyStillSettings(still: LibraryStill) {
|
|||||||
browseFolderId.value = still.folderId
|
browseFolderId.value = still.folderId
|
||||||
rememberInputSeed(settings?.seed)
|
rememberInputSeed(settings?.seed)
|
||||||
applyPromptRestore(still.prompt || '', still)
|
applyPromptRestore(still.prompt || '', still)
|
||||||
|
// Non-image stills are video start frames — keep Video mode and only restore prompt parts.
|
||||||
|
if (!dest) {
|
||||||
|
studioMode.value = 'video'
|
||||||
|
outputFocus.value = 'video'
|
||||||
|
return
|
||||||
|
}
|
||||||
if (dest === 'imagev2') {
|
if (dest === 'imagev2') {
|
||||||
studioMode.value = 'editv2'
|
studioMode.value = 'editv2'
|
||||||
outputFocus.value = 'edit'
|
outputFocus.value = 'edit'
|
||||||
|
|||||||
Reference in New Issue
Block a user