0.8.6: clip instances get stage transforms (x/y/scale/rotation)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
53c0410824
commit
d60684edd1
7 files changed
+512
-41
No files matched your search
@@ -73,6 +73,11 @@ interface State {
|
||||
* anchor. Used by group-selected / delete-selected and any
|
||||
* operation that needs the whole set. */
|
||||
selectedLayerIds: string[]
|
||||
/** Selected clip-instance id — drives the canvas transformer when a
|
||||
* packed clip is clicked on the stage. Mutually exclusive with
|
||||
* `selectedLayerId`: selecting a clip clears the layer selection
|
||||
* and vice versa. */
|
||||
selectedClipInstanceId: string | null
|
||||
playhead: number
|
||||
playing: boolean
|
||||
activeClipId: string | null
|
||||
@@ -268,6 +273,7 @@ export const useSceneStore = defineStore('scene', {
|
||||
scene: createBlankScene(),
|
||||
selectedLayerId: null,
|
||||
selectedLayerIds: [],
|
||||
selectedClipInstanceId: null,
|
||||
playhead: 0,
|
||||
playing: false,
|
||||
activeClipId: null,
|
||||
@@ -454,6 +460,14 @@ export const useSceneStore = defineStore('scene', {
|
||||
selectLayer(id: string | null) {
|
||||
this.selectedLayerId = id
|
||||
this.selectedLayerIds = id ? [id] : []
|
||||
if (id) this.selectedClipInstanceId = null
|
||||
},
|
||||
selectClipInstance(id: string | null) {
|
||||
this.selectedClipInstanceId = id
|
||||
if (id) {
|
||||
this.selectedLayerId = null
|
||||
this.selectedLayerIds = []
|
||||
}
|
||||
},
|
||||
/** Shift-click behaviour: add the layer to the selection if it's
|
||||
* not already there; otherwise remove it. The anchor moves to
|
||||
@@ -1808,6 +1822,49 @@ export const useSceneStore = defineStore('scene', {
|
||||
removeClipInstance(id: string) {
|
||||
if (!this.scene.clipInstances) return
|
||||
this.scene.clipInstances = this.scene.clipInstances.filter((ci) => ci.id !== id)
|
||||
if (this.selectedClipInstanceId === id) this.selectedClipInstanceId = null
|
||||
},
|
||||
/** Update the per-instance x / y / scaleX / scaleY. Missing fields
|
||||
* on the patch are left alone; clearing a field (setting it to
|
||||
* the default 0 / 1) prunes it from the stored object so the
|
||||
* JSON stays clean. The clip's own keyframes are untouched. */
|
||||
setClipInstanceTransform(
|
||||
id: string,
|
||||
patch: Partial<{
|
||||
x: number
|
||||
y: number
|
||||
scaleX: number
|
||||
scaleY: number
|
||||
rotation: number
|
||||
}>,
|
||||
) {
|
||||
const inst = this.scene.clipInstances?.find((ci) => ci.id === id)
|
||||
if (!inst) return
|
||||
if (patch.x !== undefined) {
|
||||
if (patch.x === 0) delete inst.x
|
||||
else inst.x = patch.x
|
||||
}
|
||||
if (patch.y !== undefined) {
|
||||
if (patch.y === 0) delete inst.y
|
||||
else inst.y = patch.y
|
||||
}
|
||||
if (patch.scaleX !== undefined) {
|
||||
if (patch.scaleX === 1) delete inst.scaleX
|
||||
else inst.scaleX = patch.scaleX
|
||||
}
|
||||
if (patch.scaleY !== undefined) {
|
||||
if (patch.scaleY === 1) delete inst.scaleY
|
||||
else inst.scaleY = patch.scaleY
|
||||
}
|
||||
if (patch.rotation !== undefined) {
|
||||
// Normalise to (-180, 180] so the stored value stays human-
|
||||
// readable and idempotent across multiple transform sessions.
|
||||
let r = patch.rotation % 360
|
||||
if (r > 180) r -= 360
|
||||
if (r <= -180) r += 360
|
||||
if (r === 0) delete inst.rotation
|
||||
else inst.rotation = r
|
||||
}
|
||||
},
|
||||
addTrackGroup(name?: string): TrackGroup {
|
||||
const group: TrackGroup = {
|
||||
|
||||
Reference in new issue
Block a user