From 944cf1fbed59c184664de48058a994342773d1c3 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Mon, 20 Apr 2020 16:55:34 +0200 Subject: [PATCH 1/7] Implement cut tool yeah that was the easy part but still - Added hotkeys for copy, paste and cut - Added _copyPaste.js for copy, cut and paste management --- js/_copyPaste.js | 21 +++++++++++++++++++++ js/_hotkeyListener.js | 38 ++++++++++++++++++++++++++++++++++++++ js/_mouseEvents.js | 2 +- js/_move.js | 6 +++--- js/_rectSelect.js | 3 ++- js/_tools.js | 2 +- js/_updateCursor.js | 5 ++--- js/pixel-editor.js | 1 + 8 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 js/_copyPaste.js diff --git a/js/_copyPaste.js b/js/_copyPaste.js new file mode 100644 index 0000000..7f19b68 --- /dev/null +++ b/js/_copyPaste.js @@ -0,0 +1,21 @@ +let clipboardData; + +function copySelection() { + +} + +function pasteSelection() { + imageDataToMove = clipboardData; + updateMovePreview(); +} + +function cutSelectionTool() { + // Getting the selected pixels + clipBoardData = currentLayer.context.getImageData(startX, startY, endX - startX + 1, endY - startY + 1); + + currentLayer.context.clearRect(startX - 0.5, startY - 0.5, endX - startX + 1, endY - startY + 1); + // Moving those pixels from the current layer to the tmp layer + //TMPLayer.context.putImageData(imageDataToMove, startX + 1, startY); + + //originalDataPosition = [currentPos[0], currentPos[1]]; +} \ No newline at end of file diff --git a/js/_hotkeyListener.js b/js/_hotkeyListener.js index 47c82e5..1175f4c 100644 --- a/js/_hotkeyListener.js +++ b/js/_hotkeyListener.js @@ -1,5 +1,21 @@ var spacePressed = false; +/** + Copy / paste / cut logic: + - The user selects an area + - Pressing ctrl+c copies the selection + - Pressing ctrl+v ends the current selection and copies the clipboard in the tmp layer: + the editor enters move mode and lets the user move the copied selection around. + Pressing ctrl+v while moving a copy has the same effect of pressing ctrl+v after a ctrl+c + - Pressing ctrl+x cuts the selection and stores it in the clipboard + - The behaviour of ctrl+v is the same and doesn't depend on how the selected area was obtained + (with ctrl+c or with ctrl+v) + - Selecting a different tool while moving the copied or cut selection has the same effect of selecting + a different tool while moving a standard selection + - You can't paste while dragging + - You can paste at any other time +*/ + function KeyPress(e) { var keyboardEvent = window.event? event : e; @@ -24,6 +40,13 @@ function KeyPress(e) { case 49: case 66: tool.pencil.switchTo(); break; + // copy tool c + case 67: case 99: + console.log("Copying"); + if (keyboardEvent.ctrlKey && !dragging && currentTool.name == 'moveselection') { + copySelection(); + } + break; //fill tool - 2, f case 50: case 70: tool.fill.switchTo(); @@ -49,6 +72,21 @@ function KeyPress(e) { case 77: case 109: tool.rectselect.switchTo() break; + // Paste tool + case 86: case 118: + console.log("Pasting"); + if (keyboardEvent.ctrlKey && !dragging) { + pasteSelection(); + } + break; + case 88: case 120: + console.log("Cutting"); + if (keyboardEvent.ctrlKey && !dragging && currentTool.name == 'moveselection') { + cutSelectionTool(); + endSelection(); + tool.pencil.switchTo(); + } + break; //Z case 90: console.log('PRESSED Z ', keyboardEvent.ctrlKey) diff --git a/js/_mouseEvents.js b/js/_mouseEvents.js index fa62a34..5b9cb07 100644 --- a/js/_mouseEvents.js +++ b/js/_mouseEvents.js @@ -355,7 +355,7 @@ function draw (mouseEvent) { // If I'm dragging, I move the preview if (dragging && cursorInSelectedArea()) { - updateMovePreview(mouseEvent); + updateMovePreview(getCursorPosition(mouseEvent)); } } } diff --git a/js/_move.js b/js/_move.js index ae98086..5695527 100644 --- a/js/_move.js +++ b/js/_move.js @@ -6,17 +6,17 @@ var selectionCanceled = true; var firstTimeMove = true; // TODO: move with arrows -function updateMovePreview(mouseEvent) { +function updateMovePreview(mousePosition) { // ISSUE selectionCanceled = false; if (firstTimeMove) { - cutSelection(mouseEvent); + cutSelection(mousePosition); } firstTimeMove = false; - lastMousePos = getCursorPosition(mouseEvent); + lastMousePos = mousePosition; // clear the entire tmp layer TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height); // put the image data with offset diff --git a/js/_rectSelect.js b/js/_rectSelect.js index 236f92c..60e9b06 100644 --- a/js/_rectSelect.js +++ b/js/_rectSelect.js @@ -72,10 +72,11 @@ function endRectSelection(mouseEvent) { currentTool.updateCursor(); } -function cutSelection(mouseEvent) { +function cutSelection(mousePosition) { console.log("Coordinate: start x, y: " + startX + ", " + startY + " end x, y: " + endX + ", " + endY); // Getting the selected pixels imageDataToMove = currentLayer.context.getImageData(startX, startY, endX - startX + 1, endY - startY + 1); + clipBoardData = imageDataToMove; currentLayer.context.clearRect(startX - 0.5, startY - 0.5, endX - startX + 1, endY - startY + 1); // Moving those pixels from the current layer to the tmp layer diff --git a/js/_tools.js b/js/_tools.js index f7cca56..160dd88 100644 --- a/js/_tools.js +++ b/js/_tools.js @@ -48,7 +48,7 @@ class Tool { endSelection(); } - //set tool and temp tje tje tpp; + //set tool and temp tje tje tpp <--- he's speaking the language of the gods, don't delete currentTool = this; currentToolTemp = this; diff --git a/js/_updateCursor.js b/js/_updateCursor.js index bda3ec7..bbd207f 100644 --- a/js/_updateCursor.js +++ b/js/_updateCursor.js @@ -2,15 +2,14 @@ //set the correct cursor for the current tool Tool.prototype.updateCursor = function () { - - console.log('updateCursor()', currentTool) + //console.log('updateCursor()', currentTool) //switch to that tools cursor canvasView.style.cursor = this.cursor || 'default'; //if the tool uses a brush preview, make it visible and update the size if (this.brushPreview) { - console.log('brush size',this.currentBrushSize) + //console.log('brush size',this.currentBrushSize) brushPreview.style.display = 'block'; brushPreview.style.width = this.currentBrushSize * zoom + 'px'; brushPreview.style.height = this.currentBrushSize * zoom + 'px'; diff --git a/js/pixel-editor.js b/js/pixel-editor.js index efb03b7..2c35eff 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -42,6 +42,7 @@ //=include _replaceAllOfColor.js //=include _checkerboard.js //=include _layer.js +//=include _copyPaste.js /**load file**/ //=include _loadImage.js From 12e43e044952395cdadaa5c4fa9b250f366b54ef Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Mon, 20 Apr 2020 19:26:00 +0200 Subject: [PATCH 2/7] Continued cut -> paste implementation There's only a bug, when pasting consecutively, every time it cuts the area again. There's probably some weird cut call somewhere. --- js/_copyPaste.js | 57 +++++++++++++++++++++++++++++++++++++++---- js/_hotkeyListener.js | 9 +++---- js/_move.js | 4 +++ js/_rectSelect.js | 3 +-- js/_tools.js | 7 ++++-- 5 files changed, 65 insertions(+), 15 deletions(-) diff --git a/js/_copyPaste.js b/js/_copyPaste.js index 7f19b68..bae215a 100644 --- a/js/_copyPaste.js +++ b/js/_copyPaste.js @@ -1,19 +1,66 @@ let clipboardData; +let isPasting = false; + +let copiedStartX; +let copiedStartY; +let copiedEndX; +let copiedEndY; function copySelection() { - + /* + copiedEndX = endX; + copiedEndY = endY; + + copiedStartX = startX; + copiedStartY = startY; +*/ + // Getting the selected pixels + clipboardData = currentLayer.context.getImageData(startX, startY, endX - startX + 1, endY - startY + 1); } function pasteSelection() { + isPasting = true; + // Putting the image data on the tmp layer + TMPLayer.context.putImageData(clipboardData, copiedStartX, copiedStartY); + + // Setting up the move tool to move the pasted value + selectionCanceled = false; imageDataToMove = clipboardData; - updateMovePreview(); + firstTimeMove = false; + isRectSelecting = false; + + // Switching to the move tool + tool.moveselection.switchTo(); + // Updating the rectangle preview + moveSelection( + copiedStartX + (copiedEndX - copiedStartX) / 2, + copiedStartY + (copiedEndY - copiedStartY) / 2, + imageDataToMove.width, imageDataToMove.height); + //drawRect(copiedStartX, copiedEndX, copiedStartY, copiedEndY); } function cutSelectionTool() { - // Getting the selected pixels - clipBoardData = currentLayer.context.getImageData(startX, startY, endX - startX + 1, endY - startY + 1); + // Saving the canvas + new HistoryStateEditCanvas(); - currentLayer.context.clearRect(startX - 0.5, startY - 0.5, endX - startX + 1, endY - startY + 1); + copiedEndX = endX; + copiedEndY = endY; + + copiedStartX = startX; + copiedStartY = startY; + + // Getting the selected pixels + if (imageDataToMove !== undefined) { + clipboardData = imageDataToMove; + TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height); + imageDataToMove = undefined; + } + else { + clipboardData = currentLayer.context.getImageData(startX, startY, endX - startX + 1, endY - startY + 1); + currentLayer.context.clearRect(startX - 0.5, startY - 0.5, endX - startX + 1, endY - startY + 1); + } + + // Moving those pixels from the current layer to the tmp layer //TMPLayer.context.putImageData(imageDataToMove, startX + 1, startY); diff --git a/js/_hotkeyListener.js b/js/_hotkeyListener.js index 1175f4c..c0dec89 100644 --- a/js/_hotkeyListener.js +++ b/js/_hotkeyListener.js @@ -7,13 +7,14 @@ var spacePressed = false; - Pressing ctrl+v ends the current selection and copies the clipboard in the tmp layer: the editor enters move mode and lets the user move the copied selection around. Pressing ctrl+v while moving a copy has the same effect of pressing ctrl+v after a ctrl+c - - Pressing ctrl+x cuts the selection and stores it in the clipboard - The behaviour of ctrl+v is the same and doesn't depend on how the selected area was obtained (with ctrl+c or with ctrl+v) - Selecting a different tool while moving the copied or cut selection has the same effect of selecting a different tool while moving a standard selection - - You can't paste while dragging - You can paste at any other time + + BUGS: + - */ function KeyPress(e) { @@ -30,7 +31,6 @@ function KeyPress(e) { // if (e.key === "Escape") { if (!selectionCanceled) { - endSelection(); tool.pencil.switchTo(); } } @@ -83,7 +83,6 @@ function KeyPress(e) { console.log("Cutting"); if (keyboardEvent.ctrlKey && !dragging && currentTool.name == 'moveselection') { cutSelectionTool(); - endSelection(); tool.pencil.switchTo(); } break; @@ -94,14 +93,12 @@ function KeyPress(e) { if (keyboardEvent.altKey && keyboardEvent.ctrlKey) redo(); if (!selectionCanceled) { - endSelection(); tool.pencil.switchTo() } //CTRL+Z undo else if (keyboardEvent.ctrlKey) { undo(); if (!selectionCanceled) { - endSelection(); tool.pencil.switchTo() } } diff --git a/js/_move.js b/js/_move.js index 5695527..cff6c21 100644 --- a/js/_move.js +++ b/js/_move.js @@ -63,10 +63,14 @@ function endSelection() { Math.round(lastMovePos[0] / zoom - imageDataToMove.width / 2), Math.round(lastMovePos[1] / zoom - imageDataToMove.height / 2)); } + else { + undo(); + } } selectionCanceled = true; isRectSelecting = false; firstTimeMove = true; imageDataToMove = undefined; + isPasting = false; } \ No newline at end of file diff --git a/js/_rectSelect.js b/js/_rectSelect.js index 60e9b06..ce38571 100644 --- a/js/_rectSelect.js +++ b/js/_rectSelect.js @@ -76,8 +76,7 @@ function cutSelection(mousePosition) { console.log("Coordinate: start x, y: " + startX + ", " + startY + " end x, y: " + endX + ", " + endY); // Getting the selected pixels imageDataToMove = currentLayer.context.getImageData(startX, startY, endX - startX + 1, endY - startY + 1); - clipBoardData = imageDataToMove; - + currentLayer.context.clearRect(startX - 0.5, startY - 0.5, endX - startX + 1, endY - startY + 1); // Moving those pixels from the current layer to the tmp layer TMPLayer.context.putImageData(imageDataToMove, startX + 1, startY); diff --git a/js/_tools.js b/js/_tools.js index 160dd88..5493365 100644 --- a/js/_tools.js +++ b/js/_tools.js @@ -58,8 +58,11 @@ class Tool { tools[i].classList.remove("selected"); } - //give the button of the selected tool the .selected class - document.getElementById(this.name+"-button").parentNode.classList.add("selected"); + let buttonNode = document.getElementById(this.name + "-button"); + //give the button of the selected tool the .selected class if the tool has a button + if(buttonNode != null && buttonNode.parentNode != null) { + document.getElementById(this.name+"-button").parentNode.classList.add("selected"); + } //change cursor this.updateCursor(); From 9beeefd39952b87e477017defbd725ae5720b7c8 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Fri, 5 Jun 2020 22:19:48 +0200 Subject: [PATCH 3/7] Finished copy / cut /paste Also fixed a minor bug that caused the preview rectangle for the selection tool to not be aligned to the actual selection. --- js/_copyPaste.js | 11 +++++++---- js/_move.js | 22 ++++++++++++++++------ js/_rectSelect.js | 5 ++--- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/js/_copyPaste.js b/js/_copyPaste.js index bae215a..66695be 100644 --- a/js/_copyPaste.js +++ b/js/_copyPaste.js @@ -6,19 +6,22 @@ let copiedStartY; let copiedEndX; let copiedEndY; +// BUG: when merging tmp layer to currentLayer there are offset problems +// FIX: maybe copy the entire tmp layer and paste it so that the merging happens at 0,0 + function copySelection() { - /* copiedEndX = endX; copiedEndY = endY; copiedStartX = startX; copiedStartY = startY; -*/ // Getting the selected pixels clipboardData = currentLayer.context.getImageData(startX, startY, endX - startX + 1, endY - startY + 1); } function pasteSelection() { + endSelection(); + isPasting = true; // Putting the image data on the tmp layer TMPLayer.context.putImageData(clipboardData, copiedStartX, copiedStartY); @@ -35,11 +38,12 @@ function pasteSelection() { moveSelection( copiedStartX + (copiedEndX - copiedStartX) / 2, copiedStartY + (copiedEndY - copiedStartY) / 2, - imageDataToMove.width, imageDataToMove.height); + clipboardData.width, clipboardData.height); //drawRect(copiedStartX, copiedEndX, copiedStartY, copiedEndY); } function cutSelectionTool() { + console.log("Taglio"); // Saving the canvas new HistoryStateEditCanvas(); @@ -59,7 +63,6 @@ function cutSelectionTool() { clipboardData = currentLayer.context.getImageData(startX, startY, endX - startX + 1, endY - startY + 1); currentLayer.context.clearRect(startX - 0.5, startY - 0.5, endX - startX + 1, endY - startY + 1); } - // Moving those pixels from the current layer to the tmp layer //TMPLayer.context.putImageData(imageDataToMove, startX + 1, startY); diff --git a/js/_move.js b/js/_move.js index cff6c21..cbf30f8 100644 --- a/js/_move.js +++ b/js/_move.js @@ -7,7 +7,6 @@ var firstTimeMove = true; // TODO: move with arrows function updateMovePreview(mousePosition) { - // ISSUE selectionCanceled = false; if (firstTimeMove) { @@ -22,8 +21,8 @@ function updateMovePreview(mousePosition) { // put the image data with offset TMPLayer.context.putImageData( imageDataToMove, - Math.round(lastMousePos[0] / zoom - imageDataToMove.width / 2), - Math.round(lastMousePos[1] / zoom - imageDataToMove.height / 2)); + Math.round(lastMousePos[0] / zoom) - imageDataToMove.width / 2, + Math.round(lastMousePos[1] / zoom) - imageDataToMove.height / 2); lastMovePos = lastMousePos; moveSelection(lastMousePos[0] / zoom, lastMousePos[1] / zoom, imageDataToMove.width, imageDataToMove.height); @@ -32,8 +31,12 @@ function updateMovePreview(mousePosition) { function endSelection() { TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height); VFXLayer.context.clearRect(0, 0, VFXLayer.canvas.width, VFXLayer.canvas.height); + let cleanImageData = new ImageData(endX - startX, endY - startY); if (imageDataToMove !== undefined) { + // Saving the current clipboard before editing it in order to merge it with the current layer + cleanImageData.data.set(imageDataToMove.data); + let underlyingImageData = currentLayer.context.getImageData(startX, startY, endX - startX, endY - startY); for (let i=0; i Date: Fri, 5 Jun 2020 22:28:28 +0200 Subject: [PATCH 4/7] Added a line to handle the history --- js/_move.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/_move.js b/js/_move.js index cbf30f8..aae7c67 100644 --- a/js/_move.js +++ b/js/_move.js @@ -67,7 +67,6 @@ function endSelection() { Math.round(lastMovePos[1] / zoom) - imageDataToMove.height / 2); } else { - console.log("yo"); currentLayer.context.putImageData( imageDataToMove, copiedStartX, @@ -83,4 +82,6 @@ function endSelection() { imageDataToMove = undefined; isPasting = false; isCutting = false; + + new HistoryStateEditCanvas(); } \ No newline at end of file From 0fc1df16504a4a764f93f98d7ace54c35af1c70e Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Sat, 6 Jun 2020 21:44:52 +0200 Subject: [PATCH 5/7] Added Selection menu Also fixed a few minor bugs. --- js/_fileMenu.js | 15 +++++++++++++++ js/_history.js | 28 ++++++++++++++-------------- js/_mouseEvents.js | 3 ++- js/_move.js | 3 +++ views/pixel-editor.hbs | 8 ++++++++ 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/js/_fileMenu.js b/js/_fileMenu.js index 494af19..7f884b4 100644 --- a/js/_fileMenu.js +++ b/js/_fileMenu.js @@ -103,6 +103,21 @@ for (var i = 1; i < mainMenuItems.length; i++) { case 'Add color': addColor('#eeeeee'); break; + // SELECTION MENU + case 'Paste': + pasteSelection(); + break; + case 'Copy': + copySelection(); + tool.pencil.switchTo(); + break; + case 'Cut': + cutSelectionTool(); + tool.pencil.switchTo(); + break; + case 'Cancel': + tool.pencil.switchTo(); + break; //Help Menu case 'Settings': diff --git a/js/_history.js b/js/_history.js index f1f1453..6c5ec06 100644 --- a/js/_history.js +++ b/js/_history.js @@ -87,7 +87,7 @@ function HistoryStateEditColor (newColorValue, oldColorValue) { //find new color in palette and change it back to old color var colors = document.getElementsByClassName('color-button'); for (var i = 0; i < colors.length; i++) { - console.log(newColorValue, '==', colors[i].jscolor.toString()); + //console.log(newColorValue, '==', colors[i].jscolor.toString()); if (newColorValue == colors[i].jscolor.toString()) { colors[i].jscolor.fromString(oldColorValue); break; @@ -105,7 +105,7 @@ function HistoryStateEditColor (newColorValue, oldColorValue) { //find old color in palette and change it back to new color var colors = document.getElementsByClassName('color-button'); for (var i = 0; i < colors.length; i++) { - console.log(oldColorValue, '==', colors[i].jscolor.toString()); + //console.log(oldColorValue, '==', colors[i].jscolor.toString()); if (oldColorValue == colors[i].jscolor.toString()) { colors[i].jscolor.fromString(newColorValue); break; @@ -123,8 +123,8 @@ function HistoryStateEditColor (newColorValue, oldColorValue) { //rename to add undo state function saveHistoryState (state) { - console.log('%csaving history state', undoLogStyle); - console.log(state); + //console.log('%csaving history state', undoLogStyle); + //console.log(state); //get current canvas data and save to undoStates array undoStates.push(state); @@ -140,12 +140,12 @@ function saveHistoryState (state) { //there should be no redoStates after an undoState is saved redoStates = []; - console.log(undoStates); - console.log(redoStates); + //console.log(undoStates); + //console.log(redoStates); } function undo () { - console.log('%cundo', undoLogStyle); + //console.log('%cundo', undoLogStyle); //if there are any states saved to undo if (undoStates.length > 0) { @@ -154,7 +154,7 @@ function undo () { //get state var undoState = undoStates[undoStates.length-1]; - console.log(undoState); + //console.log(undoState); //restore the state undoState.undo(); @@ -167,12 +167,12 @@ function undo () { document.getElementById('undo-button').classList.add('disabled'); } - console.log(undoStates); - console.log(redoStates); + //console.log(undoStates); + //console.log(redoStates); } function redo () { - console.log('%credo', undoLogStyle); + //console.log('%credo', undoLogStyle); if (redoStates.length > 0) { @@ -181,7 +181,7 @@ function redo () { //get state var redoState = redoStates[redoStates.length-1]; - console.log(redoState); + //console.log(redoState); //restore the state redoState.redo(); @@ -193,6 +193,6 @@ function redo () { if (redoStates.length == 0) document.getElementById('redo-button').classList.add('disabled'); } - console.log(undoStates); - console.log(redoStates); + //console.log(undoStates); + //console.log(redoStates); } diff --git a/js/_mouseEvents.js b/js/_mouseEvents.js index 5b9cb07..3fd2caa 100644 --- a/js/_mouseEvents.js +++ b/js/_mouseEvents.js @@ -26,7 +26,8 @@ window.addEventListener("mousedown", function (mouseEvent) { (currentTool.name == 'pencil' || currentTool.name == 'eraser' || currentTool.name == 'rectangle')) new HistoryStateEditCanvas(); else if (currentTool.name == 'moveselection') { - if (!cursorInSelectedArea()) { + if (!cursorInSelectedArea() && + ((mouseEvent.target.id == 'canvas-view') || mouseEvent.target.className == 'drawingCanvas')) { tool.pencil.switchTo(); canDraw = false; } diff --git a/js/_move.js b/js/_move.js index aae7c67..0bc1471 100644 --- a/js/_move.js +++ b/js/_move.js @@ -34,6 +34,7 @@ function endSelection() { let cleanImageData = new ImageData(endX - startX, endY - startY); if (imageDataToMove !== undefined) { + console.log("definito"); // Saving the current clipboard before editing it in order to merge it with the current layer cleanImageData.data.set(imageDataToMove.data); @@ -67,6 +68,7 @@ function endSelection() { Math.round(lastMovePos[1] / zoom) - imageDataToMove.height / 2); } else { + console.log("incollo male"); currentLayer.context.putImageData( imageDataToMove, copiedStartX, @@ -82,6 +84,7 @@ function endSelection() { imageDataToMove = undefined; isPasting = false; isCutting = false; + lastMovePos = undefined; new HistoryStateEditCanvas(); } \ No newline at end of file diff --git a/views/pixel-editor.hbs b/views/pixel-editor.hbs index 2624833..74ab6f9 100644 --- a/views/pixel-editor.hbs +++ b/views/pixel-editor.hbs @@ -61,6 +61,14 @@
  • +
  • + +