Get undo/redo working

This commit is contained in:
DD 2018-04-09 17:47:11 -04:00
parent 15053d15f0
commit 6e4ab3191a
5 changed files with 60 additions and 21 deletions

View file

@ -1,5 +1,6 @@
import paper from '@scratch/paper'; import paper from '@scratch/paper';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import PaintEditorComponent from '../components/paint-editor/paint-editor.jsx'; import PaintEditorComponent from '../components/paint-editor/paint-editor.jsx';
@ -11,7 +12,8 @@ import {deactivateEyeDropper} from '../reducers/eye-dropper';
import {setTextEditTarget} from '../reducers/text-edit-target'; import {setTextEditTarget} from '../reducers/text-edit-target';
import {updateViewBounds} from '../reducers/view-bounds'; import {updateViewBounds} from '../reducers/view-bounds';
import {hideGuideLayers, showGuideLayers} from '../helper/layer'; import {getRaster, hideGuideLayers, showGuideLayers} from '../helper/layer';
import {trim} from '../helper/bitmap';
import {performUndo, performRedo, performSnapshot, shouldShowUndo, shouldShowRedo} from '../helper/undo'; import {performUndo, performRedo, performSnapshot, shouldShowUndo, shouldShowRedo} from '../helper/undo';
import {bringToFront, sendBackward, sendToBack, bringForward} from '../helper/order'; import {bringToFront, sendBackward, sendToBack, bringForward} from '../helper/order';
import {groupSelection, ungroupSelection} from '../helper/group'; import {groupSelection, ungroupSelection} from '../helper/group';
@ -90,9 +92,20 @@ class PaintEditor extends React.Component {
const oldCenter = paper.project.view.center.clone(); const oldCenter = paper.project.view.center.clone();
resetZoom(); resetZoom();
const guideLayers = hideGuideLayers(); let raster;
if (this.props.format === Formats.BITMAP) {
// @todo export bitmap here
raster = trim(getRaster());
if (raster.width === 0 || raster.height === 0) {
raster.remove();
} else {
paper.project.activeLayer.addChild(raster);
}
}
const guideLayers = hideGuideLayers(true /* includeRaster */);
const bounds = paper.project.activeLayer.bounds; const bounds = paper.project.activeLayer.bounds;
this.props.onUpdateSvg( this.props.onUpdateSvg(
paper.project.exportSVG({ paper.project.exportSVG({
asString: true, asString: true,
@ -108,6 +121,8 @@ class PaintEditor extends React.Component {
performSnapshot(this.props.undoSnapshot); performSnapshot(this.props.undoSnapshot);
} }
if (raster) raster.remove();
// Restore old zoom // Restore old zoom
paper.project.view.zoom = oldZoom; paper.project.view.zoom = oldZoom;
paper.project.view.center = oldCenter; paper.project.view.center = oldCenter;

View file

@ -79,15 +79,17 @@ class PaperCanvas extends React.Component {
} }
} }
convertToBitmap () { convertToBitmap () {
this.props.clearSelectedItems();
const raster = paper.project.activeLayer.rasterize(72, false /* insert */); const raster = paper.project.activeLayer.rasterize(72, false /* insert */);
raster.onLoad = function () { raster.onLoad = function () {
const subCanvas = raster.canvas; const subCanvas = raster.canvas;
getRaster().drawImage(subCanvas, raster.bounds.topLeft); getRaster().drawImage(subCanvas, raster.bounds.topLeft);
};
paper.project.activeLayer.removeChildren(); paper.project.activeLayer.removeChildren();
performSnapshot(this.props.undoSnapshot); this.props.onUpdateSvg();
}.bind(this);
} }
convertToVector () { convertToVector () {
this.props.clearSelectedItems();
const raster = trim(getRaster()); const raster = trim(getRaster());
if (raster.width === 0 || raster.height === 0) { if (raster.width === 0 || raster.height === 0) {
raster.remove(); raster.remove();
@ -95,7 +97,7 @@ class PaperCanvas extends React.Component {
paper.project.activeLayer.addChild(raster); paper.project.activeLayer.addChild(raster);
} }
clearRaster(); clearRaster();
performSnapshot(this.props.undoSnapshot); this.props.onUpdateSvg();
} }
switchCostume (svg, rotationCenterX, rotationCenterY) { switchCostume (svg, rotationCenterX, rotationCenterY) {
for (const layer of paper.project.layers) { for (const layer of paper.project.layers) {

View file

@ -9,7 +9,6 @@ const _getLayer = function (layerString) {
return layer; return layer;
} }
} }
log.error(`Didn't find layer ${layerString}`);
}; };
const _getPaintingLayer = function () { const _getPaintingLayer = function () {
@ -36,22 +35,40 @@ const _getBackgroundGuideLayer = function () {
return _getLayer('isBackgroundGuideLayer'); return _getLayer('isBackgroundGuideLayer');
}; };
const _makeGuideLayer = function () {
const guideLayer = new paper.Layer();
guideLayer.data.isGuideLayer = true;
return guideLayer;
};
const getGuideLayer = function () { const getGuideLayer = function () {
return _getLayer('isGuideLayer'); let layer = _getLayer('isGuideLayer');
if (!layer) {
layer = _makeGuideLayer();
_getPaintingLayer().activate();
}
return layer;
}; };
/** /**
* Removes the guide layers, e.g. for purposes of exporting the image. Must call showGuideLayers to re-add them. * Removes the guide layers, e.g. for purposes of exporting the image. Must call showGuideLayers to re-add them.
* @param {boolean} includeRaster true if the raster layer should also be hidden
* @return {object} an object of the removed layers, which should be passed to showGuideLayers to re-add them. * @return {object} an object of the removed layers, which should be passed to showGuideLayers to re-add them.
*/ */
const hideGuideLayers = function () { const hideGuideLayers = function (includeRaster) {
const backgroundGuideLayer = _getBackgroundGuideLayer(); const backgroundGuideLayer = _getBackgroundGuideLayer();
const guideLayer = getGuideLayer(); const guideLayer = getGuideLayer();
guideLayer.remove(); guideLayer.remove();
backgroundGuideLayer.remove(); backgroundGuideLayer.remove();
let rasterLayer;
if (includeRaster) {
rasterLayer = _getLayer('isRasterLayer');
rasterLayer.remove();
}
return { return {
guideLayer: guideLayer, guideLayer: guideLayer,
backgroundGuideLayer: backgroundGuideLayer backgroundGuideLayer: backgroundGuideLayer,
rasterLayer: rasterLayer
}; };
}; };
@ -63,6 +80,11 @@ const hideGuideLayers = function () {
const showGuideLayers = function (guideLayers) { const showGuideLayers = function (guideLayers) {
const backgroundGuideLayer = guideLayers.backgroundGuideLayer; const backgroundGuideLayer = guideLayers.backgroundGuideLayer;
const guideLayer = guideLayers.guideLayer; const guideLayer = guideLayers.guideLayer;
const rasterLayer = guideLayers.rasterLayer;
if (rasterLayer && !rasterLayer.index) {
paper.project.addLayer(rasterLayer);
rasterLayer.sendToBack();
}
if (!backgroundGuideLayer.index) { if (!backgroundGuideLayer.index) {
paper.project.addLayer(backgroundGuideLayer); paper.project.addLayer(backgroundGuideLayer);
backgroundGuideLayer.sendToBack(); backgroundGuideLayer.sendToBack();
@ -77,12 +99,6 @@ const showGuideLayers = function (guideLayers) {
} }
}; };
const _makeGuideLayer = function () {
const guideLayer = new paper.Layer();
guideLayer.data.isGuideLayer = true;
return guideLayer;
};
const _makePaintingLayer = function () { const _makePaintingLayer = function () {
const paintingLayer = new paper.Layer(); const paintingLayer = new paper.Layer();
paintingLayer.data.isPaintingLayer = true; paintingLayer.data.isPaintingLayer = true;

View file

@ -54,7 +54,7 @@ class BoundingBoxTool {
* @param {Array<paper.Item>} selectedItems Array of selected items. * @param {Array<paper.Item>} selectedItems Array of selected items.
*/ */
onSelectionChanged (selectedItems) { onSelectionChanged (selectedItems) {
if (selectedItems) { if (selectedItems && selectedItems.length) {
this.setSelectionBounds(); this.setSelectionBounds();
} else { } else {
this.removeBoundsPath(); this.removeBoundsPath();

View file

@ -1,7 +1,7 @@
// undo functionality // undo functionality
// modifed from https://github.com/memononen/stylii // modifed from https://github.com/memononen/stylii
import paper from '@scratch/paper'; import paper from '@scratch/paper';
import {hideGuideLayers, showGuideLayers} from '../helper/layer'; import {hideGuideLayers, showGuideLayers, getRaster} from '../helper/layer';
const performSnapshot = function (dispatchPerformSnapshot) { const performSnapshot = function (dispatchPerformSnapshot) {
const guideLayers = hideGuideLayers(); const guideLayers = hideGuideLayers();
@ -12,7 +12,8 @@ const performSnapshot = function (dispatchPerformSnapshot) {
}; };
const _restore = function (entry, setSelectedItems, onUpdateSvg) { const _restore = function (entry, setSelectedItems, onUpdateSvg) {
for (const layer of paper.project.layers) { for (let i = paper.project.layers.length - 1; i >= 0; i--) {
const layer = paper.project.layers[i];
if (!layer.data.isBackgroundGuideLayer) { if (!layer.data.isBackgroundGuideLayer) {
layer.removeChildren(); layer.removeChildren();
layer.remove(); layer.remove();
@ -21,8 +22,13 @@ const _restore = function (entry, setSelectedItems, onUpdateSvg) {
paper.project.importJSON(entry.json); paper.project.importJSON(entry.json);
setSelectedItems(); setSelectedItems();
getRaster().onLoad = function () {
onUpdateSvg(true /* skipSnapshot */); onUpdateSvg(true /* skipSnapshot */);
}; };
if (getRaster().loaded) {
getRaster().onLoad();
}
};
const performUndo = function (undoState, dispatchPerformUndo, setSelectedItems, onUpdateSvg) { const performUndo = function (undoState, dispatchPerformUndo, setSelectedItems, onUpdateSvg) {
if (undoState.pointer > 0) { if (undoState.pointer > 0) {