diff --git a/src/js/window/storyboarder-sketch-pane.js b/src/js/window/storyboarder-sketch-pane.js index ffa55c19f9..f88843dd65 100644 --- a/src/js/window/storyboarder-sketch-pane.js +++ b/src/js/window/storyboarder-sketch-pane.js @@ -247,6 +247,7 @@ class StoryboarderSketchPane extends EventEmitter { onSketchPaneOnUp (...args) { // quick erase : off this.unsetQuickErase() + this.unsetQuickResize() this.emit('onup', ...args) @@ -286,6 +287,9 @@ class StoryboarderSketchPane extends EventEmitter { if (!keytracker('') && !this.isEraseButtonActive) { this.unsetQuickErase() } + if (keytracker('')) { + this.unsetQuickResize() + } } } @@ -368,7 +372,13 @@ class StoryboarderSketchPane extends EventEmitter { // render the cursor if (this.lastCursorEvent && this.brushPointerContainer && this.brushPointerContainer.style) { // update the position of the cursor - this.brushPointerContainer.style.transform = 'translate(' + this.lastCursorEvent.clientX + 'px, ' + this.lastCursorEvent.clientY + 'px)' + // If using quick resize, draw the cursor at the start position instead of the current mouse position + if (this.toolbar.getIsQuickResizing()) { + let clientStartPos = this.getAbsolutePosition(this.strategy.startAt.x, this.strategy.startAt.y) + this.brushPointerContainer.style.transform = 'translate(' + clientStartPos.x + 'px, ' + clientStartPos.y + 'px)' + } else { + this.brushPointerContainer.style.transform = 'translate(' + this.lastCursorEvent.clientX + 'px, ' + this.lastCursorEvent.clientY + 'px)' + } this.lastCursorEvent = null } @@ -403,6 +413,18 @@ class StoryboarderSketchPane extends EventEmitter { } } + setQuickResizeIfRequested () { + if (keytracker('')) { + this.toolbar.setIsQuickResizing(true) + } + } + + unsetQuickResize () { + if (this.toolbar.getIsQuickResizing()) { + this.toolbar.setIsQuickResizing(false) + } + } + startMultiLayerOperation () { // if (this.isMultiLayerOperation) return this.isMultiLayerOperation = true @@ -498,6 +520,21 @@ class StoryboarderSketchPane extends EventEmitter { } } + // Inverse getRelativePosition, i.e. given a point relative to the sketchPane + // return an absolute position in the window + getAbsolutePosition (relativeX, relativeY) { + let rect = this.boundingClientRect + let scaleFactorX = this.canvasSize[0] / rect.width + let scaleFactorY = this.canvasSize[1] / rect.height + + let rectOnCanvas = {x: relativeX / scaleFactorX, y: relativeY / scaleFactorY} + + return { + x: rectOnCanvas.x + rect.left, + y: rectOnCanvas.y + rect.top + } + } + fit (frameSize, imageSize) { const frameAspectRatio = frameSize[0] / frameSize[1] const imageAspectRatio = imageSize[0] / imageSize[1] @@ -782,6 +819,10 @@ class StoryboarderSketchPane extends EventEmitter { class DrawingStrategy { constructor (container) { this.container = container + + // For quick resize + this.startAt = null + this.startBrushSize = null } canvasPointerDown (e) { @@ -800,6 +841,8 @@ class DrawingStrategy { // quick erase : on this.container.setQuickEraseIfRequested() + this.container.setQuickResizeIfRequested() + if (!this.container.toolbar.getIsQuickErasing() && this.container.sketchPane.getPaintingKnockout()) { this.container.startMultiLayerOperation() this.container.setCompositeLayerVisibility(true) @@ -807,7 +850,12 @@ class DrawingStrategy { let pointerPosition = this.container.getRelativePosition(e.clientX, e.clientY) this.container.lineMileageCounter.reset() - this.container.sketchPane.down(pointerPosition.x, pointerPosition.y, e.pointerType === "pen" ? e.pressure : 1) + if (this.container.toolbar.getIsQuickResizing()) { + this.startAt = {x: pointerPosition.x, y: pointerPosition.y} + this.startBrushSize = this.container.brush.getSize() + } else { + this.container.sketchPane.down(pointerPosition.x, pointerPosition.y, e.pointerType === "pen" ? e.pressure : 1) + } document.addEventListener('pointermove', this.container.canvasPointerMove) document.addEventListener('pointerup', this.container.canvasPointerUp) this.container.emit('pointerdown', pointerPosition.x, pointerPosition.y, e.pointerType === "pen" ? e.pressure : 1, e.pointerType) @@ -829,15 +877,31 @@ class DrawingStrategy { this.container.lastMoveEvent = null this.container.lastCursorEvent = null + this.startAt = null + this.startBrushSize = null + let pointerPosition = this.container.getRelativePosition(e.clientX, e.clientY) - this.container.sketchPane.up(pointerPosition.x, pointerPosition.y, e.pointerType === "pen" ? e.pressure : 1) + if (!this.container.toolbar.getIsQuickResizing()) { + this.container.sketchPane.up(pointerPosition.x, pointerPosition.y, e.pointerType === "pen" ? e.pressure : 1) + } this.container.emit('lineMileage', this.container.lineMileageCounter.get()) document.removeEventListener('pointermove', this.container.canvasPointerMove) document.removeEventListener('pointerup', this.container.canvasPointerUp) + + this.container.unsetQuickResize(); } renderMoveEvent (moveEvent) { - this.container.sketchPane.move(moveEvent.x, moveEvent.y, moveEvent.pointerType === "pen" ? moveEvent.pressure : 1) + // If quick resizing (ctrl+click when pointer went down), override move handler + if (this.container.toolbar.getIsQuickResizing()) { + let dx = moveEvent.x - this.startAt.x + this.startBrushSize + let dy = moveEvent.y - this.startAt.y + let length = Math.sqrt(dx * dx + dy * dy) + this.container.toolbar.setBrushSize(length) + } + else { + this.container.sketchPane.move(moveEvent.x, moveEvent.y, moveEvent.pointerType === "pen" ? moveEvent.pressure : 1) + } } startMultiLayerOperation () { diff --git a/src/js/window/toolbar.js b/src/js/window/toolbar.js index e4557899c2..8a473aaa4b 100644 --- a/src/js/window/toolbar.js +++ b/src/js/window/toolbar.js @@ -23,6 +23,7 @@ const initialState = { brush: null, isQuickErasing: false, + isQuickResizing: false, brushes: { [BRUSH_PENCIL]: { @@ -142,6 +143,10 @@ class Toolbar extends EventEmitter { this.state = initialState } + // Do not recover isQuickResizing from saved toolbarState + // (Ths is a temporary state) + this.isQuickResizing = initialState.isQuickResizing; + this.el = el this.swatchTimer = null @@ -170,8 +175,6 @@ class Toolbar extends EventEmitter { } changeBrushSize (direction, fine = false) { - let min = 1 - let max = 256 let currSize = this.state.brushes[this.state.brush].size if (fine) { @@ -184,10 +187,17 @@ class Toolbar extends EventEmitter { } } - if (currSize < min) currSize = min - if (currSize > max) currSize = max + setBrushSize (currSize) + } + + setBrushSize (size) { + let min = 1 + let max = 256 + + if (size < min) size = min + if (size > max) size = max - this.state.brushes[this.state.brush].size = currSize + this.state.brushes[this.state.brush].size = size this.emit('brush:size', this.getBrushOptions().size) this.render() @@ -201,6 +211,15 @@ class Toolbar extends EventEmitter { this.state.isQuickErasing = value } + getIsQuickResizing () { + return this.state.isQuickResizing + } + + setIsQuickResizing (value) { + console.log("setIsQuickResizing: " + value) + this.state.isQuickResizing = value + } + changeCurrentColor (color) { if (this.getIsQuickErasing()) return