1515 :panzoom-transform =" panzoomTransform"
1616 :interactive =" isOverlayInteractive"
1717 :wheel-target =" mainMediaElement"
18- v-show =" isAnnotationsDisplayed"
18+ v-show ="
19+ isAnnotationsDisplayed &&
20+ (isMovie || isPicture) &&
21+ mainMediaElement
22+ "
1923 @click =" onCanvasClicked"
2024 @resized =" onMainCanvasResized"
2125 />
3034 isAnnotationsDisplayed &&
3135 isComparing &&
3236 previewToCompare &&
33- !isComparisonOverlay
37+ !isComparisonOverlay &&
38+ (isMovie || isPicture) &&
39+ comparisonMediaElement
3440 "
3541 @click =" onCanvasClicked"
3642 @resized =" onComparisonCanvasResized"
215221 v-model:current-background =" currentBackground"
216222 v-model:current-shape =" currentShape"
217223 v-model:is-environment-skybox =" isEnvironmentSkybox"
224+ v-model:is-eraser-mode-on =" isEraserModeOn"
218225 v-model:is-shape-mode =" isShapeMode"
219226 v-model:is-wireframe =" isWireframe"
220227 @annotation-displayed-clicked =" onAnnotationDisplayedClicked"
224231 @change-text-color =" onChangeTextColor"
225232 @comment-clicked =" onCommentClicked"
226233 @delete-clicked =" onDeleteClicked"
234+ @erase-clicked =" onEraseClicked"
227235 @object-background-selected =" onObjectBackgroundSelected"
228236 @pencil-annotate-clicked =" onPencilAnnotateClicked"
229237 @redo =" redoLastAction"
@@ -650,6 +658,7 @@ const {
650658 currentShape ,
651659 deleteSelection ,
652660 isShapeMode ,
661+ isEraserModeOn ,
653662 isWriting ,
654663 getNewAnnotations ,
655664 loadSingleAnnotation ,
@@ -1213,17 +1222,32 @@ const onPencilAnnotateClicked = () => {
12131222 _resetPencil ()
12141223 isShapeMode .value = false
12151224 isTyping .value = false
1225+ isEraserModeOn .value = false
12161226 isDrawing .value = true
12171227 }
12181228}
12191229
1230+ // Eraser is a fourth mutually-exclusive tool. The wrapper clears the
1231+ // player-owned mode refs on entry, then delegates the brush swap and the
1232+ // isEraserModeOn toggle to the composable.
1233+ const onEraseClicked = () => {
1234+ clearFocus ()
1235+ if (! isEraserModeOn .value ) {
1236+ isDrawing .value = false
1237+ isShapeMode .value = false
1238+ isTyping .value = false
1239+ }
1240+ annotation .onEraseClicked ()
1241+ }
1242+
12201243const onTypeClicked = () => {
12211244 clearFocus ()
12221245 if (isTyping .value ) {
12231246 isTyping .value = false
12241247 } else {
12251248 isDrawing .value = false
12261249 isShapeMode .value = false
1250+ isEraserModeOn .value = false
12271251 isTyping .value = true
12281252 }
12291253}
@@ -1235,6 +1259,7 @@ const onShapeModeClicked = () => {
12351259 if (isShapeMode .value ) {
12361260 isDrawing .value = false
12371261 isTyping .value = false
1262+ isEraserModeOn .value = false
12381263 if (! isAnnotationsDisplayed .value ) isAnnotationsDisplayed .value = true
12391264 }
12401265}
@@ -1468,12 +1493,15 @@ const extractPicturePreviewSnapshots = async ({ withLabel = false } = {}) => {
14681493 for (const { preview , index } of picturePreviews) {
14691494 if (currentIndex .value !== index) {
14701495 currentIndex .value = index
1471- // Wait for the picture to swap and annotations to reload. The
1472- // chain is async (image load -> resetPlayerPositions ->
1473- // AnnotationCanvas resized -> reloadAnnotations) so a single tick
1474- // isn't enough.
1475- await new Promise (resolve => setTimeout (resolve, 500 ))
14761496 }
1497+ // Always wait for the picture to load and the live canvas to
1498+ // settle before compositing. Iteration #1 often skips the index
1499+ // switch (the user is already on the main preview), but the chain
1500+ // is async (image load -> resetPlayerPositions -> AnnotationCanvas
1501+ // resized -> reloadAnnotations) and composite would otherwise
1502+ // capture an empty live canvas, producing a PNG without any
1503+ // annotation.
1504+ await new Promise (resolve => setTimeout (resolve, 500 ))
14771505 const canvas = document .getElementById (' annotation-snapshot' )
14781506 previewViewer .value .extractPicture (canvas)
14791507 await compositeLiveAnnotationsOntoCanvas (canvas)
@@ -1536,6 +1564,10 @@ const { isAltHeld } = usePreviewShortcuts({
15361564 container .value .focus ()
15371565 onPencilAnnotateClicked ()
15381566 },
1567+ onErase : () => {
1568+ container .value .focus ()
1569+ onEraseClicked ()
1570+ },
15391571 onUndo : () => undoLastAction (),
15401572 onRedo : () => redoLastAction (),
15411573 onPrevPreview : () => onPreviousClicked (),
@@ -1549,7 +1581,9 @@ const { cursor: annotationCursor } = useAnnotationCursor({
15491581 isAltHeld,
15501582 isDrawing,
15511583 isTyping,
1552- isShapeMode
1584+ isShapeMode,
1585+ isEraserModeOn,
1586+ pencilWidth
15531587})
15541588
15551589const onCommentClicked = () => {
@@ -1875,6 +1909,7 @@ watch(isTyping, () => {
18751909watch (isAnnotationsDisplayed, () => {
18761910 if (! isAnnotationsDisplayed .value ) {
18771911 isDrawing .value = false
1912+ if (isEraserModeOn .value ) onEraseClicked ()
18781913 }
18791914})
18801915
0 commit comments