feat(ui): buffered rect drawing

This commit is contained in:
psychedelicious 2024-07-05 10:14:52 +10:00
parent 908e504a6f
commit 3f6ee1b7a4
10 changed files with 150 additions and 57 deletions

View File

@ -6,7 +6,7 @@ import { CanvasRect } from 'features/controlLayers/konva/CanvasRect';
import { getNodeBboxFast } from 'features/controlLayers/konva/entityBbox'; import { getNodeBboxFast } from 'features/controlLayers/konva/entityBbox';
import { getObjectGroupId, INPAINT_MASK_LAYER_ID } from 'features/controlLayers/konva/naming'; import { getObjectGroupId, INPAINT_MASK_LAYER_ID } from 'features/controlLayers/konva/naming';
import { mapId } from 'features/controlLayers/konva/util'; import { mapId } from 'features/controlLayers/konva/util';
import type { BrushLine, EraserLine, InpaintMaskEntity } from 'features/controlLayers/store/types'; import type { BrushLine, EraserLine, InpaintMaskEntity, RectShape } from 'features/controlLayers/store/types';
import { isDrawingTool, RGBA_RED } from 'features/controlLayers/store/types'; import { isDrawingTool, RGBA_RED } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
import { assert } from 'tsafe'; import { assert } from 'tsafe';
@ -21,7 +21,7 @@ export class CanvasInpaintMask {
compositingRect: Konva.Rect; compositingRect: Konva.Rect;
transformer: Konva.Transformer; transformer: Konva.Transformer;
objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect>; objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect>;
private drawingBuffer: BrushLine | EraserLine | null; private drawingBuffer: BrushLine | EraserLine | RectShape | null;
private inpaintMaskState: InpaintMaskEntity; private inpaintMaskState: InpaintMaskEntity;
constructor(entity: InpaintMaskEntity, manager: CanvasManager) { constructor(entity: InpaintMaskEntity, manager: CanvasManager) {
@ -71,7 +71,7 @@ export class CanvasInpaintMask {
return this.drawingBuffer; return this.drawingBuffer;
} }
async setDrawingBuffer(obj: BrushLine | EraserLine | null) { async setDrawingBuffer(obj: BrushLine | EraserLine | RectShape | null) {
this.drawingBuffer = obj; this.drawingBuffer = obj;
if (this.drawingBuffer) { if (this.drawingBuffer) {
if (this.drawingBuffer.type === 'brush_line') { if (this.drawingBuffer.type === 'brush_line') {
@ -91,6 +91,8 @@ export class CanvasInpaintMask {
this.manager.stateApi.onBrushLineAdded2({ id: this.id, brushLine: this.drawingBuffer }, 'inpaint_mask'); this.manager.stateApi.onBrushLineAdded2({ id: this.id, brushLine: this.drawingBuffer }, 'inpaint_mask');
} else if (this.drawingBuffer.type === 'eraser_line') { } else if (this.drawingBuffer.type === 'eraser_line') {
this.manager.stateApi.onEraserLineAdded2({ id: this.id, eraserLine: this.drawingBuffer }, 'inpaint_mask'); this.manager.stateApi.onEraserLineAdded2({ id: this.id, eraserLine: this.drawingBuffer }, 'inpaint_mask');
} else if (this.drawingBuffer.type === 'rect_shape') {
this.manager.stateApi.onRectShapeAdded2({ id: this.id, rectShape: this.drawingBuffer }, 'layer');
} }
this.setDrawingBuffer(null); this.setDrawingBuffer(null);
} }

View File

@ -5,7 +5,7 @@ import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import { CanvasRect } from 'features/controlLayers/konva/CanvasRect'; import { CanvasRect } from 'features/controlLayers/konva/CanvasRect';
import { getObjectGroupId } from 'features/controlLayers/konva/naming'; import { getObjectGroupId } from 'features/controlLayers/konva/naming';
import { mapId } from 'features/controlLayers/konva/util'; import { mapId } from 'features/controlLayers/konva/util';
import type { BrushLine, EraserLine, LayerEntity } from 'features/controlLayers/store/types'; import type { BrushLine, EraserLine, LayerEntity, RectShape } from 'features/controlLayers/store/types';
import { isDrawingTool } from 'features/controlLayers/store/types'; import { isDrawingTool } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
import { assert } from 'tsafe'; import { assert } from 'tsafe';
@ -19,7 +19,7 @@ export class CanvasLayer {
objectsGroup: Konva.Group; objectsGroup: Konva.Group;
transformer: Konva.Transformer; transformer: Konva.Transformer;
objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect | CanvasImage>; objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect | CanvasImage>;
private drawingBuffer: BrushLine | EraserLine | null; private drawingBuffer: BrushLine | EraserLine | RectShape | null;
private layerState: LayerEntity; private layerState: LayerEntity;
constructor(entity: LayerEntity, manager: CanvasManager) { constructor(entity: LayerEntity, manager: CanvasManager) {
@ -70,7 +70,7 @@ export class CanvasLayer {
return this.drawingBuffer; return this.drawingBuffer;
} }
async setDrawingBuffer(obj: BrushLine | EraserLine | null) { async setDrawingBuffer(obj: BrushLine | EraserLine | RectShape | null) {
if (obj) { if (obj) {
this.drawingBuffer = obj; this.drawingBuffer = obj;
await this.renderObject(this.drawingBuffer, true); await this.renderObject(this.drawingBuffer, true);
@ -88,6 +88,8 @@ export class CanvasLayer {
this.manager.stateApi.onBrushLineAdded2({ id: this.id, brushLine: this.drawingBuffer }, 'layer'); this.manager.stateApi.onBrushLineAdded2({ id: this.id, brushLine: this.drawingBuffer }, 'layer');
} else if (this.drawingBuffer.type === 'eraser_line') { } else if (this.drawingBuffer.type === 'eraser_line') {
this.manager.stateApi.onEraserLineAdded2({ id: this.id, eraserLine: this.drawingBuffer }, 'layer'); this.manager.stateApi.onEraserLineAdded2({ id: this.id, eraserLine: this.drawingBuffer }, 'layer');
} else if (this.drawingBuffer.type === 'rect_shape') {
this.manager.stateApi.onRectShapeAdded2({ id: this.id, rectShape: this.drawingBuffer }, 'layer');
} }
this.setDrawingBuffer(null); this.setDrawingBuffer(null);
} }

View File

@ -6,7 +6,7 @@ import { CanvasRect } from 'features/controlLayers/konva/CanvasRect';
import { getNodeBboxFast } from 'features/controlLayers/konva/entityBbox'; import { getNodeBboxFast } from 'features/controlLayers/konva/entityBbox';
import { getObjectGroupId } from 'features/controlLayers/konva/naming'; import { getObjectGroupId } from 'features/controlLayers/konva/naming';
import { mapId } from 'features/controlLayers/konva/util'; import { mapId } from 'features/controlLayers/konva/util';
import type { BrushLine, EraserLine, RegionEntity } from 'features/controlLayers/store/types'; import type { BrushLine, EraserLine, RectShape, RegionEntity } from 'features/controlLayers/store/types';
import { isDrawingTool, RGBA_RED } from 'features/controlLayers/store/types'; import { isDrawingTool, RGBA_RED } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
import { assert } from 'tsafe'; import { assert } from 'tsafe';
@ -21,7 +21,7 @@ export class CanvasRegion {
compositingRect: Konva.Rect; compositingRect: Konva.Rect;
transformer: Konva.Transformer; transformer: Konva.Transformer;
objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect>; objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect>;
private drawingBuffer: BrushLine | EraserLine | null; private drawingBuffer: BrushLine | EraserLine | RectShape | null;
private regionState: RegionEntity; private regionState: RegionEntity;
constructor(entity: RegionEntity, manager: CanvasManager) { constructor(entity: RegionEntity, manager: CanvasManager) {
@ -71,7 +71,7 @@ export class CanvasRegion {
return this.drawingBuffer; return this.drawingBuffer;
} }
async setDrawingBuffer(obj: BrushLine | EraserLine | null) { async setDrawingBuffer(obj: BrushLine | EraserLine | RectShape | null) {
this.drawingBuffer = obj; this.drawingBuffer = obj;
if (this.drawingBuffer) { if (this.drawingBuffer) {
if (this.drawingBuffer.type === 'brush_line') { if (this.drawingBuffer.type === 'brush_line') {
@ -90,6 +90,8 @@ export class CanvasRegion {
this.manager.stateApi.onBrushLineAdded2({ id: this.id, brushLine: this.drawingBuffer }, 'regional_guidance'); this.manager.stateApi.onBrushLineAdded2({ id: this.id, brushLine: this.drawingBuffer }, 'regional_guidance');
} else if (this.drawingBuffer.type === 'eraser_line') { } else if (this.drawingBuffer.type === 'eraser_line') {
this.manager.stateApi.onEraserLineAdded2({ id: this.id, eraserLine: this.drawingBuffer }, 'regional_guidance'); this.manager.stateApi.onEraserLineAdded2({ id: this.id, eraserLine: this.drawingBuffer }, 'regional_guidance');
} else if (this.drawingBuffer.type === 'rect_shape') {
this.manager.stateApi.onRectShapeAdded2({ id: this.id, rectShape: this.drawingBuffer }, 'layer');
} }
this.setDrawingBuffer(null); this.setDrawingBuffer(null);
} }

View File

@ -25,6 +25,7 @@ import {
imImageCacheChanged, imImageCacheChanged,
imLinePointAdded, imLinePointAdded,
imRectAdded, imRectAdded,
imRectShapeAdded2,
imScaled, imScaled,
imTranslated, imTranslated,
layerBboxChanged, layerBboxChanged,
@ -35,6 +36,7 @@ import {
layerImageCacheChanged, layerImageCacheChanged,
layerLinePointAdded, layerLinePointAdded,
layerRectAdded, layerRectAdded,
layerRectShapeAdded2,
layerScaled, layerScaled,
layerTranslated, layerTranslated,
rgBboxChanged, rgBboxChanged,
@ -45,6 +47,7 @@ import {
rgImageCacheChanged, rgImageCacheChanged,
rgLinePointAdded, rgLinePointAdded,
rgRectAdded, rgRectAdded,
rgRectShapeAdded2,
rgScaled, rgScaled,
rgTranslated, rgTranslated,
toolBufferChanged, toolBufferChanged,
@ -59,6 +62,7 @@ import type {
EraserLineAddedArg, EraserLineAddedArg,
PointAddedToLineArg, PointAddedToLineArg,
PosChangedArg, PosChangedArg,
RectShape,
RectShapeAddedArg, RectShapeAddedArg,
ScaleChangedArg, ScaleChangedArg,
Tool, Tool,
@ -175,6 +179,16 @@ export class CanvasStateApi {
this.store.dispatch(imRectAdded(arg)); this.store.dispatch(imRectAdded(arg));
} }
}; };
onRectShapeAdded2 = (arg: { id: string; rectShape: RectShape }, entityType: CanvasEntity['type']) => {
log.debug('Rect shape added');
if (entityType === 'layer') {
this.store.dispatch(layerRectShapeAdded2(arg));
} else if (entityType === 'regional_guidance') {
this.store.dispatch(rgRectShapeAdded2(arg));
} else if (entityType === 'inpaint_mask') {
this.store.dispatch(imRectShapeAdded2(arg));
}
};
onBboxTransformed = (bbox: IRect) => { onBboxTransformed = (bbox: IRect) => {
log.debug('Generation bbox transformed'); log.debug('Generation bbox transformed');
this.store.dispatch(bboxChanged(bbox)); this.store.dispatch(bboxChanged(bbox));

View File

@ -5,7 +5,6 @@ import {
BRUSH_BORDER_OUTER_COLOR, BRUSH_BORDER_OUTER_COLOR,
BRUSH_ERASER_BORDER_WIDTH, BRUSH_ERASER_BORDER_WIDTH,
} from 'features/controlLayers/konva/constants'; } from 'features/controlLayers/konva/constants';
import { PREVIEW_RECT_ID } from 'features/controlLayers/konva/naming';
import Konva from 'konva'; import Konva from 'konva';
export class CanvasTool { export class CanvasTool {
@ -23,10 +22,10 @@ export class CanvasTool {
innerBorderCircle: Konva.Circle; innerBorderCircle: Konva.Circle;
outerBorderCircle: Konva.Circle; outerBorderCircle: Konva.Circle;
}; };
rect: { // rect: {
group: Konva.Group; // group: Konva.Group;
fillRect: Konva.Rect; // fillRect: Konva.Rect;
}; // };
constructor(manager: CanvasManager) { constructor(manager: CanvasManager) {
this.manager = manager; this.manager = manager;
@ -83,17 +82,17 @@ export class CanvasTool {
this.eraser.group.add(this.eraser.outerBorderCircle); this.eraser.group.add(this.eraser.outerBorderCircle);
this.group.add(this.eraser.group); this.group.add(this.eraser.group);
// Create the rect preview - this is a rectangle drawn from the last mouse down position to the current cursor position // // Create the rect preview - this is a rectangle drawn from the last mouse down position to the current cursor position
this.rect = { // this.rect = {
group: new Konva.Group(), // group: new Konva.Group(),
fillRect: new Konva.Rect({ // fillRect: new Konva.Rect({
id: PREVIEW_RECT_ID, // id: PREVIEW_RECT_ID,
listening: false, // listening: false,
strokeEnabled: false, // strokeEnabled: false,
}), // }),
}; // };
this.rect.group.add(this.rect.fillRect); // this.rect.group.add(this.rect.fillRect);
this.group.add(this.rect.group); // this.group.add(this.rect.group);
} }
scaleTool = () => { scaleTool = () => {
@ -189,7 +188,7 @@ export class CanvasTool {
this.brush.group.visible(true); this.brush.group.visible(true);
this.eraser.group.visible(false); this.eraser.group.visible(false);
this.rect.group.visible(false); // this.rect.group.visible(false);
} else if (cursorPos && tool === 'eraser') { } else if (cursorPos && tool === 'eraser') {
const scale = stage.scaleX(); const scale = stage.scaleX();
// Update the fill circle // Update the fill circle
@ -215,23 +214,23 @@ export class CanvasTool {
this.brush.group.visible(false); this.brush.group.visible(false);
this.eraser.group.visible(true); this.eraser.group.visible(true);
this.rect.group.visible(false); // this.rect.group.visible(false);
} else if (cursorPos && lastMouseDownPos && tool === 'rect') { // } else if (cursorPos && lastMouseDownPos && tool === 'rect') {
this.rect.fillRect.setAttrs({ // this.rect.fillRect.setAttrs({
x: Math.min(cursorPos.x, lastMouseDownPos.x), // x: Math.min(cursorPos.x, lastMouseDownPos.x),
y: Math.min(cursorPos.y, lastMouseDownPos.y), // y: Math.min(cursorPos.y, lastMouseDownPos.y),
width: Math.abs(cursorPos.x - lastMouseDownPos.x), // width: Math.abs(cursorPos.x - lastMouseDownPos.x),
height: Math.abs(cursorPos.y - lastMouseDownPos.y), // height: Math.abs(cursorPos.y - lastMouseDownPos.y),
fill: rgbaColorToString(currentFill), // fill: rgbaColorToString(currentFill),
visible: true, // visible: true,
}); // });
this.brush.group.visible(false); // this.brush.group.visible(false);
this.eraser.group.visible(false); // this.eraser.group.visible(false);
this.rect.group.visible(true); // this.rect.group.visible(true);
} else { } else {
this.brush.group.visible(false); this.brush.group.visible(false);
this.eraser.group.visible(false); this.eraser.group.visible(false);
this.rect.group.visible(false); // this.rect.group.visible(false);
} }
} }
} }

View File

@ -16,7 +16,7 @@ import { clamp } from 'lodash-es';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { BRUSH_SPACING_TARGET_SCALE, CANVAS_SCALE_BY, MAX_CANVAS_SCALE, MIN_CANVAS_SCALE } from './constants'; import { BRUSH_SPACING_TARGET_SCALE, CANVAS_SCALE_BY, MAX_CANVAS_SCALE, MIN_CANVAS_SCALE } from './constants';
import { getBrushLineId, getEraserLineId } from './naming'; import { getBrushLineId, getEraserLineId, getRectShapeId } from './naming';
/** /**
* Updates the last cursor position atom with the current cursor position, returning the new position or `null` if the * Updates the last cursor position atom with the current cursor position, returning the new position or `null` if the
@ -267,6 +267,21 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
} }
setLastAddedPoint(pos); setLastAddedPoint(pos);
} }
if (toolState.selected === 'rect') {
if (selectedEntityAdapter.getDrawingBuffer()) {
selectedEntityAdapter.finalizeDrawingBuffer();
}
await selectedEntityAdapter.setDrawingBuffer({
id: getRectShapeId(selectedEntityAdapter.id, uuidv4()),
type: 'rect_shape',
x: pos.x - selectedEntity.x,
y: pos.y - selectedEntity.y,
width: 0,
height: 0,
color: getCurrentFill(),
});
}
} }
manager.preview.tool.render(); manager.preview.tool.render();
}); });
@ -284,7 +299,8 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
isDrawableEntity(selectedEntity) && isDrawableEntity(selectedEntity) &&
selectedEntityAdapter && selectedEntityAdapter &&
isDrawableEntityAdapter(selectedEntityAdapter) && isDrawableEntityAdapter(selectedEntityAdapter) &&
!getSpaceKey() !getSpaceKey() &&
getIsPrimaryMouseDown(e)
) { ) {
const toolState = getToolState(); const toolState = getToolState();
@ -307,22 +323,28 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
} }
if (toolState.selected === 'rect') { if (toolState.selected === 'rect') {
const lastMouseDownPos = getLastMouseDownPos(); const drawingBuffer = selectedEntityAdapter.getDrawingBuffer();
if (lastMouseDownPos) { if (drawingBuffer?.type === 'rect_shape') {
onRectShapeAdded( selectedEntityAdapter.finalizeDrawingBuffer();
{ } else {
id: selectedEntity.id, await selectedEntityAdapter.setDrawingBuffer(null);
rect: {
x: Math.min(pos.x - selectedEntity.x, lastMouseDownPos.x - selectedEntity.x),
y: Math.min(pos.y - selectedEntity.y, lastMouseDownPos.y - selectedEntity.y),
width: Math.abs(pos.x - lastMouseDownPos.x),
height: Math.abs(pos.y - lastMouseDownPos.y),
},
color: getCurrentFill(),
},
selectedEntity.type
);
} }
// const lastMouseDownPos = getLastMouseDownPos();
// if (lastMouseDownPos) {
// onRectShapeAdded(
// {
// id: selectedEntity.id,
// rect: {
// x: Math.min(pos.x - selectedEntity.x, lastMouseDownPos.x - selectedEntity.x),
// y: Math.min(pos.y - selectedEntity.y, lastMouseDownPos.y - selectedEntity.y),
// width: Math.abs(pos.x - lastMouseDownPos.x),
// height: Math.abs(pos.y - lastMouseDownPos.y),
// },
// color: getCurrentFill(),
// },
// selectedEntity.type
// );
// }
} }
setLastMouseDownPos(null); setLastMouseDownPos(null);
@ -415,6 +437,19 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
setLastAddedPoint(pos); setLastAddedPoint(pos);
} }
} }
if (toolState.selected === 'rect') {
const drawingBuffer = selectedEntityAdapter.getDrawingBuffer();
if (drawingBuffer) {
if (drawingBuffer.type === 'rect_shape') {
drawingBuffer.width = pos.x - selectedEntity.x - drawingBuffer.x;
drawingBuffer.height = pos.y - selectedEntity.y - drawingBuffer.y;
await selectedEntityAdapter.setDrawingBuffer(drawingBuffer);
} else {
await selectedEntityAdapter.setDrawingBuffer(null);
}
}
}
} }
manager.preview.tool.render(); manager.preview.tool.render();
}); });
@ -446,6 +481,11 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
drawingBuffer.points.push(pos.x - selectedEntity.x, pos.y - selectedEntity.y); drawingBuffer.points.push(pos.x - selectedEntity.x, pos.y - selectedEntity.y);
await selectedEntityAdapter.setDrawingBuffer(drawingBuffer); await selectedEntityAdapter.setDrawingBuffer(drawingBuffer);
selectedEntityAdapter.finalizeDrawingBuffer(); selectedEntityAdapter.finalizeDrawingBuffer();
} else if (toolState.selected === 'rect' && drawingBuffer?.type === 'rect_shape') {
drawingBuffer.width = pos.x - selectedEntity.x - drawingBuffer.x;
drawingBuffer.height = pos.y - selectedEntity.y - drawingBuffer.y;
await selectedEntityAdapter.setDrawingBuffer(drawingBuffer);
selectedEntityAdapter.finalizeDrawingBuffer();
} }
} }

View File

@ -349,10 +349,13 @@ export const {
stagingAreaPreviousImageSelected, stagingAreaPreviousImageSelected,
layerBrushLineAdded2, layerBrushLineAdded2,
layerEraserLineAdded2, layerEraserLineAdded2,
layerRectShapeAdded2,
rgBrushLineAdded2, rgBrushLineAdded2,
rgEraserLineAdded2, rgEraserLineAdded2,
rgRectShapeAdded2,
imBrushLineAdded2, imBrushLineAdded2,
imEraserLineAdded2, imEraserLineAdded2,
imRectShapeAdded2,
} = canvasV2Slice.actions; } = canvasV2Slice.actions;
export const selectCanvasV2Slice = (state: RootState) => state.canvasV2; export const selectCanvasV2Slice = (state: RootState) => state.canvasV2;

View File

@ -5,6 +5,7 @@ import type {
CanvasV2State, CanvasV2State,
EraserLine, EraserLine,
InpaintMaskEntity, InpaintMaskEntity,
RectShape,
ScaleChangedArg, ScaleChangedArg,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { imageDTOToImageWithDims, RGBA_RED } from 'features/controlLayers/store/types'; import { imageDTOToImageWithDims, RGBA_RED } from 'features/controlLayers/store/types';
@ -99,6 +100,12 @@ export const inpaintMaskReducers = {
state.inpaintMask.bboxNeedsUpdate = true; state.inpaintMask.bboxNeedsUpdate = true;
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
imRectShapeAdded2: (state, action: PayloadAction<{ rectShape: RectShape }>) => {
const { rectShape } = action.payload;
state.inpaintMask.objects.push(rectShape);
state.inpaintMask.bboxNeedsUpdate = true;
state.layers.imageCache = null;
},
imEraserLineAdded: { imEraserLineAdded: {
reducer: (state, action: PayloadAction<Omit<EraserLineAddedArg, 'id'> & { lineId: string }>) => { reducer: (state, action: PayloadAction<Omit<EraserLineAddedArg, 'id'> & { lineId: string }>) => {
const { points, lineId, width, clip } = action.payload; const { points, lineId, width, clip } = action.payload;

View File

@ -15,6 +15,7 @@ import type {
ImageObjectAddedArg, ImageObjectAddedArg,
LayerEntity, LayerEntity,
PointAddedToLineArg, PointAddedToLineArg,
RectShape,
RectShapeAddedArg, RectShapeAddedArg,
ScaleChangedArg, ScaleChangedArg,
} from './types'; } from './types';
@ -176,6 +177,17 @@ export const layersReducers = {
layer.bboxNeedsUpdate = true; layer.bboxNeedsUpdate = true;
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
layerRectShapeAdded2: (state, action: PayloadAction<{ id: string; rectShape: RectShape }>) => {
const { id, rectShape } = action.payload;
const layer = selectLayer(state, id);
if (!layer) {
return;
}
layer.objects.push(rectShape);
layer.bboxNeedsUpdate = true;
state.layers.imageCache = null;
},
layerBrushLineAdded: { layerBrushLineAdded: {
reducer: (state, action: PayloadAction<BrushLineAddedArg & { lineId: string }>) => { reducer: (state, action: PayloadAction<BrushLineAddedArg & { lineId: string }>) => {
const { id, points, lineId, color, width, clip } = action.payload; const { id, points, lineId, color, width, clip } = action.payload;

View File

@ -7,6 +7,7 @@ import type {
CLIPVisionModelV2, CLIPVisionModelV2,
EraserLine, EraserLine,
IPMethodV2, IPMethodV2,
RectShape,
ScaleChangedArg, ScaleChangedArg,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { imageDTOToImageObject, imageDTOToImageWithDims, RGBA_RED } from 'features/controlLayers/store/types'; import { imageDTOToImageObject, imageDTOToImageWithDims, RGBA_RED } from 'features/controlLayers/store/types';
@ -383,6 +384,17 @@ export const regionsReducers = {
rg.bboxNeedsUpdate = true; rg.bboxNeedsUpdate = true;
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
rgRectShapeAdded2: (state, action: PayloadAction<{ id: string; rectShape: RectShape }>) => {
const { id, rectShape } = action.payload;
const rg = selectRG(state, id);
if (!rg) {
return;
}
rg.objects.push(rectShape);
rg.bboxNeedsUpdate = true;
state.layers.imageCache = null;
},
rgEraserLineAdded: { rgEraserLineAdded: {
reducer: (state, action: PayloadAction<EraserLineAddedArg & { lineId: string }>) => { reducer: (state, action: PayloadAction<EraserLineAddedArg & { lineId: string }>) => {
const { id, points, lineId, width, clip } = action.payload; const { id, points, lineId, width, clip } = action.payload;