0.8.7: duplicate track via right-click (layer / clip / script)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
d60684edd1
commit
517705bf55
4 files changed
+254
-1
No files matched your search
@@ -1756,6 +1756,100 @@ export const useSceneStore = defineStore('scene', {
|
||||
;(this.scene.trackOrder ||= []).push(track.id)
|
||||
return track
|
||||
},
|
||||
/**
|
||||
* Duplicate a top-level track by id. Handles layer / clipTrack /
|
||||
* scriptTrack — clip instances and script frames belonging to the
|
||||
* original are cloned too. The duplicate lands directly after the
|
||||
* original in trackOrder (or in the same group's childIds if the
|
||||
* original lived inside one). Groups themselves are not supported
|
||||
* here; returns null for unknown ids, clip-edit / button-edit
|
||||
* contexts, and groups.
|
||||
*/
|
||||
duplicateTrack(id: string): string | null {
|
||||
if (this.activeClipId || this.activeButtonAssetId) return null
|
||||
const scene = this.scene
|
||||
|
||||
// Grouped tracks live in TrackGroup.childIds and are absent from
|
||||
// scene.trackOrder entirely (only the group's own id appears at
|
||||
// top level). Duplicate stays inside whichever container held the
|
||||
// original.
|
||||
const placeAfter = (afterId: string, newId: string) => {
|
||||
const order = (scene.trackOrder ||= [])
|
||||
const idx = order.indexOf(afterId)
|
||||
if (idx >= 0) {
|
||||
order.splice(idx + 1, 0, newId)
|
||||
return
|
||||
}
|
||||
for (const g of scene.groups ?? []) {
|
||||
const gi = g.childIds.indexOf(afterId)
|
||||
if (gi >= 0) {
|
||||
g.childIds.splice(gi + 1, 0, newId)
|
||||
return
|
||||
}
|
||||
}
|
||||
order.push(newId)
|
||||
}
|
||||
|
||||
const layer = scene.layers.find((l) => l.id === id)
|
||||
if (layer) {
|
||||
const cloned = structuredClone(toRaw(layer)) as Layer
|
||||
cloned.id = uid()
|
||||
cloned.keyframes = cloned.keyframes.map((k) => ({ ...k, id: uid() }))
|
||||
if (cloned.positionKeyframes) {
|
||||
cloned.positionKeyframes = cloned.positionKeyframes.map((k) => ({ ...k, id: uid() }))
|
||||
}
|
||||
if (cloned.rotationKeyframes) {
|
||||
cloned.rotationKeyframes = cloned.rotationKeyframes.map((k) => ({ ...k, id: uid() }))
|
||||
}
|
||||
const origIdx = scene.layers.findIndex((l) => l.id === id)
|
||||
scene.layers.splice(origIdx + 1, 0, cloned)
|
||||
placeAfter(id, cloned.id)
|
||||
return cloned.id
|
||||
}
|
||||
|
||||
const clipTrack = scene.clipTracks?.find((t) => t.id === id)
|
||||
if (clipTrack) {
|
||||
const newTrack: ClipTrack = {
|
||||
...(structuredClone(toRaw(clipTrack)) as ClipTrack),
|
||||
id: uid(),
|
||||
}
|
||||
;(scene.clipTracks ||= []).push(newTrack)
|
||||
const instances = scene.clipInstances?.filter((ci) => ci.clipTrackId === id) ?? []
|
||||
for (const ci of instances) {
|
||||
const clonedInst: ClipInstance = {
|
||||
...(structuredClone(toRaw(ci)) as ClipInstance),
|
||||
id: uid(),
|
||||
clipTrackId: newTrack.id,
|
||||
}
|
||||
;(scene.clipInstances ||= []).push(clonedInst)
|
||||
}
|
||||
placeAfter(id, newTrack.id)
|
||||
return newTrack.id
|
||||
}
|
||||
|
||||
const scriptTrack = scene.scriptTracks?.find((t) => t.id === id)
|
||||
if (scriptTrack) {
|
||||
const newTrack: ScriptTrack = {
|
||||
...(structuredClone(toRaw(scriptTrack)) as ScriptTrack),
|
||||
id: uid(),
|
||||
}
|
||||
;(scene.scriptTracks ||= []).push(newTrack)
|
||||
const frames = scene.scriptFrames?.filter((f) => f.trackId === id) ?? []
|
||||
for (const f of frames) {
|
||||
const clonedFrame: ScriptFrame = {
|
||||
...(structuredClone(toRaw(f)) as ScriptFrame),
|
||||
id: uid(),
|
||||
trackId: newTrack.id,
|
||||
}
|
||||
;(scene.scriptFrames ||= []).push(clonedFrame)
|
||||
}
|
||||
if (scene.scriptFrames) scene.scriptFrames.sort((a, b) => a.time - b.time)
|
||||
placeAfter(id, newTrack.id)
|
||||
return newTrack.id
|
||||
}
|
||||
|
||||
return null
|
||||
},
|
||||
removeClipTrack(id: string) {
|
||||
if (this.scene.clipTracks) {
|
||||
this.scene.clipTracks = this.scene.clipTracks.filter((t) => t.id !== id)
|
||||
|
||||
Reference in new issue
Block a user