Add output camera framing
This commit is contained in:
1 parent
616ced17ce
commit
23a66c6fdf
19 files changed
+1955
-43
No files matched your search
@@ -30,12 +30,14 @@ import {
|
||||
shouldRotateClipCopies,
|
||||
} from '@/lib/kaleido'
|
||||
import { drawButtonFrame, drawSceneFrame, loadSceneImages } from '@/lib/render'
|
||||
import { sampleCamera } from '@/lib/camera'
|
||||
import type {
|
||||
Action,
|
||||
AnimatableProps,
|
||||
Asset,
|
||||
ButtonAsset,
|
||||
ButtonState,
|
||||
CameraProps,
|
||||
ClipInstance,
|
||||
HitShape,
|
||||
Keyframe,
|
||||
@@ -762,6 +764,67 @@ const clipGroupConfig = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const cameraVisibleInEditor = computed(() => {
|
||||
if (store.activeClipId || store.activeButtonAssetId || store.activeSvgAssetId) return false
|
||||
const camera = store.scene.camera
|
||||
return !!camera && camera.overlayVisible !== false
|
||||
})
|
||||
|
||||
const cameraFrame = computed<CameraProps | null>(() => {
|
||||
if (!cameraVisibleInEditor.value) return null
|
||||
return sampleCamera(store.scene, store.playhead)
|
||||
})
|
||||
|
||||
const cameraFrameConfig = computed(() => {
|
||||
const frame = cameraFrame.value
|
||||
const camera = store.scene.camera
|
||||
if (!frame || !camera) return null
|
||||
const selected = store.selectedCamera
|
||||
return {
|
||||
id: 'camera-frame',
|
||||
name: 'camera-frame',
|
||||
x: frame.x,
|
||||
y: frame.y,
|
||||
width: frame.width,
|
||||
height: frame.height,
|
||||
fillEnabled: false,
|
||||
stroke: selected ? '#38bdf8' : '#0ea5e9',
|
||||
strokeWidth: (selected ? 2.5 : 1.5) / zoom.value,
|
||||
strokeScaleEnabled: false,
|
||||
dash: [10 / zoom.value, 6 / zoom.value],
|
||||
hitStrokeWidth: Math.max(10 / zoom.value, 8),
|
||||
listening: true,
|
||||
draggable: selected && !camera.locked,
|
||||
}
|
||||
})
|
||||
|
||||
function selectCameraFromStage(e?: Konva.KonvaEventObject<MouseEvent>) {
|
||||
if (e) e.cancelBubble = true
|
||||
store.selectCamera(true)
|
||||
}
|
||||
|
||||
function onCameraDragMove(e: Konva.KonvaEventObject<DragEvent>) {
|
||||
const camera = store.scene.camera
|
||||
if (!camera || camera.locked) return
|
||||
const node = e.target
|
||||
store.upsertCameraKeyframe(store.playhead, {
|
||||
x: Math.round(node.x()),
|
||||
y: Math.round(node.y()),
|
||||
})
|
||||
}
|
||||
|
||||
function onCameraDragEnd(e: Konva.KonvaEventObject<DragEvent>) {
|
||||
onCameraDragMove(e)
|
||||
}
|
||||
|
||||
function toggleCameraEnabled() {
|
||||
if (store.scene.camera?.enabled) {
|
||||
store.disableCamera()
|
||||
return
|
||||
}
|
||||
store.enableCamera()
|
||||
}
|
||||
|
||||
/** Horizontal + vertical centre-crosshair line configs. Null when
|
||||
* the toggle is off. Lines span the effective canvas so the centre
|
||||
* is exactly where layer keyframes default to (canvas.width/2,
|
||||
@@ -4723,6 +4786,13 @@ function onResizeHandlePointerUp(e: PointerEvent) {
|
||||
<v-line :config="centerCrosshairConfigs.horizontal" />
|
||||
<v-line :config="centerCrosshairConfigs.vertical" />
|
||||
</template>
|
||||
<v-rect
|
||||
v-if="cameraFrameConfig"
|
||||
:config="cameraFrameConfig"
|
||||
@mousedown="selectCameraFromStage"
|
||||
@dragmove="onCameraDragMove"
|
||||
@dragend="onCameraDragEnd"
|
||||
/>
|
||||
<v-rect
|
||||
v-for="h in canvasResizeHandles"
|
||||
:key="`canvas-resize-${h.edge}`"
|
||||
@@ -4926,6 +4996,14 @@ function onResizeHandlePointerUp(e: PointerEvent) {
|
||||
>
|
||||
<PhCursorClick :size="13" />
|
||||
</button>
|
||||
<button
|
||||
class="zc-btn camera-btn"
|
||||
:class="{ active: store.scene.camera?.enabled, selected: store.selectedCamera }"
|
||||
v-tooltip="store.scene.camera?.enabled ? t('canvas.cameraOff') : t('canvas.cameraOn')"
|
||||
@click="toggleCameraEnabled"
|
||||
>
|
||||
<PhFrameCorners :size="13" />
|
||||
</button>
|
||||
<button
|
||||
class="zc-btn motion-paths-btn"
|
||||
:class="{ active: showMotionPaths }"
|
||||
|
||||
Reference in new issue
Block a user