|
66 | 66 | let justFinishedDrag = false; // Used to prevent click events after a drag |
67 | 67 | let dragInPanel = false; |
68 | 68 |
|
| 69 | + // Alt+Drag duplication |
| 70 | + let altKeyPressedDuringDrag = false; |
| 71 | + let originalLayersBeforeDuplication: bigint[] | undefined = undefined; |
| 72 | + let duplicatedLayerIds: bigint[] | undefined = undefined; |
| 73 | +
|
69 | 74 | // Interactive clipping |
70 | 75 | let layerToClipUponClick: LayerListingInfo | undefined = undefined; |
71 | 76 | let layerToClipAltKeyPressed = false; |
|
107 | 112 | addEventListener("pointermove", draggingPointerMove); |
108 | 113 | addEventListener("mousedown", draggingMouseDown); |
109 | 114 | addEventListener("keydown", draggingKeyDown); |
| 115 | + addEventListener("keyup", draggingKeyUp); |
| 116 | + addEventListener("blur", () => internalDragState?.active && abortDrag()); |
110 | 117 |
|
111 | 118 | addEventListener("pointermove", clippingHover); |
112 | 119 | addEventListener("keydown", clippingKeyPress); |
|
124 | 131 | removeEventListener("pointermove", draggingPointerMove); |
125 | 132 | removeEventListener("mousedown", draggingMouseDown); |
126 | 133 | removeEventListener("keydown", draggingKeyDown); |
| 134 | + removeEventListener("keyup", draggingKeyUp); |
127 | 135 |
|
128 | 136 | removeEventListener("pointermove", clippingHover); |
129 | 137 | removeEventListener("keydown", clippingKeyPress); |
|
469 | 477 | abortDrag(); |
470 | 478 | } |
471 | 479 |
|
| 480 | + async function startDuplicates() { |
| 481 | + originalLayersBeforeDuplication = [...$nodeGraph.selected]; |
| 482 | + editor.handle.duplicateSelectedLayers(); |
| 483 | + |
| 484 | + await tick(); |
| 485 | + duplicatedLayerIds = [...$nodeGraph.selected]; |
| 486 | + } |
| 487 | +
|
| 488 | + function stopDuplicates() { |
| 489 | + if (!originalLayersBeforeDuplication || !duplicatedLayerIds) return; |
| 490 | +
|
| 491 | + duplicatedLayerIds.forEach(layerId => { |
| 492 | + editor.handle.deleteNode(layerId); |
| 493 | + }); |
| 494 | +
|
| 495 | + editor.handle.deselectAllLayers(); |
| 496 | + originalLayersBeforeDuplication.forEach((layerId, index) => { |
| 497 | + const ctrl = index > 0; |
| 498 | + editor.handle.selectLayer(layerId, ctrl, false); |
| 499 | + }); |
| 500 | +
|
| 501 | + originalLayersBeforeDuplication = undefined; |
| 502 | + duplicatedLayerIds = undefined; |
| 503 | + } |
| 504 | +
|
472 | 505 | function abortDrag() { |
| 506 | + if (altKeyPressedDuringDrag && originalLayersBeforeDuplication) { |
| 507 | + stopDuplicates(); |
| 508 | + } |
| 509 | +
|
473 | 510 | internalDragState = undefined; |
474 | 511 | draggingData = undefined; |
475 | 512 | fakeHighlightOfNotYetSelectedLayerBeingDragged = undefined; |
476 | 513 | dragInPanel = false; |
| 514 | + altKeyPressedDuringDrag = false; |
| 515 | + originalLayersBeforeDuplication = undefined; |
| 516 | + duplicatedLayerIds = undefined; |
477 | 517 | } |
478 | 518 |
|
479 | 519 | function draggingMouseDown(e: MouseEvent) { |
|
489 | 529 | justFinishedDrag = true; |
490 | 530 | abortDrag(); |
491 | 531 | } |
| 532 | +
|
| 533 | + if (e.key === "Alt" && !altKeyPressedDuringDrag) { |
| 534 | + altKeyPressedDuringDrag = true; |
| 535 | + startDuplicates(); |
| 536 | + } |
| 537 | + } |
| 538 | +
|
| 539 | + function draggingKeyUp(e: KeyboardEvent) { |
| 540 | + if (e.key === "Alt" && altKeyPressedDuringDrag) { |
| 541 | + altKeyPressedDuringDrag = false; |
| 542 | + stopDuplicates(); |
| 543 | + } |
492 | 544 | } |
493 | 545 |
|
494 | 546 | function fileDragOver(e: DragEvent) { |
|
0 commit comments