{ "version": 3, "sources": ["../../../../../src/lib/tools/SelectTool/children/ScribbleBrushing.ts"], "sourcesContent": ["import {\n\tGeometry2d,\n\tHIT_TEST_MARGIN,\n\tStateNode,\n\tTLEventHandlers,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLScribble,\n\tTLShape,\n\tTLShapeId,\n\tVec2d,\n\tintersectLineSegmentPolyline,\n\tpointInPolygon,\n} from '@tldraw/editor'\nimport { ScribbleManager } from '../../../shapes/shared/ScribbleManager'\n\nexport class ScribbleBrushing extends StateNode {\n\tstatic override id = 'scribble_brushing'\n\n\thits = new Set()\n\n\tsize = 0\n\n\tscribble = {} as ScribbleManager\n\n\tinitialSelectedShapeIds = new Set()\n\tnewlySelectedShapeIds = new Set()\n\n\toverride onEnter = () => {\n\t\tthis.initialSelectedShapeIds = new Set(\n\t\t\tthis.editor.inputs.shiftKey ? this.editor.selectedShapeIds : []\n\t\t)\n\t\tthis.newlySelectedShapeIds = new Set()\n\t\tthis.size = 0\n\t\tthis.hits.clear()\n\n\t\tthis.startScribble()\n\n\t\tthis.updateScribbleSelection(true)\n\n\t\trequestAnimationFrame(() => {\n\t\t\tthis.editor.updateInstanceState({ brush: null })\n\t\t})\n\t}\n\n\toverride onExit = () => {\n\t\tthis.scribble.stop()\n\t}\n\n\toverride onPointerMove = () => {\n\t\tthis.updateScribbleSelection(true)\n\t}\n\n\toverride onPointerUp = () => {\n\t\tthis.complete()\n\t}\n\n\toverride onKeyDown = () => {\n\t\tthis.updateScribbleSelection(false)\n\t}\n\n\toverride onKeyUp = () => {\n\t\tif (!this.editor.inputs.altKey) {\n\t\t\tthis.parent.transition('brushing', {})\n\t\t} else {\n\t\t\tthis.updateScribbleSelection(false)\n\t\t}\n\t}\n\n\toverride onCancel: TLEventHandlers['onCancel'] = () => {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete: TLEventHandlers['onComplete'] = () => {\n\t\tthis.complete()\n\t}\n\n\tprivate startScribble = () => {\n\t\tif (this.scribble.tick) {\n\t\t\tthis.editor.off('tick', this.scribble?.tick)\n\t\t}\n\n\t\tthis.scribble = new ScribbleManager({\n\t\t\tonUpdate: this.onScribbleUpdate,\n\t\t\tonComplete: this.onScribbleComplete,\n\t\t\tcolor: 'selection-stroke',\n\t\t\topacity: 0.32,\n\t\t\tsize: 12,\n\t\t})\n\n\t\tthis.editor.on('tick', this.scribble.tick)\n\t}\n\n\tprivate pushPointToScribble = () => {\n\t\tconst { x, y } = this.editor.inputs.currentPagePoint\n\t\tthis.scribble.addPoint(x, y)\n\t}\n\n\tprivate onScribbleUpdate = (scribble: TLScribble) => {\n\t\tthis.editor.updateInstanceState({ scribble })\n\t}\n\n\tprivate onScribbleComplete = () => {\n\t\tthis.editor.off('tick', this.scribble.tick)\n\t\tthis.editor.updateInstanceState({ scribble: null })\n\t}\n\n\tprivate updateScribbleSelection(addPoint: boolean) {\n\t\tconst {\n\t\t\tzoomLevel,\n\t\t\tcurrentPageShapes: currentPageShapes,\n\t\t\tinputs: { shiftKey, originPagePoint, previousPagePoint, currentPagePoint },\n\t\t} = this.editor\n\n\t\tconst { newlySelectedShapeIds, initialSelectedShapeIds } = this\n\n\t\tif (addPoint) {\n\t\t\tthis.pushPointToScribble()\n\t\t}\n\n\t\tconst shapes = currentPageShapes\n\t\tlet shape: TLShape, geometry: Geometry2d, A: Vec2d, B: Vec2d\n\n\t\tfor (let i = 0, n = shapes.length; i < n; i++) {\n\t\t\tshape = shapes[i]\n\t\t\tgeometry = this.editor.getShapeGeometry(shape)\n\n\t\t\t// If the shape is a group or is already selected or locked, don't select it\n\t\t\tif (\n\t\t\t\tthis.editor.isShapeOfType(shape, 'group') ||\n\t\t\t\tnewlySelectedShapeIds.has(shape.id) ||\n\t\t\t\tthis.editor.isShapeOrAncestorLocked(shape)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// If the scribble started inside of the frame, don't select it\n\t\t\tif (this.editor.isShapeOfType(shape, 'frame')) {\n\t\t\t\tconst point = this.editor.getPointInShapeSpace(shape, originPagePoint)\n\t\t\t\tif (geometry.bounds.containsPoint(point)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tA = this.editor.getPointInShapeSpace(shape, previousPagePoint)\n\t\t\tB = this.editor.getPointInShapeSpace(shape, currentPagePoint)\n\t\t\tif (geometry.hitTestLineSegment(A, B, HIT_TEST_MARGIN / zoomLevel)) {\n\t\t\t\tconst outermostShape = this.editor.getOutermostSelectableShape(shape)\n\n\t\t\t\tconst pageMask = this.editor.getShapeMask(outermostShape.id)\n\n\t\t\t\tif (pageMask) {\n\t\t\t\t\tconst intersection = intersectLineSegmentPolyline(\n\t\t\t\t\t\tpreviousPagePoint,\n\t\t\t\t\t\tcurrentPagePoint,\n\t\t\t\t\t\tpageMask\n\t\t\t\t\t)\n\t\t\t\t\tif (intersection !== null) {\n\t\t\t\t\t\tconst isInMask = pointInPolygon(currentPagePoint, pageMask)\n\t\t\t\t\t\tif (!isInMask) continue\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tnewlySelectedShapeIds.add(outermostShape.id)\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setSelectedShapes(\n\t\t\t[\n\t\t\t\t...new Set(\n\t\t\t\t\tshiftKey\n\t\t\t\t\t\t? [...newlySelectedShapeIds, ...initialSelectedShapeIds]\n\t\t\t\t\t\t: [...newlySelectedShapeIds]\n\t\t\t\t),\n\t\t\t],\n\t\t\t{ squashing: true }\n\t\t)\n\t}\n\n\tprivate complete() {\n\t\tthis.parent.transition('idle', {})\n\t}\n\n\tprivate cancel() {\n\t\tthis.editor.setSelectedShapes([...this.initialSelectedShapeIds], { squashing: true })\n\t\tthis.parent.transition('idle', {})\n\t}\n}\n"], "mappings": "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", "names": [] }