/** How the history works * - undoStates stores the states that can be undone * - redoStates stores the states that can be redone * - undo() undoes an action and adds it to the redoStates * - redo() redoes an action and adds it to the undoStates * - Each HistoryState must implement an undo() and redo() function * Those functions actually implement the undo and redo mechanism for that action, * so you'll need to save the data you need as attributes in the constructor. For example, * for the HistoryStateAddColour, the added colour is saved so that it can be removed in * undo() or added back in redo(). * - Each HistoryState must call saveHistoryState(this) so that it gets added to the stack * */ var undoStates = []; var redoStates = []; const undoLogStyle = 'background: #87ff1c; color: black; padding: 5px;'; function HistoryStateResizeSprite(xRatio, yRatio, algo, oldData) { this.xRatio = xRatio; this.yRatio = yRatio; this.algo = algo; this.oldData = oldData; this.undo = function() { let layerIndex = 0; currentAlgo = algo; resizeSprite(null, [1 / this.xRatio, 1 / this.yRatio]); // Also putting the old data for (let i=0; i this.index + 1) { layers[this.index + 1].selectLayer(); } else { layers[this.index - 1].selectLayer(); } this.added.canvas.remove(); this.added.menuEntry.remove(); layers.splice(index, 1); }; this.redo = function() { undoStates.push(this); canvasView.append(this.added.canvas); layerList.prepend(this.added.menuEntry); layers.splice(this.index, 0, this.added); }; saveHistoryState(this); } //prototype for undoing canvas changes function HistoryStateEditCanvas () { this.canvasState = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); this.layerID = currentLayer.id; this.undo = function () { var stateLayer = getLayerByID(this.layerID); var currentCanvas = stateLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); stateLayer.context.putImageData(this.canvasState, 0, 0); this.canvasState = currentCanvas; redoStates.push(this); stateLayer.updateLayerPreview(); }; this.redo = function () { console.log("YEET"); var stateLayer = getLayerByID(this.layerID); var currentCanvas = stateLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); stateLayer.context.putImageData(this.canvasState, 0, 0); this.canvasState = currentCanvas; undoStates.push(this); stateLayer.updateLayerPreview(); }; //add self to undo array saveHistoryState(this); } //prototype for undoing added colors function HistoryStateAddColor (colorValue) { this.colorValue = colorValue; this.undo = function () { redoStates.push(this); deleteColor(this.colorValue); }; this.redo = function () { addColor(this.colorValue); undoStates.push(this); }; //add self to undo array saveHistoryState(this); } //prototype for undoing deleted colors function HistoryStateDeleteColor (colorValue) { this.colorValue = colorValue; this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); this.undo = function () { var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); currentLayer.context.putImageData(this.canvas, 0, 0); addColor(this.colorValue); this.canvas = currentCanvas; redoStates.push(this); }; this.redo = function () { var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); currentLayer.context.putImageData(this.canvas, 0, 0); deleteColor(this.colorValue); this.canvas = currentCanvas; undoStates.push(this); }; //add self to undo array saveHistoryState(this); } //prototype for undoing colors edits function HistoryStateEditColor (newColorValue, oldColorValue) { this.newColorValue = newColorValue; this.oldColorValue = oldColorValue; this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); this.undo = function () { var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); currentLayer.context.putImageData(this.canvas, 0, 0); //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()); if (newColorValue == colors[i].jscolor.toString()) { colors[i].jscolor.fromString(oldColorValue); break; } } this.canvas = currentCanvas; redoStates.push(this); }; this.redo = function () { var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); currentLayer.context.putImageData(this.canvas, 0, 0); //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()); if (oldColorValue == colors[i].jscolor.toString()) { colors[i].jscolor.fromString(newColorValue); break; } } this.canvas = currentCanvas; undoStates.push(this); }; //add self to undo array saveHistoryState(this); } //rename to add undo state function saveHistoryState (state) { //get current canvas data and save to undoStates array undoStates.push(state); //limit the number of states to settings.numberOfHistoryStates if (undoStates.length > settings.numberOfHistoryStates) { undoStates = undoStates.splice(-settings.numberOfHistoryStates, settings.numberOfHistoryStates); } //there is now definitely at least 1 undo state, so the button shouldnt be disabled document.getElementById('undo-button').classList.remove('disabled'); //there should be no redoStates after an undoState is saved redoStates = []; } function undo () { //if there are any states saved to undo if (undoStates.length > 0) { document.getElementById('redo-button').classList.remove('disabled'); //get state var undoState = undoStates[undoStates.length-1]; //console.log(undoState); //remove from the undo list undoStates.splice(undoStates.length-1,1); //restore the state undoState.undo(); //if theres none left to undo, disable the option if (undoStates.length == 0) document.getElementById('undo-button').classList.add('disabled'); } } function redo () { if (redoStates.length > 0) { //enable undo button document.getElementById('undo-button').classList.remove('disabled'); //get state var redoState = redoStates[redoStates.length-1]; //remove from redo array (do this before restoring the state, else the flatten state will break) redoStates.splice(redoStates.length-1,1); //restore the state redoState.redo(); //if theres none left to redo, disable the option if (redoStates.length == 0) document.getElementById('redo-button').classList.add('disabled'); } //console.log(undoStates); //console.log(redoStates); }