mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): fix bbox caching
This commit is contained in:
parent
1e904d281a
commit
148a6c08ca
@ -229,8 +229,8 @@ export const regionalPromptsSlice = createSlice({
|
|||||||
strokeWidth: state.brushSize,
|
strokeWidth: state.brushSize,
|
||||||
});
|
});
|
||||||
layer.bboxNeedsUpdate = true;
|
layer.bboxNeedsUpdate = true;
|
||||||
if (!layer.hasEraserStrokes) {
|
if (!layer.hasEraserStrokes && tool === 'eraser') {
|
||||||
layer.hasEraserStrokes = tool === 'eraser';
|
layer.hasEraserStrokes = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import openBase64ImageInTab from 'common/util/openBase64ImageInTab';
|
import openBase64ImageInTab from 'common/util/openBase64ImageInTab';
|
||||||
import { imageDataToDataURL } from 'features/canvas/util/blobToDataURL';
|
import { imageDataToDataURL } from 'features/canvas/util/blobToDataURL';
|
||||||
|
import { REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import type { Layer as KonvaLayerType } from 'konva/lib/Layer';
|
import type { Layer as KonvaLayerType } from 'konva/lib/Layer';
|
||||||
import type { Node as KonvaNodeType, NodeConfig as KonvaNodeConfigType } from 'konva/lib/Node';
|
|
||||||
import type { IRect } from 'konva/lib/types';
|
import type { IRect } from 'konva/lib/types';
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
@ -57,11 +57,7 @@ const getImageDataBbox = (imageData: ImageData): Extents | null => {
|
|||||||
* @param filterChildren Optional filter function to exclude certain children from the bounding box calculation. Defaults to including all children.
|
* @param filterChildren Optional filter function to exclude certain children from the bounding box calculation. Defaults to including all children.
|
||||||
* @param preview Whether to open a new tab displaying the rendered layer, which is used to calculate the bbox.
|
* @param preview Whether to open a new tab displaying the rendered layer, which is used to calculate the bbox.
|
||||||
*/
|
*/
|
||||||
export const getKonvaLayerBbox = (
|
export const getKonvaLayerBbox = (layer: KonvaLayerType, preview: boolean = false): IRect | null => {
|
||||||
layer: KonvaLayerType,
|
|
||||||
filterChildren?: (item: KonvaNodeType<KonvaNodeConfigType>) => boolean,
|
|
||||||
preview: boolean = false
|
|
||||||
): IRect | null => {
|
|
||||||
// To calculate the layer's bounding box, we must first export it to a pixel array, then do some math.
|
// To calculate the layer's bounding box, we must first export it to a pixel array, then do some math.
|
||||||
//
|
//
|
||||||
// Though it is relatively fast, we can't use Konva's `getClientRect`. It programmatically determines the rect
|
// Though it is relatively fast, we can't use Konva's `getClientRect`. It programmatically determines the rect
|
||||||
@ -69,7 +65,6 @@ export const getKonvaLayerBbox = (
|
|||||||
//
|
//
|
||||||
// This doesn't work when some shapes are drawn with composite operations that "erase" pixels, like eraser lines.
|
// This doesn't work when some shapes are drawn with composite operations that "erase" pixels, like eraser lines.
|
||||||
// These shapes' extents are still calculated as if they were solid, leading to a bounding box that is too large.
|
// These shapes' extents are still calculated as if they were solid, leading to a bounding box that is too large.
|
||||||
|
|
||||||
const stage = layer.getStage();
|
const stage = layer.getStage();
|
||||||
|
|
||||||
// Construct and offscreen canvas on which we will do the bbox calculations.
|
// Construct and offscreen canvas on which we will do the bbox calculations.
|
||||||
@ -84,8 +79,12 @@ export const getKonvaLayerBbox = (
|
|||||||
const layerClone = layer.clone();
|
const layerClone = layer.clone();
|
||||||
offscreenStage.add(layerClone);
|
offscreenStage.add(layerClone);
|
||||||
|
|
||||||
if (filterChildren) {
|
for (const child of layerClone.getChildren()) {
|
||||||
for (const child of layerClone.getChildren(filterChildren)) {
|
if (child.name() === REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME) {
|
||||||
|
// We need to cache the group to ensure it composites out eraser strokes correctly
|
||||||
|
child.cache();
|
||||||
|
} else {
|
||||||
|
// Filter out unwanted children.
|
||||||
child.destroy();
|
child.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ import {
|
|||||||
} from 'features/regionalPrompts/store/regionalPromptsSlice';
|
} from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
import { getKonvaLayerBbox } from 'features/regionalPrompts/util/bbox';
|
import { getKonvaLayerBbox } from 'features/regionalPrompts/util/bbox';
|
||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import type { Node, NodeConfig } from 'konva/lib/Node';
|
|
||||||
import type { IRect, Vector2d } from 'konva/lib/types';
|
import type { IRect, Vector2d } from 'konva/lib/types';
|
||||||
import type { RgbColor } from 'react-colorful';
|
import type { RgbColor } from 'react-colorful';
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
@ -30,9 +29,6 @@ const BRUSH_PREVIEW_BORDER_OUTER_COLOR = 'rgba(255,255,255,0.8)';
|
|||||||
const GET_CLIENT_RECT_CONFIG = { skipTransform: true };
|
const GET_CLIENT_RECT_CONFIG = { skipTransform: true };
|
||||||
|
|
||||||
const mapId = (object: { id: string }) => object.id;
|
const mapId = (object: { id: string }) => object.id;
|
||||||
const selectPromptLayerObjectGroup = (item: Node<NodeConfig>) => {
|
|
||||||
return item.name() !== REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME;
|
|
||||||
};
|
|
||||||
const getIsSelected = (layerId?: string | null) => {
|
const getIsSelected = (layerId?: string | null) => {
|
||||||
if (!layerId) {
|
if (!layerId) {
|
||||||
return false;
|
return false;
|
||||||
@ -345,7 +341,7 @@ export const renderBbox = (
|
|||||||
if (reduxLayer.bboxNeedsUpdate && reduxLayer.objects.length) {
|
if (reduxLayer.bboxNeedsUpdate && reduxLayer.objects.length) {
|
||||||
// We only need to use the pixel-perfect bounding box if the layer has eraser strokes
|
// We only need to use the pixel-perfect bounding box if the layer has eraser strokes
|
||||||
bbox = reduxLayer.hasEraserStrokes
|
bbox = reduxLayer.hasEraserStrokes
|
||||||
? getKonvaLayerBbox(konvaLayer, selectPromptLayerObjectGroup)
|
? getKonvaLayerBbox(konvaLayer)
|
||||||
: konvaLayer.getClientRect(GET_CLIENT_RECT_CONFIG);
|
: konvaLayer.getClientRect(GET_CLIENT_RECT_CONFIG);
|
||||||
|
|
||||||
// Update the layer's bbox in the redux store
|
// Update the layer's bbox in the redux store
|
||||||
@ -382,6 +378,7 @@ export const renderBbox = (
|
|||||||
});
|
});
|
||||||
konvaLayer.add(rect);
|
konvaLayer.add(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
rect.setAttrs({
|
rect.setAttrs({
|
||||||
visible: true,
|
visible: true,
|
||||||
listening: true,
|
listening: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user