mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): trying to fix flicker after transform
This commit is contained in:
parent
ea02323095
commit
1ddea87c35
@ -7,15 +7,16 @@ import { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
|
||||
import { CanvasRect } from 'features/controlLayers/konva/CanvasRect';
|
||||
import { getBrushLineId, getEraserLineId, getRectShapeId } from 'features/controlLayers/konva/naming';
|
||||
import { konvaNodeToBlob, mapId, previewBlob } from 'features/controlLayers/konva/util';
|
||||
import { layerRasterized } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import type {
|
||||
BrushLine,
|
||||
CanvasV2State,
|
||||
Coordinate,
|
||||
EraserLine,
|
||||
LayerEntity,
|
||||
Rect,
|
||||
RectShape,
|
||||
import { layerAllObjectsDeletedExceptOne, layerRasterized } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import {
|
||||
type BrushLine,
|
||||
type CanvasV2State,
|
||||
type Coordinate,
|
||||
type EraserLine,
|
||||
imageDTOToImageObject,
|
||||
type LayerEntity,
|
||||
type Rect,
|
||||
type RectShape,
|
||||
} from 'features/controlLayers/store/types';
|
||||
import Konva from 'konva';
|
||||
import { debounce, get } from 'lodash-es';
|
||||
@ -53,6 +54,8 @@ export class CanvasLayer {
|
||||
_isFirstRender: boolean;
|
||||
|
||||
isTransforming: boolean;
|
||||
isPendingBboxCalculation: boolean;
|
||||
rasterizedObjectId: string | null;
|
||||
|
||||
rect: Rect;
|
||||
bbox: Rect;
|
||||
@ -188,6 +191,8 @@ export class CanvasLayer {
|
||||
this._bboxNeedsUpdate = true;
|
||||
this.isTransforming = false;
|
||||
this._isFirstRender = true;
|
||||
this.rasterizedObjectId = null;
|
||||
this.isPendingBboxCalculation = false;
|
||||
this._log = this.manager.getLogger(`layer_${this.id}`);
|
||||
}
|
||||
|
||||
@ -326,6 +331,12 @@ export class CanvasLayer {
|
||||
if (didUpdate) {
|
||||
this.calculateBbox();
|
||||
}
|
||||
|
||||
if (this.isTransforming && this.rasterizedObjectId) {
|
||||
this.manager._store.dispatch(layerAllObjectsDeletedExceptOne({ id: this.id, objectId: this.rasterizedObjectId }));
|
||||
this.isTransforming = false;
|
||||
this.rasterizedObjectId = null;
|
||||
}
|
||||
}
|
||||
|
||||
async updateOpacity(arg?: { opacity: number }) {
|
||||
@ -388,6 +399,10 @@ export class CanvasLayer {
|
||||
async updateBbox() {
|
||||
this._log.trace('Updating bbox');
|
||||
|
||||
if (this.isPendingBboxCalculation) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the bbox has no width or height, that means the layer is fully transparent. This can happen if it is only
|
||||
// eraser lines, fully clipped brush lines or if it has been fully erased.
|
||||
if (this.bbox.width === 0 || this.bbox.height === 0) {
|
||||
@ -547,11 +562,16 @@ export class CanvasLayer {
|
||||
}
|
||||
const imageDTO = await uploadImage(blob, `${this.id}_transform.png`, 'other', true);
|
||||
const { dispatch } = getStore();
|
||||
dispatch(layerRasterized({ id: this.id, imageDTO, position: { x: rect.x, y: rect.y } }));
|
||||
this.isTransforming = false;
|
||||
const imageObject = imageDTOToImageObject(this.id, uuidv4(), imageDTO);
|
||||
dispatch(layerRasterized({ id: this.id, imageObject, position: { x: rect.x, y: rect.y } }));
|
||||
this.rasterizedObjectId = imageObject.id;
|
||||
this.resetScale();
|
||||
}
|
||||
|
||||
async finalizeTransform() {
|
||||
//
|
||||
}
|
||||
|
||||
async cancelTransform() {
|
||||
this._log.debug('Canceling transform');
|
||||
|
||||
@ -572,9 +592,12 @@ export class CanvasLayer {
|
||||
calculateBbox = debounce(() => {
|
||||
this._log.debug('Calculating bbox');
|
||||
|
||||
this.isPendingBboxCalculation = true;
|
||||
|
||||
if (this.objects.size === 0) {
|
||||
this.rect = this.getDefaultRect();
|
||||
this.bbox = this.getDefaultRect();
|
||||
this.isPendingBboxCalculation = false;
|
||||
this.updateBbox();
|
||||
return;
|
||||
}
|
||||
@ -607,6 +630,7 @@ export class CanvasLayer {
|
||||
if (!needsPixelBbox) {
|
||||
this.rect = deepClone(rect);
|
||||
this.bbox = deepClone(rect);
|
||||
this.isPendingBboxCalculation = false;
|
||||
this._log.trace({ bbox: this.bbox, rect: this.rect }, 'Got bbox from client rect');
|
||||
this.updateBbox();
|
||||
return;
|
||||
@ -636,6 +660,7 @@ export class CanvasLayer {
|
||||
} else {
|
||||
this.bbox = deepClone(rect);
|
||||
}
|
||||
this.isPendingBboxCalculation = false;
|
||||
this._log.trace({ bbox: this.bbox, rect: this.rect, extents }, `Got bbox from worker`);
|
||||
this.updateBbox();
|
||||
clone.destroy();
|
||||
|
@ -329,7 +329,7 @@ export class CanvasManager {
|
||||
for (const canvasLayer of this.layers.values()) {
|
||||
if (!state.layers.entities.find((l) => l.id === canvasLayer.id)) {
|
||||
this.log.debug(`Destroying deleted layer ${canvasLayer.id}`);
|
||||
canvasLayer.destroy();
|
||||
await canvasLayer.destroy();
|
||||
this.layers.delete(canvasLayer.id);
|
||||
}
|
||||
}
|
||||
|
@ -220,6 +220,7 @@ export const {
|
||||
layerTranslated,
|
||||
layerBboxChanged,
|
||||
layerImageAdded,
|
||||
layerAllObjectsDeletedExceptOne,
|
||||
layerAllDeleted,
|
||||
layerImageCacheChanged,
|
||||
layerScaled,
|
||||
|
@ -10,6 +10,7 @@ import type {
|
||||
CanvasV2State,
|
||||
Coordinate,
|
||||
EraserLine,
|
||||
ImageObject,
|
||||
ImageObjectAddedArg,
|
||||
LayerEntity,
|
||||
PositionChangedArg,
|
||||
@ -252,16 +253,25 @@ export const layersReducers = {
|
||||
const { imageDTO } = action.payload;
|
||||
state.layers.imageCache = imageDTO ? imageDTOToImageWithDims(imageDTO) : null;
|
||||
},
|
||||
layerRasterized: (state, action: PayloadAction<{ id: string; imageDTO: ImageDTO; position: Coordinate }>) => {
|
||||
const { id, imageDTO, position } = action.payload;
|
||||
layerRasterized: (state, action: PayloadAction<{ id: string; imageObject: ImageObject; position: Coordinate }>) => {
|
||||
const { id, imageObject, position } = action.payload;
|
||||
const layer = selectLayer(state, id);
|
||||
if (!layer) {
|
||||
return;
|
||||
}
|
||||
layer.objects = [imageDTOToImageObject(id, uuidv4(), imageDTO)];
|
||||
layer.objects.push(imageObject);
|
||||
layer.position = position;
|
||||
state.layers.imageCache = null;
|
||||
},
|
||||
layerAllObjectsDeletedExceptOne: (state, action: PayloadAction<{ id: string; objectId: string }>) => {
|
||||
const { id, objectId } = action.payload;
|
||||
const layer = selectLayer(state, id);
|
||||
if (!layer) {
|
||||
return;
|
||||
}
|
||||
layer.objects = layer.objects.filter((obj) => obj.id === objectId);
|
||||
state.layers.imageCache = null;
|
||||
},
|
||||
} satisfies SliceCaseReducers<CanvasV2State>;
|
||||
|
||||
const scalePoints = (points: number[], scaleX: number, scaleY: number) => {
|
||||
|
Loading…
Reference in New Issue
Block a user