mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): hallelujah (???)
This commit is contained in:
parent
de597a5eb4
commit
d15321a373
@ -1,4 +1,5 @@
|
||||
import { getStore } from 'app/store/nanostores/store';
|
||||
import { deepClone } from 'common/util/deepClone';
|
||||
import { CanvasBrushLine } from 'features/controlLayers/konva/CanvasBrushLine';
|
||||
import { CanvasEraserLine } from 'features/controlLayers/konva/CanvasEraserLine';
|
||||
import { CanvasImage } from 'features/controlLayers/konva/CanvasImage';
|
||||
@ -13,6 +14,7 @@ import type {
|
||||
Coordinate,
|
||||
EraserLine,
|
||||
LayerEntity,
|
||||
Rect,
|
||||
RectShape,
|
||||
} from 'features/controlLayers/store/types';
|
||||
import Konva from 'konva';
|
||||
@ -46,15 +48,14 @@ export class CanvasLayer {
|
||||
};
|
||||
objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect | CanvasImage>;
|
||||
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
width: number;
|
||||
height: number;
|
||||
log: Logger;
|
||||
bboxNeedsUpdate: boolean;
|
||||
isTransforming: boolean;
|
||||
isFirstRender: boolean;
|
||||
|
||||
rect: Rect;
|
||||
bbox: Rect;
|
||||
|
||||
constructor(state: LayerEntity, manager: CanvasManager) {
|
||||
this.id = state.id;
|
||||
this.manager = manager;
|
||||
@ -146,8 +147,8 @@ export class CanvasLayer {
|
||||
});
|
||||
|
||||
this.konva.objectGroup.setAttrs({
|
||||
x: this.konva.interactionRect.x() - this.offsetX * this.konva.interactionRect.scaleX(),
|
||||
y: this.konva.interactionRect.y() - this.offsetY * this.konva.interactionRect.scaleY(),
|
||||
x: this.konva.interactionRect.x(),
|
||||
y: this.konva.interactionRect.y(),
|
||||
scaleX: this.konva.interactionRect.scaleX(),
|
||||
scaleY: this.konva.interactionRect.scaleY(),
|
||||
rotation: this.konva.interactionRect.rotation(),
|
||||
@ -158,8 +159,8 @@ export class CanvasLayer {
|
||||
y: this.konva.objectGroup.y(),
|
||||
scaleX: this.konva.objectGroup.scaleX(),
|
||||
scaleY: this.konva.objectGroup.scaleY(),
|
||||
offsetX: this.offsetX,
|
||||
offsetY: this.offsetY,
|
||||
offsetX: this.konva.objectGroup.offsetX(),
|
||||
offsetY: this.konva.objectGroup.offsetY(),
|
||||
width: this.konva.objectGroup.width(),
|
||||
height: this.konva.objectGroup.height(),
|
||||
rotation: this.konva.objectGroup.rotation(),
|
||||
@ -196,8 +197,8 @@ export class CanvasLayer {
|
||||
// The object group is translated by the difference between the interaction rect's new and old positions (which is
|
||||
// stored as this.bbox)
|
||||
this.konva.objectGroup.setAttrs({
|
||||
x: this.konva.interactionRect.x() - this.offsetX * this.konva.interactionRect.scaleX(),
|
||||
y: this.konva.interactionRect.y() - this.offsetY * this.konva.interactionRect.scaleY(),
|
||||
x: this.konva.interactionRect.x(),
|
||||
y: this.konva.interactionRect.y(),
|
||||
});
|
||||
});
|
||||
this.konva.interactionRect.on('dragend', () => {
|
||||
@ -213,8 +214,8 @@ export class CanvasLayer {
|
||||
{
|
||||
id: this.id,
|
||||
position: {
|
||||
x: this.konva.interactionRect.x() - this.offsetX * this.konva.interactionRect.scaleX(),
|
||||
y: this.konva.interactionRect.y() - this.offsetY * this.konva.interactionRect.scaleY(),
|
||||
x: this.konva.interactionRect.x() - this.bbox.x,
|
||||
y: this.konva.interactionRect.y() - this.bbox.y,
|
||||
},
|
||||
},
|
||||
'layer'
|
||||
@ -224,16 +225,12 @@ export class CanvasLayer {
|
||||
this.objects = new Map();
|
||||
this.drawingBuffer = null;
|
||||
this.state = state;
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.rect = this.getDefaultRect();
|
||||
this.bbox = this.getDefaultRect();
|
||||
this.bboxNeedsUpdate = true;
|
||||
this.isTransforming = false;
|
||||
this.isFirstRender = true;
|
||||
this.log = this.manager.getLogger(`layer_${this.id}`);
|
||||
|
||||
console.log(this);
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
@ -317,16 +314,18 @@ export class CanvasLayer {
|
||||
const bboxPadding = this.manager.getScaledBboxPadding();
|
||||
|
||||
this.konva.objectGroup.setAttrs({
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
x: position.x + this.bbox.x,
|
||||
y: position.y + this.bbox.y,
|
||||
offsetX: this.bbox.x,
|
||||
offsetY: this.bbox.y,
|
||||
});
|
||||
this.konva.bbox.setAttrs({
|
||||
x: position.x + this.offsetX * this.konva.interactionRect.scaleX() - bboxPadding,
|
||||
y: position.y + this.offsetY * this.konva.interactionRect.scaleY() - bboxPadding,
|
||||
x: position.x + this.bbox.x - bboxPadding,
|
||||
y: position.y + this.bbox.y - bboxPadding,
|
||||
});
|
||||
this.konva.interactionRect.setAttrs({
|
||||
x: position.x + this.offsetX * this.konva.interactionRect.scaleX(),
|
||||
y: position.y + this.offsetY * this.konva.interactionRect.scaleY(),
|
||||
x: position.x + this.bbox.x * this.konva.interactionRect.scaleX(),
|
||||
y: position.y + this.bbox.y * this.konva.interactionRect.scaleY(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -428,7 +427,7 @@ export class CanvasLayer {
|
||||
// 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. In this case, we should reset the layer
|
||||
// so we aren't drawing shapes that do not render anything.
|
||||
if (this.width === 0 || this.height === 0) {
|
||||
if (this.bbox.width === 0 || this.bbox.height === 0) {
|
||||
this.manager.stateApi.onEntityReset({ id: this.id }, 'layer');
|
||||
return;
|
||||
}
|
||||
@ -437,17 +436,23 @@ export class CanvasLayer {
|
||||
const bboxPadding = this.manager.getScaledBboxPadding();
|
||||
|
||||
this.konva.bbox.setAttrs({
|
||||
x: this.state.position.x + this.offsetX * this.konva.interactionRect.scaleX() - bboxPadding,
|
||||
y: this.state.position.y + this.offsetY * this.konva.interactionRect.scaleY() - bboxPadding,
|
||||
width: this.width + bboxPadding * 2,
|
||||
height: this.height + bboxPadding * 2,
|
||||
x: this.state.position.x + this.bbox.x - bboxPadding,
|
||||
y: this.state.position.y + this.bbox.y - bboxPadding,
|
||||
width: this.bbox.width + bboxPadding * 2,
|
||||
height: this.bbox.height + bboxPadding * 2,
|
||||
strokeWidth: onePixel,
|
||||
});
|
||||
this.konva.interactionRect.setAttrs({
|
||||
x: this.state.position.x + this.offsetX * this.konva.interactionRect.scaleX(),
|
||||
y: this.state.position.y + this.offsetY * this.konva.interactionRect.scaleY(),
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
x: this.state.position.x + this.bbox.x,
|
||||
y: this.state.position.y + this.bbox.y,
|
||||
width: this.bbox.width,
|
||||
height: this.bbox.height,
|
||||
});
|
||||
this.konva.objectGroup.setAttrs({
|
||||
x: this.state.position.x + this.bbox.x,
|
||||
y: this.state.position.y + this.bbox.y,
|
||||
offsetX: this.bbox.x,
|
||||
offsetY: this.bbox.y,
|
||||
});
|
||||
}
|
||||
|
||||
@ -550,11 +555,14 @@ export class CanvasLayer {
|
||||
|
||||
async resetScale() {
|
||||
this.konva.objectGroup.scaleX(1);
|
||||
this.konva.objectGroup.scaleY(1);
|
||||
this.konva.objectGroup.scaleX(1);
|
||||
this.konva.objectGroup.rotation(0);
|
||||
this.konva.bbox.scaleX(1);
|
||||
this.konva.bbox.scaleY(1);
|
||||
this.konva.bbox.scaleX(1);
|
||||
this.konva.bbox.rotation(0);
|
||||
this.konva.interactionRect.scaleX(1);
|
||||
this.konva.interactionRect.scaleY(1);
|
||||
this.konva.interactionRect.scaleX(1);
|
||||
this.konva.interactionRect.rotation(0);
|
||||
}
|
||||
|
||||
async applyTransform() {
|
||||
@ -562,13 +570,7 @@ export class CanvasLayer {
|
||||
|
||||
this.isTransforming = false;
|
||||
const objectGroupClone = this.konva.objectGroup.clone();
|
||||
const rect = {
|
||||
x: this.konva.interactionRect.x(),
|
||||
y: this.konva.interactionRect.y(),
|
||||
width: this.konva.interactionRect.width() * this.konva.interactionRect.scaleX(),
|
||||
height: this.konva.interactionRect.height() * this.konva.interactionRect.scaleY(),
|
||||
};
|
||||
const blob = await konvaNodeToBlob(objectGroupClone, rect);
|
||||
const blob = await konvaNodeToBlob(objectGroupClone, objectGroupClone.getClientRect());
|
||||
previewBlob(blob, 'transformed layer');
|
||||
const imageDTO = await uploadImage(blob, `${this.id}_transform.png`, 'other', true, true);
|
||||
const { dispatch } = getStore();
|
||||
@ -590,14 +592,16 @@ export class CanvasLayer {
|
||||
});
|
||||
}
|
||||
|
||||
getDefaultRect(): Rect {
|
||||
return { x: 0, y: 0, width: 0, height: 0 };
|
||||
}
|
||||
|
||||
calculateBbox = debounce(() => {
|
||||
this.log.debug('Calculating bbox');
|
||||
|
||||
if (this.objects.size === 0) {
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.rect = this.getDefaultRect();
|
||||
this.bbox = this.getDefaultRect();
|
||||
this.updateBbox();
|
||||
return;
|
||||
}
|
||||
@ -605,8 +609,6 @@ export class CanvasLayer {
|
||||
let needsPixelBbox = false;
|
||||
const rect = this.konva.objectGroup.getClientRect({ skipTransform: true });
|
||||
|
||||
console.log('getBbox rect', rect);
|
||||
|
||||
/**
|
||||
* In some cases, we can use konva's getClientRect as the bbox, but there are some cases where we need to calculate
|
||||
* the bbox using pixel data:
|
||||
@ -628,11 +630,9 @@ export class CanvasLayer {
|
||||
}
|
||||
|
||||
if (!needsPixelBbox) {
|
||||
this.offsetX = rect.x;
|
||||
this.offsetY = rect.y;
|
||||
this.width = rect.width;
|
||||
this.height = rect.height;
|
||||
this.logBbox('new bbox from client rect');
|
||||
this.rect = deepClone(rect);
|
||||
this.bbox = deepClone(rect);
|
||||
this.log.trace({ bbox: this.bbox, rect: this.rect }, 'Got bbox from client rect');
|
||||
this.updateBbox();
|
||||
return;
|
||||
}
|
||||
@ -649,20 +649,19 @@ export class CanvasLayer {
|
||||
this.manager.requestBbox(
|
||||
{ buffer: imageData.data.buffer, width: imageData.width, height: imageData.height },
|
||||
(extents) => {
|
||||
console.log('extents', extents);
|
||||
this.rect = deepClone(rect);
|
||||
if (extents) {
|
||||
const { minX, minY, maxX, maxY } = extents;
|
||||
this.offsetX = minX + rect.x;
|
||||
this.offsetY = minY + rect.y;
|
||||
this.width = maxX - minX;
|
||||
this.height = maxY - minY;
|
||||
this.bbox = {
|
||||
x: rect.x + minX,
|
||||
y: rect.y + minY,
|
||||
width: maxX - minX,
|
||||
height: maxY - minY,
|
||||
};
|
||||
} else {
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.bbox = deepClone(rect);
|
||||
}
|
||||
this.logBbox('new bbox from worker');
|
||||
this.log.trace({ bbox: this.bbox, rect: this.rect, extents }, `Got bbox from worker`);
|
||||
this.updateBbox();
|
||||
clone.destroy();
|
||||
}
|
||||
@ -673,19 +672,8 @@ export class CanvasLayer {
|
||||
console.log(msg, {
|
||||
x: this.state.position.x,
|
||||
y: this.state.position.y,
|
||||
offsetX: this.offsetX,
|
||||
offsetY: this.offsetY,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
rect: deepClone(this.rect),
|
||||
bbox: deepClone(this.bbox),
|
||||
});
|
||||
}
|
||||
|
||||
getLayerRect() {
|
||||
return {
|
||||
x: this.state.position.x + this.offsetX,
|
||||
y: this.state.position.y + this.offsetY,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user