mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): clip lines to bbox
This commit is contained in:
parent
4dcab357a0
commit
fc5467150e
@ -116,7 +116,7 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
|
|||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
$toolState.set(tool);
|
$toolState.set(tool);
|
||||||
$selectedEntity.set(selectedEntity);
|
$selectedEntity.set(selectedEntity);
|
||||||
$bbox.set({ x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height });
|
$bbox.set(bbox);
|
||||||
$currentFill.set(currentFill);
|
$currentFill.set(currentFill);
|
||||||
$document.set(document);
|
$document.set(document);
|
||||||
}, [selectedEntity, tool, bbox, currentFill, document]);
|
}, [selectedEntity, tool, bbox, currentFill, document]);
|
||||||
@ -255,6 +255,7 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
|
|||||||
getSpaceKey: $spaceKey.get,
|
getSpaceKey: $spaceKey.get,
|
||||||
setStageAttrs: $stageAttrs.set,
|
setStageAttrs: $stageAttrs.set,
|
||||||
getDocument: $document.get,
|
getDocument: $document.get,
|
||||||
|
getBbox: $bbox.get,
|
||||||
onBrushLineAdded,
|
onBrushLineAdded,
|
||||||
onEraserLineAdded,
|
onEraserLineAdded,
|
||||||
onPointAddedToLine,
|
onPointAddedToLine,
|
||||||
|
@ -47,6 +47,7 @@ type Arg = {
|
|||||||
getSelectedEntity: () => CanvasEntity | null;
|
getSelectedEntity: () => CanvasEntity | null;
|
||||||
getSpaceKey: () => boolean;
|
getSpaceKey: () => boolean;
|
||||||
getDocument: () => CanvasV2State['document'];
|
getDocument: () => CanvasV2State['document'];
|
||||||
|
getBbox: () => CanvasV2State['bbox'];
|
||||||
onBrushLineAdded: (arg: BrushLineAddedArg, entityType: CanvasEntity['type']) => void;
|
onBrushLineAdded: (arg: BrushLineAddedArg, entityType: CanvasEntity['type']) => void;
|
||||||
onEraserLineAdded: (arg: EraserLineAddedArg, entityType: CanvasEntity['type']) => void;
|
onEraserLineAdded: (arg: EraserLineAddedArg, entityType: CanvasEntity['type']) => void;
|
||||||
onPointAddedToLine: (arg: PointAddedToLineArg, entityType: CanvasEntity['type']) => void;
|
onPointAddedToLine: (arg: PointAddedToLineArg, entityType: CanvasEntity['type']) => void;
|
||||||
@ -147,6 +148,7 @@ export const setStageEventHandlers = ({
|
|||||||
getSelectedEntity,
|
getSelectedEntity,
|
||||||
getSpaceKey,
|
getSpaceKey,
|
||||||
getDocument,
|
getDocument,
|
||||||
|
getBbox,
|
||||||
onBrushLineAdded,
|
onBrushLineAdded,
|
||||||
onEraserLineAdded,
|
onEraserLineAdded,
|
||||||
onPointAddedToLine,
|
onPointAddedToLine,
|
||||||
@ -190,6 +192,7 @@ export const setStageEventHandlers = ({
|
|||||||
setLastMouseDownPos(pos);
|
setLastMouseDownPos(pos);
|
||||||
|
|
||||||
if (toolState.selected === 'brush') {
|
if (toolState.selected === 'brush') {
|
||||||
|
const bbox = getBbox();
|
||||||
if (e.evt.shiftKey) {
|
if (e.evt.shiftKey) {
|
||||||
const lastAddedPoint = getLastAddedPoint();
|
const lastAddedPoint = getLastAddedPoint();
|
||||||
// Create a straight line if holding shift
|
// Create a straight line if holding shift
|
||||||
@ -205,6 +208,12 @@ export const setStageEventHandlers = ({
|
|||||||
],
|
],
|
||||||
color: getCurrentFill(),
|
color: getCurrentFill(),
|
||||||
width: toolState.brush.width,
|
width: toolState.brush.width,
|
||||||
|
clip: {
|
||||||
|
x: bbox.x,
|
||||||
|
y: bbox.y,
|
||||||
|
width: bbox.width,
|
||||||
|
height: bbox.height,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
selectedEntity.type
|
selectedEntity.type
|
||||||
);
|
);
|
||||||
@ -221,6 +230,12 @@ export const setStageEventHandlers = ({
|
|||||||
],
|
],
|
||||||
color: getCurrentFill(),
|
color: getCurrentFill(),
|
||||||
width: toolState.brush.width,
|
width: toolState.brush.width,
|
||||||
|
clip: {
|
||||||
|
x: bbox.x,
|
||||||
|
y: bbox.y,
|
||||||
|
width: bbox.width,
|
||||||
|
height: bbox.height,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
selectedEntity.type
|
selectedEntity.type
|
||||||
);
|
);
|
||||||
@ -229,6 +244,7 @@ export const setStageEventHandlers = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (toolState.selected === 'eraser') {
|
if (toolState.selected === 'eraser') {
|
||||||
|
const bbox = getBbox();
|
||||||
if (e.evt.shiftKey) {
|
if (e.evt.shiftKey) {
|
||||||
// Create a straight line if holding shift
|
// Create a straight line if holding shift
|
||||||
const lastAddedPoint = getLastAddedPoint();
|
const lastAddedPoint = getLastAddedPoint();
|
||||||
@ -243,6 +259,12 @@ export const setStageEventHandlers = ({
|
|||||||
pos.y - selectedEntity.y,
|
pos.y - selectedEntity.y,
|
||||||
],
|
],
|
||||||
width: toolState.eraser.width,
|
width: toolState.eraser.width,
|
||||||
|
clip: {
|
||||||
|
x: bbox.x,
|
||||||
|
y: bbox.y,
|
||||||
|
width: bbox.width,
|
||||||
|
height: bbox.height,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
selectedEntity.type
|
selectedEntity.type
|
||||||
);
|
);
|
||||||
@ -258,6 +280,12 @@ export const setStageEventHandlers = ({
|
|||||||
pos.y - selectedEntity.y,
|
pos.y - selectedEntity.y,
|
||||||
],
|
],
|
||||||
width: toolState.eraser.width,
|
width: toolState.eraser.width,
|
||||||
|
clip: {
|
||||||
|
x: bbox.x,
|
||||||
|
y: bbox.y,
|
||||||
|
width: bbox.width,
|
||||||
|
height: bbox.height,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
selectedEntity.type
|
selectedEntity.type
|
||||||
);
|
);
|
||||||
@ -348,6 +376,7 @@ export const setStageEventHandlers = ({
|
|||||||
// Continue the last line
|
// Continue the last line
|
||||||
maybeAddNextPoint(selectedEntity, pos, getToolState, getLastAddedPoint, setLastAddedPoint, onPointAddedToLine);
|
maybeAddNextPoint(selectedEntity, pos, getToolState, getLastAddedPoint, setLastAddedPoint, onPointAddedToLine);
|
||||||
} else {
|
} else {
|
||||||
|
const bbox = getBbox();
|
||||||
// Start a new line
|
// Start a new line
|
||||||
onBrushLineAdded(
|
onBrushLineAdded(
|
||||||
{
|
{
|
||||||
@ -360,6 +389,12 @@ export const setStageEventHandlers = ({
|
|||||||
],
|
],
|
||||||
width: toolState.brush.width,
|
width: toolState.brush.width,
|
||||||
color: getCurrentFill(),
|
color: getCurrentFill(),
|
||||||
|
clip: {
|
||||||
|
x: bbox.x,
|
||||||
|
y: bbox.y,
|
||||||
|
width: bbox.width,
|
||||||
|
height: bbox.height,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
selectedEntity.type
|
selectedEntity.type
|
||||||
);
|
);
|
||||||
@ -373,6 +408,7 @@ export const setStageEventHandlers = ({
|
|||||||
// Continue the last line
|
// Continue the last line
|
||||||
maybeAddNextPoint(selectedEntity, pos, getToolState, getLastAddedPoint, setLastAddedPoint, onPointAddedToLine);
|
maybeAddNextPoint(selectedEntity, pos, getToolState, getLastAddedPoint, setLastAddedPoint, onPointAddedToLine);
|
||||||
} else {
|
} else {
|
||||||
|
const bbox = getBbox();
|
||||||
// Start a new line
|
// Start a new line
|
||||||
onEraserLineAdded(
|
onEraserLineAdded(
|
||||||
{
|
{
|
||||||
@ -384,6 +420,12 @@ export const setStageEventHandlers = ({
|
|||||||
pos.y - selectedEntity.y,
|
pos.y - selectedEntity.y,
|
||||||
],
|
],
|
||||||
width: toolState.eraser.width,
|
width: toolState.eraser.width,
|
||||||
|
clip: {
|
||||||
|
x: bbox.x,
|
||||||
|
y: bbox.y,
|
||||||
|
width: bbox.width,
|
||||||
|
height: bbox.height,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
selectedEntity.type
|
selectedEntity.type
|
||||||
);
|
);
|
||||||
|
@ -23,10 +23,19 @@ import { v4 as uuidv4 } from 'uuid';
|
|||||||
* @param layerObjectGroup The konva layer's object group to add the line to
|
* @param layerObjectGroup The konva layer's object group to add the line to
|
||||||
* @param name The konva name for the line
|
* @param name The konva name for the line
|
||||||
*/
|
*/
|
||||||
export const createBrushLine = (brushLine: BrushLine, layerObjectGroup: Konva.Group, name: string): Konva.Line => {
|
export const getBrushLine = (brushLine: BrushLine, layerObjectGroup: Konva.Group, name: string): Konva.Line => {
|
||||||
const konvaLine = new Konva.Line({
|
let konvaLineGroup = layerObjectGroup.findOne<Konva.Group>(`#${brushLine.id}_group`);
|
||||||
|
let konvaLine = konvaLineGroup?.findOne<Konva.Line>(`#${brushLine.id}`);
|
||||||
|
if (konvaLine) {
|
||||||
|
return konvaLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
konvaLineGroup = new Konva.Group({
|
||||||
|
id: `${brushLine.id}_group`,
|
||||||
|
// clip: brushLine.clip,
|
||||||
|
});
|
||||||
|
konvaLine = new Konva.Line({
|
||||||
id: brushLine.id,
|
id: brushLine.id,
|
||||||
key: brushLine.id,
|
|
||||||
name,
|
name,
|
||||||
strokeWidth: brushLine.strokeWidth,
|
strokeWidth: brushLine.strokeWidth,
|
||||||
tension: 0,
|
tension: 0,
|
||||||
@ -37,7 +46,8 @@ export const createBrushLine = (brushLine: BrushLine, layerObjectGroup: Konva.Gr
|
|||||||
listening: false,
|
listening: false,
|
||||||
stroke: rgbaColorToString(brushLine.color),
|
stroke: rgbaColorToString(brushLine.color),
|
||||||
});
|
});
|
||||||
layerObjectGroup.add(konvaLine);
|
konvaLineGroup.add(konvaLine);
|
||||||
|
layerObjectGroup.add(konvaLineGroup);
|
||||||
return konvaLine;
|
return konvaLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,7 +57,7 @@ export const createBrushLine = (brushLine: BrushLine, layerObjectGroup: Konva.Gr
|
|||||||
* @param layerObjectGroup The konva layer's object group to add the line to
|
* @param layerObjectGroup The konva layer's object group to add the line to
|
||||||
* @param name The konva name for the line
|
* @param name The konva name for the line
|
||||||
*/
|
*/
|
||||||
export const createEraserLine = (eraserLine: EraserLine, layerObjectGroup: Konva.Group, name: string): Konva.Line => {
|
export const getEraserLine = (eraserLine: EraserLine, layerObjectGroup: Konva.Group, name: string): Konva.Line => {
|
||||||
const konvaLine = new Konva.Line({
|
const konvaLine = new Konva.Line({
|
||||||
id: eraserLine.id,
|
id: eraserLine.id,
|
||||||
key: eraserLine.id,
|
key: eraserLine.id,
|
||||||
@ -60,6 +70,7 @@ export const createEraserLine = (eraserLine: EraserLine, layerObjectGroup: Konva
|
|||||||
globalCompositeOperation: 'destination-out',
|
globalCompositeOperation: 'destination-out',
|
||||||
listening: false,
|
listening: false,
|
||||||
stroke: rgbaColorToString(DEFAULT_RGBA_COLOR),
|
stroke: rgbaColorToString(DEFAULT_RGBA_COLOR),
|
||||||
|
clip: eraserLine.clip,
|
||||||
});
|
});
|
||||||
layerObjectGroup.add(konvaLine);
|
layerObjectGroup.add(konvaLine);
|
||||||
return konvaLine;
|
return konvaLine;
|
||||||
|
@ -253,7 +253,7 @@ export const renderBboxPreview = (
|
|||||||
stage: Konva.Stage,
|
stage: Konva.Stage,
|
||||||
bbox: IRect,
|
bbox: IRect,
|
||||||
tool: Tool,
|
tool: Tool,
|
||||||
getBbox: () => IRect,
|
getBbox: () => CanvasV2State['bbox'],
|
||||||
onBboxTransformed: (bbox: IRect) => void,
|
onBboxTransformed: (bbox: IRect) => void,
|
||||||
getShiftKey: () => boolean,
|
getShiftKey: () => boolean,
|
||||||
getCtrlKey: () => boolean,
|
getCtrlKey: () => boolean,
|
||||||
|
@ -7,11 +7,11 @@ import {
|
|||||||
RASTER_LAYER_RECT_SHAPE_NAME,
|
RASTER_LAYER_RECT_SHAPE_NAME,
|
||||||
} from 'features/controlLayers/konva/naming';
|
} from 'features/controlLayers/konva/naming';
|
||||||
import {
|
import {
|
||||||
createBrushLine,
|
|
||||||
createEraserLine,
|
|
||||||
createImageObjectGroup,
|
createImageObjectGroup,
|
||||||
createObjectGroup,
|
createObjectGroup,
|
||||||
createRectShape,
|
createRectShape,
|
||||||
|
getBrushLine,
|
||||||
|
getEraserLine,
|
||||||
} from 'features/controlLayers/konva/renderers/objects';
|
} from 'features/controlLayers/konva/renderers/objects';
|
||||||
import { mapId, selectRasterObjects } from 'features/controlLayers/konva/util';
|
import { mapId, selectRasterObjects } from 'features/controlLayers/konva/util';
|
||||||
import type { CanvasEntity, LayerEntity, PosChangedArg, Tool } from 'features/controlLayers/store/types';
|
import type { CanvasEntity, LayerEntity, PosChangedArg, Tool } from 'features/controlLayers/store/types';
|
||||||
@ -92,9 +92,7 @@ export const renderRasterLayer = async (
|
|||||||
|
|
||||||
for (const obj of layerState.objects) {
|
for (const obj of layerState.objects) {
|
||||||
if (obj.type === 'brush_line') {
|
if (obj.type === 'brush_line') {
|
||||||
const konvaBrushLine =
|
const konvaBrushLine = getBrushLine(obj, konvaObjectGroup, RASTER_LAYER_BRUSH_LINE_NAME);
|
||||||
konvaObjectGroup.findOne<Konva.Line>(`#${obj.id}`) ??
|
|
||||||
createBrushLine(obj, konvaObjectGroup, RASTER_LAYER_BRUSH_LINE_NAME);
|
|
||||||
// Only update the points if they have changed.
|
// Only update the points if they have changed.
|
||||||
if (konvaBrushLine.points().length !== obj.points.length) {
|
if (konvaBrushLine.points().length !== obj.points.length) {
|
||||||
konvaBrushLine.points(obj.points);
|
konvaBrushLine.points(obj.points);
|
||||||
@ -102,7 +100,7 @@ export const renderRasterLayer = async (
|
|||||||
} else if (obj.type === 'eraser_line') {
|
} else if (obj.type === 'eraser_line') {
|
||||||
const konvaEraserLine =
|
const konvaEraserLine =
|
||||||
konvaObjectGroup.findOne<Konva.Line>(`#${obj.id}`) ??
|
konvaObjectGroup.findOne<Konva.Line>(`#${obj.id}`) ??
|
||||||
createEraserLine(obj, konvaObjectGroup, RASTER_LAYER_ERASER_LINE_NAME);
|
getEraserLine(obj, konvaObjectGroup, RASTER_LAYER_ERASER_LINE_NAME);
|
||||||
// Only update the points if they have changed.
|
// Only update the points if they have changed.
|
||||||
if (konvaEraserLine.points().length !== obj.points.length) {
|
if (konvaEraserLine.points().length !== obj.points.length) {
|
||||||
konvaEraserLine.points(obj.points);
|
konvaEraserLine.points(obj.points);
|
||||||
|
@ -12,10 +12,10 @@ import {
|
|||||||
import { getLayerBboxFast } from 'features/controlLayers/konva/renderers/bbox';
|
import { getLayerBboxFast } from 'features/controlLayers/konva/renderers/bbox';
|
||||||
import {
|
import {
|
||||||
createBboxRect,
|
createBboxRect,
|
||||||
createBrushLine,
|
|
||||||
createEraserLine,
|
|
||||||
createObjectGroup,
|
createObjectGroup,
|
||||||
createRectShape,
|
createRectShape,
|
||||||
|
getBrushLine,
|
||||||
|
getEraserLine,
|
||||||
} from 'features/controlLayers/konva/renderers/objects';
|
} from 'features/controlLayers/konva/renderers/objects';
|
||||||
import { mapId, selectVectorMaskObjects } from 'features/controlLayers/konva/util';
|
import { mapId, selectVectorMaskObjects } from 'features/controlLayers/konva/util';
|
||||||
import type { CanvasEntity, PosChangedArg, RegionEntity, Tool } from 'features/controlLayers/store/types';
|
import type { CanvasEntity, PosChangedArg, RegionEntity, Tool } from 'features/controlLayers/store/types';
|
||||||
@ -117,7 +117,7 @@ export const renderRGLayer = (
|
|||||||
for (const obj of rg.objects) {
|
for (const obj of rg.objects) {
|
||||||
if (obj.type === 'brush_line') {
|
if (obj.type === 'brush_line') {
|
||||||
const konvaBrushLine =
|
const konvaBrushLine =
|
||||||
stage.findOne<Konva.Line>(`#${obj.id}`) ?? createBrushLine(obj, konvaObjectGroup, RG_LAYER_BRUSH_LINE_NAME);
|
stage.findOne<Konva.Line>(`#${obj.id}`) ?? getBrushLine(obj, konvaObjectGroup, RG_LAYER_BRUSH_LINE_NAME);
|
||||||
|
|
||||||
// Only update the points if they have changed. The point values are never mutated, they are only added to the
|
// Only update the points if they have changed. The point values are never mutated, they are only added to the
|
||||||
// array, so checking the length is sufficient to determine if we need to re-cache.
|
// array, so checking the length is sufficient to determine if we need to re-cache.
|
||||||
@ -132,7 +132,7 @@ export const renderRGLayer = (
|
|||||||
}
|
}
|
||||||
} else if (obj.type === 'eraser_line') {
|
} else if (obj.type === 'eraser_line') {
|
||||||
const konvaEraserLine =
|
const konvaEraserLine =
|
||||||
stage.findOne<Konva.Line>(`#${obj.id}`) ?? createEraserLine(obj, konvaObjectGroup, RG_LAYER_ERASER_LINE_NAME);
|
stage.findOne<Konva.Line>(`#${obj.id}`) ?? getEraserLine(obj, konvaObjectGroup, RG_LAYER_ERASER_LINE_NAME);
|
||||||
|
|
||||||
// Only update the points if they have changed. The point values are never mutated, they are only added to the
|
// Only update the points if they have changed. The point values are never mutated, they are only added to the
|
||||||
// array, so checking the length is sufficient to determine if we need to re-cache.
|
// array, so checking the length is sufficient to determine if we need to re-cache.
|
||||||
|
@ -15,7 +15,7 @@ import { settingsReducers } from 'features/controlLayers/store/settingsReducers'
|
|||||||
import { toolReducers } from 'features/controlLayers/store/toolReducers';
|
import { toolReducers } from 'features/controlLayers/store/toolReducers';
|
||||||
import { initialAspectRatioState } from 'features/parameters/components/ImageSize/constants';
|
import { initialAspectRatioState } from 'features/parameters/components/ImageSize/constants';
|
||||||
import type { AspectRatioState } from 'features/parameters/components/ImageSize/types';
|
import type { AspectRatioState } from 'features/parameters/components/ImageSize/types';
|
||||||
import type { IRect, Vector2d } from 'konva/lib/types';
|
import type { Vector2d } from 'konva/lib/types';
|
||||||
import { atom } from 'nanostores';
|
import { atom } from 'nanostores';
|
||||||
|
|
||||||
import type { CanvasEntity, CanvasEntityIdentifier, CanvasV2State, RgbaColor, StageAttrs } from './types';
|
import type { CanvasEntity, CanvasEntityIdentifier, CanvasV2State, RgbaColor, StageAttrs } from './types';
|
||||||
@ -327,7 +327,7 @@ export const $stageAttrs = atom<StageAttrs>({
|
|||||||
export const $toolState = atom<CanvasV2State['tool']>(deepClone(initialState.tool));
|
export const $toolState = atom<CanvasV2State['tool']>(deepClone(initialState.tool));
|
||||||
export const $currentFill = atom<RgbaColor>(DEFAULT_RGBA_COLOR);
|
export const $currentFill = atom<RgbaColor>(DEFAULT_RGBA_COLOR);
|
||||||
export const $selectedEntity = atom<CanvasEntity | null>(null);
|
export const $selectedEntity = atom<CanvasEntity | null>(null);
|
||||||
export const $bbox = atom<IRect>({ x: 0, y: 0, width: 0, height: 0 });
|
export const $bbox = atom<CanvasV2State['bbox']>(deepClone(initialState.bbox));
|
||||||
export const $document = atom<CanvasV2State['document']>(deepClone(initialState.document));
|
export const $document = atom<CanvasV2State['document']>(deepClone(initialState.document));
|
||||||
|
|
||||||
export const canvasV2PersistConfig: PersistConfig<CanvasV2State> = {
|
export const canvasV2PersistConfig: PersistConfig<CanvasV2State> = {
|
||||||
|
@ -136,7 +136,7 @@ export const layersReducers = {
|
|||||||
},
|
},
|
||||||
layerBrushLineAdded: {
|
layerBrushLineAdded: {
|
||||||
reducer: (state, action: PayloadAction<BrushLineAddedArg & { lineId: string }>) => {
|
reducer: (state, action: PayloadAction<BrushLineAddedArg & { lineId: string }>) => {
|
||||||
const { id, points, lineId, color, width } = action.payload;
|
const { id, points, lineId, color, width, clip } = action.payload;
|
||||||
const layer = selectLayer(state, id);
|
const layer = selectLayer(state, id);
|
||||||
if (!layer) {
|
if (!layer) {
|
||||||
return;
|
return;
|
||||||
@ -148,6 +148,7 @@ export const layersReducers = {
|
|||||||
points,
|
points,
|
||||||
strokeWidth: width,
|
strokeWidth: width,
|
||||||
color,
|
color,
|
||||||
|
clip,
|
||||||
});
|
});
|
||||||
layer.bboxNeedsUpdate = true;
|
layer.bboxNeedsUpdate = true;
|
||||||
},
|
},
|
||||||
@ -157,7 +158,7 @@ export const layersReducers = {
|
|||||||
},
|
},
|
||||||
layerEraserLineAdded: {
|
layerEraserLineAdded: {
|
||||||
reducer: (state, action: PayloadAction<EraserLineAddedArg & { lineId: string }>) => {
|
reducer: (state, action: PayloadAction<EraserLineAddedArg & { lineId: string }>) => {
|
||||||
const { id, points, lineId, width } = action.payload;
|
const { id, points, lineId, width, clip } = action.payload;
|
||||||
const layer = selectLayer(state, id);
|
const layer = selectLayer(state, id);
|
||||||
if (!layer) {
|
if (!layer) {
|
||||||
return;
|
return;
|
||||||
@ -168,6 +169,7 @@ export const layersReducers = {
|
|||||||
type: 'eraser_line',
|
type: 'eraser_line',
|
||||||
points,
|
points,
|
||||||
strokeWidth: width,
|
strokeWidth: width,
|
||||||
|
clip,
|
||||||
});
|
});
|
||||||
layer.bboxNeedsUpdate = true;
|
layer.bboxNeedsUpdate = true;
|
||||||
},
|
},
|
||||||
|
@ -304,7 +304,7 @@ export const regionsReducers = {
|
|||||||
},
|
},
|
||||||
rgBrushLineAdded: {
|
rgBrushLineAdded: {
|
||||||
reducer: (state, action: PayloadAction<BrushLineAddedArg & { lineId: string }>) => {
|
reducer: (state, action: PayloadAction<BrushLineAddedArg & { lineId: string }>) => {
|
||||||
const { id, points, lineId, color, width } = action.payload;
|
const { id, points, lineId, color, width, clip } = action.payload;
|
||||||
const rg = selectRG(state, id);
|
const rg = selectRG(state, id);
|
||||||
if (!rg) {
|
if (!rg) {
|
||||||
return;
|
return;
|
||||||
@ -315,6 +315,7 @@ export const regionsReducers = {
|
|||||||
points,
|
points,
|
||||||
strokeWidth: width,
|
strokeWidth: width,
|
||||||
color,
|
color,
|
||||||
|
clip,
|
||||||
});
|
});
|
||||||
rg.bboxNeedsUpdate = true;
|
rg.bboxNeedsUpdate = true;
|
||||||
rg.imageCache = null;
|
rg.imageCache = null;
|
||||||
@ -325,7 +326,7 @@ export const regionsReducers = {
|
|||||||
},
|
},
|
||||||
rgEraserLineAdded: {
|
rgEraserLineAdded: {
|
||||||
reducer: (state, action: PayloadAction<EraserLineAddedArg & { lineId: string }>) => {
|
reducer: (state, action: PayloadAction<EraserLineAddedArg & { lineId: string }>) => {
|
||||||
const { id, points, lineId, width } = action.payload;
|
const { id, points, lineId, width, clip } = action.payload;
|
||||||
const rg = selectRG(state, id);
|
const rg = selectRG(state, id);
|
||||||
if (!rg) {
|
if (!rg) {
|
||||||
return;
|
return;
|
||||||
@ -335,6 +336,7 @@ export const regionsReducers = {
|
|||||||
type: 'eraser_line',
|
type: 'eraser_line',
|
||||||
points,
|
points,
|
||||||
strokeWidth: width,
|
strokeWidth: width,
|
||||||
|
clip,
|
||||||
});
|
});
|
||||||
rg.bboxNeedsUpdate = true;
|
rg.bboxNeedsUpdate = true;
|
||||||
rg.imageCache = null;
|
rg.imageCache = null;
|
||||||
|
@ -498,12 +498,21 @@ export const DEFAULT_RGBA_COLOR: RgbaColor = { r: 255, g: 255, b: 255, a: 1 };
|
|||||||
|
|
||||||
const zOpacity = z.number().gte(0).lte(1);
|
const zOpacity = z.number().gte(0).lte(1);
|
||||||
|
|
||||||
|
const zRect = z.object({
|
||||||
|
x: z.number(),
|
||||||
|
y: z.number(),
|
||||||
|
width: z.number().min(1),
|
||||||
|
height: z.number().min(1),
|
||||||
|
});
|
||||||
|
export type Rect = z.infer<typeof zRect>;
|
||||||
|
|
||||||
const zBrushLine = z.object({
|
const zBrushLine = z.object({
|
||||||
id: zId,
|
id: zId,
|
||||||
type: z.literal('brush_line'),
|
type: z.literal('brush_line'),
|
||||||
strokeWidth: z.number().min(1),
|
strokeWidth: z.number().min(1),
|
||||||
points: zPoints,
|
points: zPoints,
|
||||||
color: zRgbaColor,
|
color: zRgbaColor,
|
||||||
|
clip: zRect.nullable(),
|
||||||
});
|
});
|
||||||
export type BrushLine = z.infer<typeof zBrushLine>;
|
export type BrushLine = z.infer<typeof zBrushLine>;
|
||||||
|
|
||||||
@ -512,6 +521,7 @@ const zEraserline = z.object({
|
|||||||
type: z.literal('eraser_line'),
|
type: z.literal('eraser_line'),
|
||||||
strokeWidth: z.number().min(1),
|
strokeWidth: z.number().min(1),
|
||||||
points: zPoints,
|
points: zPoints,
|
||||||
|
clip: zRect.nullable(),
|
||||||
});
|
});
|
||||||
export type EraserLine = z.infer<typeof zEraserline>;
|
export type EraserLine = z.infer<typeof zEraserline>;
|
||||||
|
|
||||||
@ -566,13 +576,6 @@ const zLayerObject = z.discriminatedUnion('type', [
|
|||||||
]);
|
]);
|
||||||
export type LayerObject = z.infer<typeof zLayerObject>;
|
export type LayerObject = z.infer<typeof zLayerObject>;
|
||||||
|
|
||||||
const zRect = z.object({
|
|
||||||
x: z.number(),
|
|
||||||
y: z.number(),
|
|
||||||
width: z.number().min(1),
|
|
||||||
height: z.number().min(1),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const zLayerEntity = z.object({
|
export const zLayerEntity = z.object({
|
||||||
id: zId,
|
id: zId,
|
||||||
type: z.literal('layer'),
|
type: z.literal('layer'),
|
||||||
@ -614,12 +617,14 @@ const zMaskObject = z
|
|||||||
...rest,
|
...rest,
|
||||||
type: 'brush_line',
|
type: 'brush_line',
|
||||||
color: { r: 255, g: 255, b: 255, a: 1 },
|
color: { r: 255, g: 255, b: 255, a: 1 },
|
||||||
|
clip: null,
|
||||||
};
|
};
|
||||||
return asBrushline;
|
return asBrushline;
|
||||||
} else if (tool === 'eraser') {
|
} else if (tool === 'eraser') {
|
||||||
const asEraserLine: EraserLine = {
|
const asEraserLine: EraserLine = {
|
||||||
...rest,
|
...rest,
|
||||||
type: 'eraser_line',
|
type: 'eraser_line',
|
||||||
|
clip: null,
|
||||||
};
|
};
|
||||||
return asEraserLine;
|
return asEraserLine;
|
||||||
}
|
}
|
||||||
@ -881,6 +886,7 @@ export type EraserLineAddedArg = {
|
|||||||
id: string;
|
id: string;
|
||||||
points: [number, number, number, number];
|
points: [number, number, number, number];
|
||||||
width: number;
|
width: number;
|
||||||
|
clip: Rect | null;
|
||||||
};
|
};
|
||||||
export type BrushLineAddedArg = EraserLineAddedArg & { color: RgbaColor };
|
export type BrushLineAddedArg = EraserLineAddedArg & { color: RgbaColor };
|
||||||
export type PointAddedToLineArg = { id: string; point: [number, number] };
|
export type PointAddedToLineArg = { id: string; point: [number, number] };
|
||||||
|
Loading…
Reference in New Issue
Block a user