Paint operations are now also stored into state history

This commit is contained in:
Igor Zinken
2021-01-13 21:36:48 +01:00
parent b91af331ac
commit 897ed43cee
2 changed files with 45 additions and 1 deletions

View File

@@ -114,6 +114,7 @@ export default {
handler( document, oldValue = null ) {
// no active document or no document content
if ( !document?.layers ) {
this.resetHistory();
if ( getCanvasInstance() ) {
getCanvasInstance().dispose();
setCanvasInstance( null );

View File

@@ -22,7 +22,7 @@
*/
import Vue from "vue";
import { sprite } from "zcanvas"
import { createCanvas, resizeImage, globalToLocal } from "@/utils/canvas-util";
import { createCanvas, cloneCanvas, resizeImage, globalToLocal } from "@/utils/canvas-util";
import { renderCross, renderMasked } from "@/utils/render-util";
import { LAYER_GRAPHIC, LAYER_MASK, LAYER_TEXT } from "@/definitions/layer-types";
import { translatePointerRotation, rotatePoints } from "@/math/image-math";
@@ -155,6 +155,9 @@ class LayerSprite extends sprite {
this._selection = null;
this._toolOptions = null;
// store pending paint states (if there were any)
this.storePaintState();
if ( !this._interactive ) {
return;
}
@@ -203,6 +206,10 @@ class LayerSprite extends sprite {
}
paint( x, y ) {
if ( !this._pendingPaintState ) {
this.preparePendingPaintState();
}
// translate pointer to translated space, when layer is rotated or mirrored
const { mirrorX, mirrorY, rotation } = this.layer.effects;
const rotCenterX = this._bounds.left + this._bounds.width / 2;
@@ -292,6 +299,37 @@ class LayerSprite extends sprite {
this.resetFilterAndRecache();
}
/**
* As storing Bitmaps will consume a lot of memory fast we debounce this by
* a larger interval to prevent creating a big bitmap per brush stroke.
* Note that upon switching tools the state is enqueued immediately to
* not delay to history state UI from updating more than necessary.
*/
preparePendingPaintState() {
this._orgSourceToStore = cloneCanvas( this.layer.source );
this._pendingPaintState = setTimeout( this.storePaintState.bind( this ), 5000 );
}
storePaintState() {
if ( !this._pendingPaintState ) {
return;
}
clearTimeout( this._pendingPaintState );
this._pendingPaintState = null;
const layer = this.layer;
const orgState = this._orgSourceToStore;
const newState = cloneCanvas( layer.source );
enqueueState( `spritePaint_${layer.id}`, {
undo() {
restorePaintFromHistory( layer, orgState );
},
redo() {
restorePaintFromHistory( layer, newState);
}
});
this._orgSourceToStore = null;
}
/* the following override zCanvas.sprite */
setBounds( x, y, width = 0, height = 0 ) {
@@ -478,3 +516,8 @@ function positionSpriteFromHistory( layer, x, y ) {
sprite.invalidate();
}
}
function restorePaintFromHistory( layer, orgState ) {
layer.source = orgState;
getSpriteForLayer( layer )?.resetFilterAndRecache();
}