tidy(ui): rename canvas stuff

This commit is contained in:
psychedelicious 2024-08-02 14:00:51 +10:00
parent ad9312e989
commit fc558094c2
29 changed files with 235 additions and 235 deletions

View File

@ -6,7 +6,7 @@ import {
sessionStagingAreaImageAccepted, sessionStagingAreaImageAccepted,
sessionStagingAreaReset, sessionStagingAreaReset,
} from 'features/controlLayers/store/canvasV2Slice'; } from 'features/controlLayers/store/canvasV2Slice';
import type { LayerEntity } from 'features/controlLayers/store/types'; import type { CanvasLayerState } from 'features/controlLayers/store/types';
import { imageDTOToImageObject } from 'features/controlLayers/store/types'; import { imageDTOToImageObject } from 'features/controlLayers/store/types';
import { toast } from 'features/toast/toast'; import { toast } from 'features/toast/toast';
import { t } from 'i18next'; import { t } from 'i18next';
@ -62,7 +62,7 @@ export const addStagingListeners = (startAppListening: AppStartListening) => {
const { imageDTO, offsetX, offsetY } = stagingAreaImage; const { imageDTO, offsetX, offsetY } = stagingAreaImage;
const imageObject = imageDTOToImageObject(imageDTO); const imageObject = imageDTOToImageObject(imageDTO);
const overrides: Partial<LayerEntity> = { const overrides: Partial<CanvasLayerState> = {
position: { x: x + offsetX, y: y + offsetY }, position: { x: x + offsetX, y: y + offsetY },
objects: [imageObject], objects: [imageObject],
}; };

View File

@ -5,7 +5,7 @@ import IAIDndImage from 'common/components/IAIDndImage';
import IAIDndImageIcon from 'common/components/IAIDndImageIcon'; import IAIDndImageIcon from 'common/components/IAIDndImageIcon';
import { bboxHeightChanged, bboxWidthChanged } from 'features/controlLayers/store/canvasV2Slice'; import { bboxHeightChanged, bboxWidthChanged } from 'features/controlLayers/store/canvasV2Slice';
import { selectOptimalDimension } from 'features/controlLayers/store/selectors'; import { selectOptimalDimension } from 'features/controlLayers/store/selectors';
import type { ControlAdapterEntity } from 'features/controlLayers/store/types'; import type { CanvasControlAdapterState } from 'features/controlLayers/store/types';
import type { ImageDraggableData, TypesafeDroppableData } from 'features/dnd/types'; import type { ImageDraggableData, TypesafeDroppableData } from 'features/dnd/types';
import { calculateNewSize } from 'features/parameters/components/DocumentSize/calculateNewSize'; import { calculateNewSize } from 'features/parameters/components/DocumentSize/calculateNewSize';
import { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { memo, useCallback, useEffect, useMemo, useState } from 'react';
@ -20,7 +20,7 @@ import {
import type { ImageDTO, PostUploadAction } from 'services/api/types'; import type { ImageDTO, PostUploadAction } from 'services/api/types';
type Props = { type Props = {
controlAdapter: ControlAdapterEntity; controlAdapter: CanvasControlAdapterState;
onChangeImage: (imageDTO: ImageDTO | null) => void; onChangeImage: (imageDTO: ImageDTO | null) => void;
droppableData: TypesafeDroppableData; droppableData: TypesafeDroppableData;
postUploadAction: PostUploadAction; postUploadAction: PostUploadAction;

View File

@ -3,7 +3,7 @@ import { rgbaColorToString } from 'common/util/colorCodeTransformers';
import { deepClone } from 'common/util/deepClone'; import { deepClone } from 'common/util/deepClone';
import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer'; import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { BrushLine } from 'features/controlLayers/store/types'; import type { CanvasBrushLineState } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
import type { Logger } from 'roarr'; import type { Logger } from 'roarr';
@ -18,13 +18,13 @@ export class CanvasBrushLine {
log: Logger; log: Logger;
getLoggingContext: (extra?: JSONObject) => JSONObject; getLoggingContext: (extra?: JSONObject) => JSONObject;
state: BrushLine; state: CanvasBrushLineState;
konva: { konva: {
group: Konva.Group; group: Konva.Group;
line: Konva.Line; line: Konva.Line;
}; };
constructor(state: BrushLine, parent: CanvasLayer) { constructor(state: CanvasBrushLineState, parent: CanvasLayer) {
const { id, strokeWidth, clip, color, points } = state; const { id, strokeWidth, clip, color, points } = state;
this.id = id; this.id = id;
this.parent = parent; this.parent = parent;
@ -59,7 +59,7 @@ export class CanvasBrushLine {
this.state = state; this.state = state;
} }
update(state: BrushLine, force?: boolean): boolean { update(state: CanvasBrushLineState, force?: boolean): boolean {
if (force || this.state !== state) { if (force || this.state !== state) {
this.log.trace({ state }, 'Updating brush line'); this.log.trace({ state }, 'Updating brush line');
const { points, color, clip, strokeWidth } = state; const { points, color, clip, strokeWidth } = state;

View File

@ -2,7 +2,7 @@ import { CanvasEntity } from 'features/controlLayers/konva/CanvasEntity';
import { CanvasImage } from 'features/controlLayers/konva/CanvasImage'; import { CanvasImage } from 'features/controlLayers/konva/CanvasImage';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import { CanvasTransformer } from 'features/controlLayers/konva/CanvasTransformer'; import { CanvasTransformer } from 'features/controlLayers/konva/CanvasTransformer';
import { type ControlAdapterEntity, isDrawingTool } from 'features/controlLayers/store/types'; import { type CanvasControlAdapterState, isDrawingTool } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
export class CanvasControlAdapter extends CanvasEntity { export class CanvasControlAdapter extends CanvasEntity {
@ -13,7 +13,7 @@ export class CanvasControlAdapter extends CanvasEntity {
static OBJECT_GROUP_NAME = `${CanvasControlAdapter.NAME_PREFIX}_object-group`; static OBJECT_GROUP_NAME = `${CanvasControlAdapter.NAME_PREFIX}_object-group`;
type = 'control_adapter'; type = 'control_adapter';
_state: ControlAdapterEntity; _state: CanvasControlAdapterState;
konva: { konva: {
layer: Konva.Layer; layer: Konva.Layer;
@ -24,7 +24,7 @@ export class CanvasControlAdapter extends CanvasEntity {
image: CanvasImage | null; image: CanvasImage | null;
transformer: CanvasTransformer; transformer: CanvasTransformer;
constructor(state: ControlAdapterEntity, manager: CanvasManager) { constructor(state: CanvasControlAdapterState, manager: CanvasManager) {
super(state.id, manager); super(state.id, manager);
this.konva = { this.konva = {
layer: new Konva.Layer({ layer: new Konva.Layer({
@ -47,7 +47,7 @@ export class CanvasControlAdapter extends CanvasEntity {
this._state = state; this._state = state;
} }
async render(state: ControlAdapterEntity) { async render(state: CanvasControlAdapterState) {
this._state = state; this._state = state;
// Update the layer's position and listening state // Update the layer's position and listening state

View File

@ -2,7 +2,7 @@ import { rgbaColorToString } from 'common/util/colorCodeTransformers';
import { deepClone } from 'common/util/deepClone'; import { deepClone } from 'common/util/deepClone';
import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer'; import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { EraserLine, GetLoggingContext } from 'features/controlLayers/store/types'; import type { CanvasEraserLineState, GetLoggingContext } from 'features/controlLayers/store/types';
import { RGBA_RED } from 'features/controlLayers/store/types'; import { RGBA_RED } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
import type { Logger } from 'roarr'; import type { Logger } from 'roarr';
@ -18,13 +18,13 @@ export class CanvasEraserLine {
log: Logger; log: Logger;
getLoggingContext: GetLoggingContext; getLoggingContext: GetLoggingContext;
state: EraserLine; state: CanvasEraserLineState;
konva: { konva: {
group: Konva.Group; group: Konva.Group;
line: Konva.Line; line: Konva.Line;
}; };
constructor(state: EraserLine, parent: CanvasLayer) { constructor(state: CanvasEraserLineState, parent: CanvasLayer) {
const { id, strokeWidth, clip, points } = state; const { id, strokeWidth, clip, points } = state;
this.id = id; this.id = id;
this.parent = parent; this.parent = parent;
@ -58,7 +58,7 @@ export class CanvasEraserLine {
this.state = state; this.state = state;
} }
update(state: EraserLine, force?: boolean): boolean { update(state: CanvasEraserLineState, force?: boolean): boolean {
if (force || this.state !== state) { if (force || this.state !== state) {
this.log.trace({ state }, 'Updating eraser line'); this.log.trace({ state }, 'Updating eraser line');
const { points, clip, strokeWidth } = state; const { points, clip, strokeWidth } = state;

View File

@ -4,7 +4,7 @@ import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { CanvasStagingArea } from 'features/controlLayers/konva/CanvasStagingArea'; import type { CanvasStagingArea } from 'features/controlLayers/konva/CanvasStagingArea';
import { FILTER_MAP } from 'features/controlLayers/konva/filters'; import { FILTER_MAP } from 'features/controlLayers/konva/filters';
import { loadImage } from 'features/controlLayers/konva/util'; import { loadImage } from 'features/controlLayers/konva/util';
import type { GetLoggingContext, ImageObject } from 'features/controlLayers/store/types'; import type { GetLoggingContext, CanvasImageState } from 'features/controlLayers/store/types';
import { t } from 'i18next'; import { t } from 'i18next';
import Konva from 'konva'; import Konva from 'konva';
import type { Logger } from 'roarr'; import type { Logger } from 'roarr';
@ -24,7 +24,7 @@ export class CanvasImage {
log: Logger; log: Logger;
getLoggingContext: GetLoggingContext; getLoggingContext: GetLoggingContext;
state: ImageObject; state: CanvasImageState;
konva: { konva: {
group: Konva.Group; group: Konva.Group;
placeholder: { group: Konva.Group; rect: Konva.Rect; text: Konva.Text }; placeholder: { group: Konva.Group; rect: Konva.Rect; text: Konva.Text };
@ -34,7 +34,7 @@ export class CanvasImage {
isLoading: boolean; isLoading: boolean;
isError: boolean; isError: boolean;
constructor(state: ImageObject, parent: CanvasLayer | CanvasStagingArea) { constructor(state: CanvasImageState, parent: CanvasLayer | CanvasStagingArea) {
const { id, width, height, x, y } = state; const { id, width, height, x, y } = state;
this.id = id; this.id = id;
this.parent = parent; this.parent = parent;
@ -138,7 +138,7 @@ export class CanvasImage {
} }
} }
async update(state: ImageObject, force?: boolean): Promise<boolean> { async update(state: CanvasImageState, force?: boolean): Promise<boolean> {
if (this.state !== state || force) { if (this.state !== state || force) {
this.log.trace({ state }, 'Updating image'); this.log.trace({ state }, 'Updating image');

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 { getNodeBboxFast } from 'features/controlLayers/konva/entityBbox'; import { getNodeBboxFast } from 'features/controlLayers/konva/entityBbox';
import { mapId } from 'features/controlLayers/konva/util'; import { mapId } from 'features/controlLayers/konva/util';
import type { BrushLine, EraserLine, InpaintMaskEntity, RectShape } from 'features/controlLayers/store/types'; import type { CanvasBrushLineState, CanvasEraserLineState, CanvasInpaintMaskState, CanvasRectState } 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';
@ -18,8 +18,8 @@ export class CanvasInpaintMask {
static OBJECT_GROUP_NAME = `${CanvasInpaintMask.NAME_PREFIX}_object-group`; static OBJECT_GROUP_NAME = `${CanvasInpaintMask.NAME_PREFIX}_object-group`;
static COMPOSITING_RECT_NAME = `${CanvasInpaintMask.NAME_PREFIX}_compositing-rect`; static COMPOSITING_RECT_NAME = `${CanvasInpaintMask.NAME_PREFIX}_compositing-rect`;
private drawingBuffer: BrushLine | EraserLine | RectShape | null; private drawingBuffer: CanvasBrushLineState | CanvasEraserLineState | CanvasRectState | null;
private state: InpaintMaskEntity; private state: CanvasInpaintMaskState;
id = 'inpaint_mask'; id = 'inpaint_mask';
manager: CanvasManager; manager: CanvasManager;
@ -33,7 +33,7 @@ export class CanvasInpaintMask {
}; };
objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect>; objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect>;
constructor(state: InpaintMaskEntity, manager: CanvasManager) { constructor(state: CanvasInpaintMaskState, manager: CanvasManager) {
this.manager = manager; this.manager = manager;
this.konva = { this.konva = {
@ -87,12 +87,12 @@ export class CanvasInpaintMask {
return this.drawingBuffer; return this.drawingBuffer;
} }
async setDrawingBuffer(obj: BrushLine | EraserLine | RectShape | null) { async setDrawingBuffer(obj: CanvasBrushLineState | CanvasEraserLineState | CanvasRectState | 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') {
this.drawingBuffer.color = RGBA_RED; this.drawingBuffer.color = RGBA_RED;
} else if (this.drawingBuffer.type === 'rect_shape') { } else if (this.drawingBuffer.type === 'rect') {
this.drawingBuffer.color = RGBA_RED; this.drawingBuffer.color = RGBA_RED;
} }
@ -109,13 +109,13 @@ export class CanvasInpaintMask {
this.manager.stateApi.onBrushLineAdded({ id: this.id, brushLine: this.drawingBuffer }, 'inpaint_mask'); this.manager.stateApi.onBrushLineAdded({ 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.onEraserLineAdded({ id: this.id, eraserLine: this.drawingBuffer }, 'inpaint_mask'); this.manager.stateApi.onEraserLineAdded({ id: this.id, eraserLine: this.drawingBuffer }, 'inpaint_mask');
} else if (this.drawingBuffer.type === 'rect_shape') { } else if (this.drawingBuffer.type === 'rect') {
this.manager.stateApi.onRectShapeAdded({ id: this.id, rectShape: this.drawingBuffer }, 'inpaint_mask'); this.manager.stateApi.onRectShapeAdded({ id: this.id, rectShape: this.drawingBuffer }, 'inpaint_mask');
} }
this.setDrawingBuffer(null); this.setDrawingBuffer(null);
} }
async render(state: InpaintMaskEntity) { async render(state: CanvasInpaintMaskState) {
this.state = state; this.state = state;
// Update the layer's position and listening state // Update the layer's position and listening state
@ -153,7 +153,7 @@ export class CanvasInpaintMask {
this.updateGroup(didDraw); this.updateGroup(didDraw);
} }
private async renderObject(obj: InpaintMaskEntity['objects'][number], force = false): Promise<boolean> { private async renderObject(obj: CanvasInpaintMaskState['objects'][number], force = false): Promise<boolean> {
if (obj.type === 'brush_line') { if (obj.type === 'brush_line') {
let brushLine = this.objects.get(obj.id); let brushLine = this.objects.get(obj.id);
assert(brushLine instanceof CanvasBrushLine || brushLine === undefined); assert(brushLine instanceof CanvasBrushLine || brushLine === undefined);
@ -182,7 +182,7 @@ export class CanvasInpaintMask {
return true; return true;
} }
} }
} else if (obj.type === 'rect_shape') { } else if (obj.type === 'rect') {
let rect = this.objects.get(obj.id); let rect = this.objects.get(obj.id);
assert(rect instanceof CanvasRect || rect === undefined); assert(rect instanceof CanvasRect || rect === undefined);

View File

@ -9,14 +9,14 @@ import { CanvasTransformer } from 'features/controlLayers/konva/CanvasTransforme
import { getPrefixedId, konvaNodeToBlob, mapId, previewBlob } from 'features/controlLayers/konva/util'; import { getPrefixedId, konvaNodeToBlob, mapId, previewBlob } from 'features/controlLayers/konva/util';
import { layerRasterized } from 'features/controlLayers/store/canvasV2Slice'; import { layerRasterized } from 'features/controlLayers/store/canvasV2Slice';
import type { import type {
BrushLine, CanvasBrushLineState,
CanvasEraserLineState,
CanvasLayerState,
CanvasRectState,
CanvasV2State, CanvasV2State,
Coordinate, Coordinate,
EraserLine,
GetLoggingContext, GetLoggingContext,
LayerEntity,
Rect, Rect,
RectShape,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { imageDTOToImageObject } from 'features/controlLayers/store/types'; import { imageDTOToImageObject } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
@ -39,8 +39,8 @@ export class CanvasLayer {
log: Logger; log: Logger;
getLoggingContext: GetLoggingContext; getLoggingContext: GetLoggingContext;
drawingBuffer: BrushLine | EraserLine | RectShape | null; drawingBuffer: CanvasBrushLineState | CanvasEraserLineState | CanvasRectState | null;
state: LayerEntity; state: CanvasLayerState;
konva: { konva: {
layer: Konva.Layer; layer: Konva.Layer;
@ -57,7 +57,7 @@ export class CanvasLayer {
rect: Rect; rect: Rect;
bbox: Rect; bbox: Rect;
constructor(state: LayerEntity, manager: CanvasManager) { constructor(state: CanvasLayerState, manager: CanvasManager) {
this.id = state.id; this.id = state.id;
this.manager = manager; this.manager = manager;
this.getLoggingContext = this.manager.buildGetLoggingContext(this); this.getLoggingContext = this.manager.buildGetLoggingContext(this);
@ -104,7 +104,7 @@ export class CanvasLayer {
return this.drawingBuffer; return this.drawingBuffer;
}; };
setDrawingBuffer = async (obj: BrushLine | EraserLine | RectShape | null) => { setDrawingBuffer = async (obj: CanvasBrushLineState | CanvasEraserLineState | CanvasRectState | null) => {
if (obj) { if (obj) {
this.drawingBuffer = obj; this.drawingBuffer = obj;
await this._renderObject(this.drawingBuffer, true); await this._renderObject(this.drawingBuffer, true);
@ -129,13 +129,13 @@ export class CanvasLayer {
} else if (drawingBuffer.type === 'eraser_line') { } else if (drawingBuffer.type === 'eraser_line') {
drawingBuffer.id = getPrefixedId('brush_line'); drawingBuffer.id = getPrefixedId('brush_line');
this.manager.stateApi.onEraserLineAdded({ id: this.id, eraserLine: drawingBuffer }, 'layer'); this.manager.stateApi.onEraserLineAdded({ id: this.id, eraserLine: drawingBuffer }, 'layer');
} else if (drawingBuffer.type === 'rect_shape') { } else if (drawingBuffer.type === 'rect') {
drawingBuffer.id = getPrefixedId('brush_line'); drawingBuffer.id = getPrefixedId('brush_line');
this.manager.stateApi.onRectShapeAdded({ id: this.id, rectShape: drawingBuffer }, 'layer'); this.manager.stateApi.onRectShapeAdded({ id: this.id, rectShape: drawingBuffer }, 'layer');
} }
}; };
update = async (arg?: { state: LayerEntity; toolState: CanvasV2State['tool']; isSelected: boolean }) => { update = async (arg?: { state: CanvasLayerState; toolState: CanvasV2State['tool']; isSelected: boolean }) => {
const state = get(arg, 'state', this.state); const state = get(arg, 'state', this.state);
const toolState = get(arg, 'toolState', this.manager.stateApi.getToolState()); const toolState = get(arg, 'toolState', this.manager.stateApi.getToolState());
const isSelected = get(arg, 'isSelected', this.manager.stateApi.getIsSelected(this.id)); const isSelected = get(arg, 'isSelected', this.manager.stateApi.getIsSelected(this.id));
@ -191,7 +191,7 @@ export class CanvasLayer {
this.transformer.update(position, this.bbox); this.transformer.update(position, this.bbox);
}; };
updateObjects = async (arg?: { objects: LayerEntity['objects'] }) => { updateObjects = async (arg?: { objects: CanvasLayerState['objects'] }) => {
this.log.trace('Updating objects'); this.log.trace('Updating objects');
const objects = get(arg, 'objects', this.state.objects); const objects = get(arg, 'objects', this.state.objects);
@ -297,7 +297,7 @@ export class CanvasLayer {
}); });
}; };
_renderObject = async (obj: LayerEntity['objects'][number], force = false): Promise<boolean> => { _renderObject = async (obj: CanvasLayerState['objects'][number], force = false): Promise<boolean> => {
if (obj.type === 'brush_line') { if (obj.type === 'brush_line') {
let brushLine = this.objects.get(obj.id); let brushLine = this.objects.get(obj.id);
assert(brushLine instanceof CanvasBrushLine || brushLine === undefined); assert(brushLine instanceof CanvasBrushLine || brushLine === undefined);
@ -324,7 +324,7 @@ export class CanvasLayer {
return true; return true;
} }
} }
} else if (obj.type === 'rect_shape') { } else if (obj.type === 'rect') {
let rect = this.objects.get(obj.id); let rect = this.objects.get(obj.id);
assert(rect instanceof CanvasRect || rect === undefined); assert(rect instanceof CanvasRect || rect === undefined);

View File

@ -2,7 +2,7 @@ import { rgbaColorToString } from 'common/util/colorCodeTransformers';
import { deepClone } from 'common/util/deepClone'; import { deepClone } from 'common/util/deepClone';
import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer'; import type { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { GetLoggingContext, RectShape } from 'features/controlLayers/store/types'; import type { GetLoggingContext, CanvasRectState } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
import type { Logger } from 'roarr'; import type { Logger } from 'roarr';
@ -17,13 +17,13 @@ export class CanvasRect {
log: Logger; log: Logger;
getLoggingContext: GetLoggingContext; getLoggingContext: GetLoggingContext;
state: RectShape; state: CanvasRectState;
konva: { konva: {
group: Konva.Group; group: Konva.Group;
rect: Konva.Rect; rect: Konva.Rect;
}; };
constructor(state: RectShape, parent: CanvasLayer) { constructor(state: CanvasRectState, parent: CanvasLayer) {
const { id, x, y, width, height, color } = state; const { id, x, y, width, height, color } = state;
this.id = id; this.id = id;
this.parent = parent; this.parent = parent;
@ -48,7 +48,7 @@ export class CanvasRect {
this.state = state; this.state = state;
} }
update(state: RectShape, force?: boolean): boolean { update(state: CanvasRectState, force?: boolean): boolean {
if (this.state !== state || force) { if (this.state !== state || force) {
this.log.trace({ state }, 'Updating rect'); this.log.trace({ state }, 'Updating rect');
const { x, y, width, height, color } = state; const { x, y, width, height, color } = state;

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 { getNodeBboxFast } from 'features/controlLayers/konva/entityBbox'; import { getNodeBboxFast } from 'features/controlLayers/konva/entityBbox';
import { mapId } from 'features/controlLayers/konva/util'; import { mapId } from 'features/controlLayers/konva/util';
import type { BrushLine, EraserLine, RectShape, RegionEntity } from 'features/controlLayers/store/types'; import type { CanvasBrushLineState, CanvasEraserLineState, CanvasRectState, CanvasRegionalGuidanceState } 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';
@ -18,8 +18,8 @@ export class CanvasRegion {
static OBJECT_GROUP_NAME = `${CanvasRegion.NAME_PREFIX}_object-group`; static OBJECT_GROUP_NAME = `${CanvasRegion.NAME_PREFIX}_object-group`;
static COMPOSITING_RECT_NAME = `${CanvasRegion.NAME_PREFIX}_compositing-rect`; static COMPOSITING_RECT_NAME = `${CanvasRegion.NAME_PREFIX}_compositing-rect`;
private drawingBuffer: BrushLine | EraserLine | RectShape | null; private drawingBuffer: CanvasBrushLineState | CanvasEraserLineState | CanvasRectState | null;
private state: RegionEntity; private state: CanvasRegionalGuidanceState;
id: string; id: string;
manager: CanvasManager; manager: CanvasManager;
@ -34,7 +34,7 @@ export class CanvasRegion {
objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect>; objects: Map<string, CanvasBrushLine | CanvasEraserLine | CanvasRect>;
constructor(state: RegionEntity, manager: CanvasManager) { constructor(state: CanvasRegionalGuidanceState, manager: CanvasManager) {
this.id = state.id; this.id = state.id;
this.manager = manager; this.manager = manager;
@ -86,12 +86,12 @@ export class CanvasRegion {
return this.drawingBuffer; return this.drawingBuffer;
} }
async setDrawingBuffer(obj: BrushLine | EraserLine | RectShape | null) { async setDrawingBuffer(obj: CanvasBrushLineState | CanvasEraserLineState | CanvasRectState | 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') {
this.drawingBuffer.color = RGBA_RED; this.drawingBuffer.color = RGBA_RED;
} else if (this.drawingBuffer.type === 'rect_shape') { } else if (this.drawingBuffer.type === 'rect') {
this.drawingBuffer.color = RGBA_RED; this.drawingBuffer.color = RGBA_RED;
} }
@ -108,13 +108,13 @@ export class CanvasRegion {
this.manager.stateApi.onBrushLineAdded({ id: this.id, brushLine: this.drawingBuffer }, 'regional_guidance'); this.manager.stateApi.onBrushLineAdded({ 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.onEraserLineAdded({ id: this.id, eraserLine: this.drawingBuffer }, 'regional_guidance'); this.manager.stateApi.onEraserLineAdded({ id: this.id, eraserLine: this.drawingBuffer }, 'regional_guidance');
} else if (this.drawingBuffer.type === 'rect_shape') { } else if (this.drawingBuffer.type === 'rect') {
this.manager.stateApi.onRectShapeAdded({ id: this.id, rectShape: this.drawingBuffer }, 'regional_guidance'); this.manager.stateApi.onRectShapeAdded({ id: this.id, rectShape: this.drawingBuffer }, 'regional_guidance');
} }
this.setDrawingBuffer(null); this.setDrawingBuffer(null);
} }
async render(state: RegionEntity) { async render(state: CanvasRegionalGuidanceState) {
this.state = state; this.state = state;
// Update the layer's position and listening state // Update the layer's position and listening state
@ -152,7 +152,7 @@ export class CanvasRegion {
this.updateGroup(didDraw); this.updateGroup(didDraw);
} }
private async renderObject(obj: RegionEntity['objects'][number], force = false): Promise<boolean> { private async renderObject(obj: CanvasRegionalGuidanceState['objects'][number], force = false): Promise<boolean> {
if (obj.type === 'brush_line') { if (obj.type === 'brush_line') {
let brushLine = this.objects.get(obj.id); let brushLine = this.objects.get(obj.id);
assert(brushLine instanceof CanvasBrushLine || brushLine === undefined); assert(brushLine instanceof CanvasBrushLine || brushLine === undefined);
@ -181,7 +181,7 @@ export class CanvasRegion {
return true; return true;
} }
} }
} else if (obj.type === 'rect_shape') { } else if (obj.type === 'rect') {
let rect = this.objects.get(obj.id); let rect = this.objects.get(obj.id);
assert(rect instanceof CanvasRect || rect === undefined); assert(rect instanceof CanvasRect || rect === undefined);

View File

@ -46,11 +46,11 @@ import {
} from 'features/controlLayers/store/canvasV2Slice'; } from 'features/controlLayers/store/canvasV2Slice';
import type { import type {
BboxChangedArg, BboxChangedArg,
BrushLine, CanvasBrushLineState,
CanvasEntity, CanvasEntity,
EraserLine, CanvasEraserLineState,
PositionChangedArg, PositionChangedArg,
RectShape, CanvasRectState,
ScaleChangedArg, ScaleChangedArg,
Tool, Tool,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
@ -111,7 +111,7 @@ export class CanvasStateApi {
this.store.dispatch(imBboxChanged(arg)); this.store.dispatch(imBboxChanged(arg));
} }
}; };
onBrushLineAdded = (arg: { id: string; brushLine: BrushLine }, entityType: CanvasEntity['type']) => { onBrushLineAdded = (arg: { id: string; brushLine: CanvasBrushLineState }, entityType: CanvasEntity['type']) => {
log.debug('Brush line added'); log.debug('Brush line added');
if (entityType === 'layer') { if (entityType === 'layer') {
this.store.dispatch(layerBrushLineAdded(arg)); this.store.dispatch(layerBrushLineAdded(arg));
@ -121,7 +121,7 @@ export class CanvasStateApi {
this.store.dispatch(imBrushLineAdded(arg)); this.store.dispatch(imBrushLineAdded(arg));
} }
}; };
onEraserLineAdded = (arg: { id: string; eraserLine: EraserLine }, entityType: CanvasEntity['type']) => { onEraserLineAdded = (arg: { id: string; eraserLine: CanvasEraserLineState }, entityType: CanvasEntity['type']) => {
log.debug('Eraser line added'); log.debug('Eraser line added');
if (entityType === 'layer') { if (entityType === 'layer') {
this.store.dispatch(layerEraserLineAdded(arg)); this.store.dispatch(layerEraserLineAdded(arg));
@ -131,7 +131,7 @@ export class CanvasStateApi {
this.store.dispatch(imEraserLineAdded(arg)); this.store.dispatch(imEraserLineAdded(arg));
} }
}; };
onRectShapeAdded = (arg: { id: string; rectShape: RectShape }, entityType: CanvasEntity['type']) => { onRectShapeAdded = (arg: { id: string; rectShape: CanvasRectState }, entityType: CanvasEntity['type']) => {
log.debug('Rect shape added'); log.debug('Rect shape added');
if (entityType === 'layer') { if (entityType === 'layer') {
this.store.dispatch(layerRectShapeAdded(arg)); this.store.dispatch(layerRectShapeAdded(arg));

View File

@ -4,9 +4,9 @@ import { imageDataToDataURL } from 'features/controlLayers/konva/util';
import type { import type {
BboxChangedArg, BboxChangedArg,
CanvasEntity, CanvasEntity,
ControlAdapterEntity, CanvasControlAdapterState,
LayerEntity, CanvasLayerState,
RegionEntity, CanvasRegionalGuidanceState,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import Konva from 'konva'; import Konva from 'konva';
import type { IRect } from 'konva/lib/types'; import type { IRect } from 'konva/lib/types';
@ -198,9 +198,9 @@ const filterCAChildren = (node: Konva.Node): boolean => true;
*/ */
export const updateBboxes = ( export const updateBboxes = (
stage: Konva.Stage, stage: Konva.Stage,
layers: LayerEntity[], layers: CanvasLayerState[],
controlAdapters: ControlAdapterEntity[], controlAdapters: CanvasControlAdapterState[],
regions: RegionEntity[], regions: CanvasRegionalGuidanceState[],
onBboxChanged: (arg: BboxChangedArg, entityType: CanvasEntity['type']) => void onBboxChanged: (arg: BboxChangedArg, entityType: CanvasEntity['type']) => void
): void => { ): void => {
for (const entityState of [...layers, ...controlAdapters, ...regions]) { for (const entityState of [...layers, ...controlAdapters, ...regions]) {

View File

@ -8,9 +8,9 @@ import {
import type { import type {
CanvasV2State, CanvasV2State,
Coordinate, Coordinate,
InpaintMaskEntity, CanvasInpaintMaskState,
LayerEntity, CanvasLayerState,
RegionEntity, CanvasRegionalGuidanceState,
Tool, Tool,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { isDrawableEntity, isDrawableEntityAdapter } from 'features/controlLayers/store/types'; import { isDrawableEntity, isDrawableEntityAdapter } from 'features/controlLayers/store/types';
@ -81,7 +81,7 @@ const getLastPointOfLine = (points: number[]): Coordinate | null => {
}; };
const getLastPointOfLastLineOfEntity = ( const getLastPointOfLastLineOfEntity = (
entity: LayerEntity | RegionEntity | InpaintMaskEntity, entity: CanvasLayerState | CanvasRegionalGuidanceState | CanvasInpaintMaskState,
tool: Tool tool: Tool
): Coordinate | null => { ): Coordinate | null => {
const lastObject = entity.objects[entity.objects.length - 1]; const lastObject = entity.objects[entity.objects.length - 1];
@ -138,7 +138,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
return e.evt.buttons === 1; return e.evt.buttons === 1;
} }
function getClip(entity: RegionEntity | LayerEntity | InpaintMaskEntity) { function getClip(entity: CanvasRegionalGuidanceState | CanvasLayerState | CanvasInpaintMaskState) {
const settings = getSettings(); const settings = getSettings();
const bboxRect = getBbox().rect; const bboxRect = getBbox().rect;
@ -264,8 +264,8 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
await selectedEntityAdapter.finalizeDrawingBuffer(); await selectedEntityAdapter.finalizeDrawingBuffer();
} }
await selectedEntityAdapter.setDrawingBuffer({ await selectedEntityAdapter.setDrawingBuffer({
id: getObjectId('rect_shape', true), id: getObjectId('rect', true),
type: 'rect_shape', type: 'rect',
x: Math.round(normalizedPoint.x), x: Math.round(normalizedPoint.x),
y: Math.round(normalizedPoint.y), y: Math.round(normalizedPoint.y),
width: 0, width: 0,
@ -314,7 +314,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
if (toolState.selected === 'rect') { if (toolState.selected === 'rect') {
const drawingBuffer = selectedEntityAdapter.getDrawingBuffer(); const drawingBuffer = selectedEntityAdapter.getDrawingBuffer();
if (drawingBuffer?.type === 'rect_shape') { if (drawingBuffer?.type === 'rect') {
await selectedEntityAdapter.finalizeDrawingBuffer(); await selectedEntityAdapter.finalizeDrawingBuffer();
} else { } else {
await selectedEntityAdapter.setDrawingBuffer(null); await selectedEntityAdapter.setDrawingBuffer(null);
@ -411,7 +411,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
if (toolState.selected === 'rect') { if (toolState.selected === 'rect') {
const drawingBuffer = selectedEntityAdapter.getDrawingBuffer(); const drawingBuffer = selectedEntityAdapter.getDrawingBuffer();
if (drawingBuffer) { if (drawingBuffer) {
if (drawingBuffer.type === 'rect_shape') { if (drawingBuffer.type === 'rect') {
const normalizedPoint = offsetCoord(pos, selectedEntity.position); const normalizedPoint = offsetCoord(pos, selectedEntity.position);
drawingBuffer.width = Math.round(normalizedPoint.x - drawingBuffer.x); drawingBuffer.width = Math.round(normalizedPoint.x - drawingBuffer.x);
drawingBuffer.height = Math.round(normalizedPoint.y - drawingBuffer.y); drawingBuffer.height = Math.round(normalizedPoint.y - drawingBuffer.y);
@ -455,7 +455,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
drawingBuffer.points.push(alignedPoint.x, alignedPoint.y); drawingBuffer.points.push(alignedPoint.x, alignedPoint.y);
await selectedEntityAdapter.setDrawingBuffer(drawingBuffer); await selectedEntityAdapter.setDrawingBuffer(drawingBuffer);
await selectedEntityAdapter.finalizeDrawingBuffer(); await selectedEntityAdapter.finalizeDrawingBuffer();
} else if (toolState.selected === 'rect' && drawingBuffer?.type === 'rect_shape') { } else if (toolState.selected === 'rect' && drawingBuffer?.type === 'rect') {
drawingBuffer.width = Math.round(normalizedPoint.x - drawingBuffer.x); drawingBuffer.width = Math.round(normalizedPoint.x - drawingBuffer.x);
drawingBuffer.height = Math.round(normalizedPoint.y - drawingBuffer.y); drawingBuffer.height = Math.round(normalizedPoint.y - drawingBuffer.y);
await selectedEntityAdapter.setDrawingBuffer(drawingBuffer); await selectedEntityAdapter.setDrawingBuffer(drawingBuffer);

View File

@ -1,7 +1,7 @@
import { getImageDataTransparency } from 'common/util/arrayBuffer'; import { getImageDataTransparency } from 'common/util/arrayBuffer';
import { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer'; import { CanvasLayer } from 'features/controlLayers/konva/CanvasLayer';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { Coordinate, GenerationMode, Rect, RenderableObject, RgbaColor } from 'features/controlLayers/store/types'; import type { Coordinate, GenerationMode, Rect, CanvasObjectState, RgbaColor } from 'features/controlLayers/store/types';
import { isValidLayer } from 'features/nodes/util/graph/generation/addLayers'; import { isValidLayer } from 'features/nodes/util/graph/generation/addLayers';
import Konva from 'konva'; import Konva from 'konva';
import type { KonvaEventObject } from 'konva/lib/Node'; import type { KonvaEventObject } from 'konva/lib/Node';
@ -618,7 +618,7 @@ export function getPrefixedId(prefix: string): string {
return `${prefix}:${nanoid()}`; return `${prefix}:${nanoid()}`;
} }
export function getObjectId(type: RenderableObject['type'], isBuffer?: boolean): string { export function getObjectId(type: CanvasObjectState['type'], isBuffer?: boolean): string {
if (isBuffer) { if (isBuffer) {
return getPrefixedId(`buffer_${type}`); return getPrefixedId(`buffer_${type}`);
} else { } else {

View File

@ -9,16 +9,16 @@ import { v4 as uuidv4 } from 'uuid';
import type { import type {
CanvasV2State, CanvasV2State,
ControlAdapterEntity, CanvasControlAdapterState,
ControlModeV2, ControlModeV2,
ControlNetConfig, ControlNetConfig,
ControlNetData, CanvasControlNetState,
Filter, Filter,
PositionChangedArg, PositionChangedArg,
ProcessorConfig, ProcessorConfig,
ScaleChangedArg, ScaleChangedArg,
T2IAdapterConfig, T2IAdapterConfig,
T2IAdapterData, CanvasT2IAdapterState,
} from './types'; } from './types';
import { buildControlAdapterProcessorV2, imageDTOToImageObject } from './types'; import { buildControlAdapterProcessorV2, imageDTOToImageObject } from './types';
@ -51,7 +51,7 @@ export const controlAdaptersReducers = {
payload: { id: uuidv4(), ...payload }, payload: { id: uuidv4(), ...payload },
}), }),
}, },
caRecalled: (state, action: PayloadAction<{ data: ControlAdapterEntity }>) => { caRecalled: (state, action: PayloadAction<{ data: CanvasControlAdapterState }>) => {
const { data } = action.payload; const { data } = action.payload;
state.controlAdapters.entities.push(data); state.controlAdapters.entities.push(data);
state.selectedEntityIdentifier = { type: 'control_adapter', id: data.id }; state.selectedEntityIdentifier = { type: 'control_adapter', id: data.id };
@ -217,11 +217,11 @@ export const controlAdaptersReducers = {
// We may need to convert the CA to match the model // We may need to convert the CA to match the model
if (ca.adapterType === 't2i_adapter' && ca.model.type === 'controlnet') { if (ca.adapterType === 't2i_adapter' && ca.model.type === 'controlnet') {
const convertedCA: ControlNetData = { ...ca, adapterType: 'controlnet', controlMode: 'balanced' }; const convertedCA: CanvasControlNetState = { ...ca, adapterType: 'controlnet', controlMode: 'balanced' };
state.controlAdapters.entities.splice(state.controlAdapters.entities.indexOf(ca), 1, convertedCA); state.controlAdapters.entities.splice(state.controlAdapters.entities.indexOf(ca), 1, convertedCA);
} else if (ca.adapterType === 'controlnet' && ca.model.type === 't2i_adapter') { } else if (ca.adapterType === 'controlnet' && ca.model.type === 't2i_adapter') {
const { controlMode: _, ...rest } = ca; const { controlMode: _, ...rest } = ca;
const convertedCA: T2IAdapterData = { ...rest, adapterType: 't2i_adapter' }; const convertedCA: CanvasT2IAdapterState = { ...rest, adapterType: 't2i_adapter' };
state.controlAdapters.entities.splice(state.controlAdapters.entities.indexOf(ca), 1, convertedCA); state.controlAdapters.entities.splice(state.controlAdapters.entities.indexOf(ca), 1, convertedCA);
} }
}, },

View File

@ -1,11 +1,11 @@
import type { PayloadAction, SliceCaseReducers } from '@reduxjs/toolkit'; import type { PayloadAction, SliceCaseReducers } from '@reduxjs/toolkit';
import type { import type {
BrushLine, CanvasBrushLineState,
CanvasV2State, CanvasV2State,
Coordinate, Coordinate,
EraserLine, CanvasEraserLineState,
InpaintMaskEntity, CanvasInpaintMaskState,
RectShape, CanvasRectState,
ScaleChangedArg, ScaleChangedArg,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { imageDTOToImageWithDims } from 'features/controlLayers/store/types'; import { imageDTOToImageWithDims } from 'features/controlLayers/store/types';
@ -21,7 +21,7 @@ export const inpaintMaskReducers = {
state.inpaintMask.bboxNeedsUpdate = false; state.inpaintMask.bboxNeedsUpdate = false;
state.inpaintMask.imageCache = null; state.inpaintMask.imageCache = null;
}, },
imRecalled: (state, action: PayloadAction<{ data: InpaintMaskEntity }>) => { imRecalled: (state, action: PayloadAction<{ data: CanvasInpaintMaskState }>) => {
const { data } = action.payload; const { data } = action.payload;
state.inpaintMask = data; state.inpaintMask = data;
state.selectedEntityIdentifier = { type: 'inpaint_mask', id: data.id }; state.selectedEntityIdentifier = { type: 'inpaint_mask', id: data.id };
@ -42,7 +42,7 @@ export const inpaintMaskReducers = {
} else if (obj.type === 'eraser_line') { } else if (obj.type === 'eraser_line') {
obj.points = obj.points.map((point) => point * scale); obj.points = obj.points.map((point) => point * scale);
obj.strokeWidth *= scale; obj.strokeWidth *= scale;
} else if (obj.type === 'rect_shape') { } else if (obj.type === 'rect') {
obj.x *= scale; obj.x *= scale;
obj.y *= scale; obj.y *= scale;
obj.height *= scale; obj.height *= scale;
@ -66,19 +66,19 @@ export const inpaintMaskReducers = {
const { imageDTO } = action.payload; const { imageDTO } = action.payload;
state.inpaintMask.imageCache = imageDTO ? imageDTOToImageWithDims(imageDTO) : null; state.inpaintMask.imageCache = imageDTO ? imageDTOToImageWithDims(imageDTO) : null;
}, },
imBrushLineAdded: (state, action: PayloadAction<{ brushLine: BrushLine }>) => { imBrushLineAdded: (state, action: PayloadAction<{ brushLine: CanvasBrushLineState }>) => {
const { brushLine } = action.payload; const { brushLine } = action.payload;
state.inpaintMask.objects.push(brushLine); state.inpaintMask.objects.push(brushLine);
state.inpaintMask.bboxNeedsUpdate = true; state.inpaintMask.bboxNeedsUpdate = true;
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
imEraserLineAdded: (state, action: PayloadAction<{ eraserLine: EraserLine }>) => { imEraserLineAdded: (state, action: PayloadAction<{ eraserLine: CanvasEraserLineState }>) => {
const { eraserLine } = action.payload; const { eraserLine } = action.payload;
state.inpaintMask.objects.push(eraserLine); state.inpaintMask.objects.push(eraserLine);
state.inpaintMask.bboxNeedsUpdate = true; state.inpaintMask.bboxNeedsUpdate = true;
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
imRectShapeAdded: (state, action: PayloadAction<{ rectShape: RectShape }>) => { imRectShapeAdded: (state, action: PayloadAction<{ rectShape: CanvasRectState }>) => {
const { rectShape } = action.payload; const { rectShape } = action.payload;
state.inpaintMask.objects.push(rectShape); state.inpaintMask.objects.push(rectShape);
state.inpaintMask.bboxNeedsUpdate = true; state.inpaintMask.bboxNeedsUpdate = true;

View File

@ -4,7 +4,7 @@ import type { ImageDTO, IPAdapterModelConfig } from 'services/api/types';
import { assert } from 'tsafe'; import { assert } from 'tsafe';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import type { CanvasV2State, CLIPVisionModelV2, IPAdapterConfig, IPAdapterEntity, IPMethodV2 } from './types'; import type { CanvasV2State, CLIPVisionModelV2, IPAdapterConfig, CanvasIPAdapterState, IPMethodV2 } from './types';
import { imageDTOToImageObject } from './types'; import { imageDTOToImageObject } from './types';
export const selectIPA = (state: CanvasV2State, id: string) => state.ipAdapters.entities.find((ipa) => ipa.id === id); export const selectIPA = (state: CanvasV2State, id: string) => state.ipAdapters.entities.find((ipa) => ipa.id === id);
@ -18,7 +18,7 @@ export const ipAdaptersReducers = {
ipaAdded: { ipaAdded: {
reducer: (state, action: PayloadAction<{ id: string; config: IPAdapterConfig }>) => { reducer: (state, action: PayloadAction<{ id: string; config: IPAdapterConfig }>) => {
const { id, config } = action.payload; const { id, config } = action.payload;
const layer: IPAdapterEntity = { const layer: CanvasIPAdapterState = {
id, id,
type: 'ip_adapter', type: 'ip_adapter',
isEnabled: true, isEnabled: true,
@ -29,7 +29,7 @@ export const ipAdaptersReducers = {
}, },
prepare: (payload: { config: IPAdapterConfig }) => ({ payload: { id: uuidv4(), ...payload } }), prepare: (payload: { config: IPAdapterConfig }) => ({ payload: { id: uuidv4(), ...payload } }),
}, },
ipaRecalled: (state, action: PayloadAction<{ data: IPAdapterEntity }>) => { ipaRecalled: (state, action: PayloadAction<{ data: CanvasIPAdapterState }>) => {
const { data } = action.payload; const { data } = action.payload;
state.ipAdapters.entities.push(data); state.ipAdapters.entities.push(data);
state.selectedEntityIdentifier = { type: 'ip_adapter', id: data.id }; state.selectedEntityIdentifier = { type: 'ip_adapter', id: data.id };

View File

@ -7,15 +7,15 @@ import type { ImageDTO } from 'services/api/types';
import { assert } from 'tsafe'; import { assert } from 'tsafe';
import type { import type {
BrushLine, CanvasBrushLineState,
CanvasV2State, CanvasV2State,
Coordinate, Coordinate,
EraserLine, CanvasEraserLineState,
ImageObject, CanvasImageState,
ImageObjectAddedArg, ImageObjectAddedArg,
LayerEntity, CanvasLayerState,
PositionChangedArg, PositionChangedArg,
RectShape, CanvasRectState,
} from './types'; } from './types';
import { imageDTOToImageObject, imageDTOToImageWithDims } from './types'; import { imageDTOToImageObject, imageDTOToImageWithDims } from './types';
@ -28,9 +28,9 @@ export const selectLayerOrThrow = (state: CanvasV2State, id: string) => {
export const layersReducers = { export const layersReducers = {
layerAdded: { layerAdded: {
reducer: (state, action: PayloadAction<{ id: string; overrides?: Partial<LayerEntity> }>) => { reducer: (state, action: PayloadAction<{ id: string; overrides?: Partial<CanvasLayerState> }>) => {
const { id } = action.payload; const { id } = action.payload;
const layer: LayerEntity = { const layer: CanvasLayerState = {
id, id,
type: 'layer', type: 'layer',
isEnabled: true, isEnabled: true,
@ -43,11 +43,11 @@ export const layersReducers = {
state.selectedEntityIdentifier = { type: 'layer', id }; state.selectedEntityIdentifier = { type: 'layer', id };
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
prepare: (payload: { overrides?: Partial<LayerEntity> }) => ({ prepare: (payload: { overrides?: Partial<CanvasLayerState> }) => ({
payload: { ...payload, id: getPrefixedId('layer') }, payload: { ...payload, id: getPrefixedId('layer') },
}), }),
}, },
layerRecalled: (state, action: PayloadAction<{ data: LayerEntity }>) => { layerRecalled: (state, action: PayloadAction<{ data: CanvasLayerState }>) => {
const { data } = action.payload; const { data } = action.payload;
state.layers.entities.push(data); state.layers.entities.push(data);
state.selectedEntityIdentifier = { type: 'layer', id: data.id }; state.selectedEntityIdentifier = { type: 'layer', id: data.id };
@ -148,7 +148,7 @@ export const layersReducers = {
moveToStart(state.layers.entities, layer); moveToStart(state.layers.entities, layer);
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
layerBrushLineAdded: (state, action: PayloadAction<{ id: string; brushLine: BrushLine }>) => { layerBrushLineAdded: (state, action: PayloadAction<{ id: string; brushLine: CanvasBrushLineState }>) => {
const { id, brushLine } = action.payload; const { id, brushLine } = action.payload;
const layer = selectLayer(state, id); const layer = selectLayer(state, id);
if (!layer) { if (!layer) {
@ -158,7 +158,7 @@ export const layersReducers = {
layer.objects.push(brushLine); layer.objects.push(brushLine);
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
layerEraserLineAdded: (state, action: PayloadAction<{ id: string; eraserLine: EraserLine }>) => { layerEraserLineAdded: (state, action: PayloadAction<{ id: string; eraserLine: CanvasEraserLineState }>) => {
const { id, eraserLine } = action.payload; const { id, eraserLine } = action.payload;
const layer = selectLayer(state, id); const layer = selectLayer(state, id);
if (!layer) { if (!layer) {
@ -168,7 +168,7 @@ export const layersReducers = {
layer.objects.push(eraserLine); layer.objects.push(eraserLine);
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
layerRectShapeAdded: (state, action: PayloadAction<{ id: string; rectShape: RectShape }>) => { layerRectShapeAdded: (state, action: PayloadAction<{ id: string; rectShape: CanvasRectState }>) => {
const { id, rectShape } = action.payload; const { id, rectShape } = action.payload;
const layer = selectLayer(state, id); const layer = selectLayer(state, id);
if (!layer) { if (!layer) {
@ -199,7 +199,7 @@ export const layersReducers = {
const { imageDTO } = action.payload; const { imageDTO } = action.payload;
state.layers.imageCache = imageDTO ? imageDTOToImageWithDims(imageDTO) : null; state.layers.imageCache = imageDTO ? imageDTOToImageWithDims(imageDTO) : null;
}, },
layerRasterized: (state, action: PayloadAction<{ id: string; imageObject: ImageObject; position: Coordinate }>) => { layerRasterized: (state, action: PayloadAction<{ id: string; imageObject: CanvasImageState; position: Coordinate }>) => {
const { id, imageObject, position } = action.payload; const { id, imageObject, position } = action.payload;
const layer = selectLayer(state, id); const layer = selectLayer(state, id);
if (!layer) { if (!layer) {

View File

@ -1,13 +1,13 @@
import type { PayloadAction, SliceCaseReducers } from '@reduxjs/toolkit'; import type { PayloadAction, SliceCaseReducers } from '@reduxjs/toolkit';
import { moveOneToEnd, moveOneToStart, moveToEnd, moveToStart } from 'common/util/arrayUtils'; import { moveOneToEnd, moveOneToStart, moveToEnd, moveToStart } from 'common/util/arrayUtils';
import type { import type {
BrushLine, CanvasBrushLineState,
CanvasV2State, CanvasV2State,
CLIPVisionModelV2, CLIPVisionModelV2,
EraserLine, CanvasEraserLineState,
IPMethodV2, IPMethodV2,
PositionChangedArg, PositionChangedArg,
RectShape, CanvasRectState,
ScaleChangedArg, ScaleChangedArg,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { imageDTOToImageObject, imageDTOToImageWithDims } from 'features/controlLayers/store/types'; import { imageDTOToImageObject, imageDTOToImageWithDims } from 'features/controlLayers/store/types';
@ -19,7 +19,7 @@ import type { ImageDTO, IPAdapterModelConfig } from 'services/api/types';
import { assert } from 'tsafe'; import { assert } from 'tsafe';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import type { IPAdapterEntity, RegionEntity, RgbColor } from './types'; import type { CanvasIPAdapterState, CanvasRegionalGuidanceState, RgbColor } from './types';
export const selectRG = (state: CanvasV2State, id: string) => state.regions.entities.find((rg) => rg.id === id); export const selectRG = (state: CanvasV2State, id: string) => state.regions.entities.find((rg) => rg.id === id);
export const selectRGOrThrow = (state: CanvasV2State, id: string) => { export const selectRGOrThrow = (state: CanvasV2State, id: string) => {
@ -54,7 +54,7 @@ export const regionsReducers = {
rgAdded: { rgAdded: {
reducer: (state, action: PayloadAction<{ id: string }>) => { reducer: (state, action: PayloadAction<{ id: string }>) => {
const { id } = action.payload; const { id } = action.payload;
const rg: RegionEntity = { const rg: CanvasRegionalGuidanceState = {
id, id,
type: 'regional_guidance', type: 'regional_guidance',
isEnabled: true, isEnabled: true,
@ -85,7 +85,7 @@ export const regionsReducers = {
rg.bboxNeedsUpdate = false; rg.bboxNeedsUpdate = false;
rg.imageCache = null; rg.imageCache = null;
}, },
rgRecalled: (state, action: PayloadAction<{ data: RegionEntity }>) => { rgRecalled: (state, action: PayloadAction<{ data: CanvasRegionalGuidanceState }>) => {
const { data } = action.payload; const { data } = action.payload;
state.regions.entities.push(data); state.regions.entities.push(data);
state.selectedEntityIdentifier = { type: 'regional_guidance', id: data.id }; state.selectedEntityIdentifier = { type: 'regional_guidance', id: data.id };
@ -117,7 +117,7 @@ export const regionsReducers = {
} else if (obj.type === 'eraser_line') { } else if (obj.type === 'eraser_line') {
obj.points = obj.points.map((point) => point * scale); obj.points = obj.points.map((point) => point * scale);
obj.strokeWidth *= scale; obj.strokeWidth *= scale;
} else if (obj.type === 'rect_shape') { } else if (obj.type === 'rect') {
obj.x *= scale; obj.x *= scale;
obj.y *= scale; obj.y *= scale;
obj.height *= scale; obj.height *= scale;
@ -215,7 +215,7 @@ export const regionsReducers = {
} }
rg.autoNegative = autoNegative; rg.autoNegative = autoNegative;
}, },
rgIPAdapterAdded: (state, action: PayloadAction<{ id: string; ipAdapter: IPAdapterEntity }>) => { rgIPAdapterAdded: (state, action: PayloadAction<{ id: string; ipAdapter: CanvasIPAdapterState }>) => {
const { id, ipAdapter } = action.payload; const { id, ipAdapter } = action.payload;
const rg = selectRG(state, id); const rg = selectRG(state, id);
if (!rg) { if (!rg) {
@ -328,7 +328,7 @@ export const regionsReducers = {
} }
ipa.clipVisionModel = clipVisionModel; ipa.clipVisionModel = clipVisionModel;
}, },
rgBrushLineAdded: (state, action: PayloadAction<{ id: string; brushLine: BrushLine }>) => { rgBrushLineAdded: (state, action: PayloadAction<{ id: string; brushLine: CanvasBrushLineState }>) => {
const { id, brushLine } = action.payload; const { id, brushLine } = action.payload;
const rg = selectRG(state, id); const rg = selectRG(state, id);
if (!rg) { if (!rg) {
@ -339,7 +339,7 @@ export const regionsReducers = {
rg.bboxNeedsUpdate = true; rg.bboxNeedsUpdate = true;
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
rgEraserLineAdded: (state, action: PayloadAction<{ id: string; eraserLine: EraserLine }>) => { rgEraserLineAdded: (state, action: PayloadAction<{ id: string; eraserLine: CanvasEraserLineState }>) => {
const { id, eraserLine } = action.payload; const { id, eraserLine } = action.payload;
const rg = selectRG(state, id); const rg = selectRG(state, id);
if (!rg) { if (!rg) {
@ -350,7 +350,7 @@ export const regionsReducers = {
rg.bboxNeedsUpdate = true; rg.bboxNeedsUpdate = true;
state.layers.imageCache = null; state.layers.imageCache = null;
}, },
rgRectShapeAdded: (state, action: PayloadAction<{ id: string; rectShape: RectShape }>) => { rgRectShapeAdded: (state, action: PayloadAction<{ id: string; rectShape: CanvasRectState }>) => {
const { id, rectShape } = action.payload; const { id, rectShape } = action.payload;
const rg = selectRG(state, id); const rg = selectRG(state, id);
if (!rg) { if (!rg) {

View File

@ -527,7 +527,7 @@ const zRect = z.object({
}); });
export type Rect = z.infer<typeof zRect>; export type Rect = z.infer<typeof zRect>;
const zBrushLine = z.object({ const zCanvasBrushLineState = 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),
@ -535,32 +535,32 @@ const zBrushLine = z.object({
color: zRgbaColor, color: zRgbaColor,
clip: zRect.nullable(), clip: zRect.nullable(),
}); });
export type BrushLine = z.infer<typeof zBrushLine>; export type CanvasBrushLineState = z.infer<typeof zCanvasBrushLineState>;
const zEraserline = z.object({ const zCanvasEraserLineState = z.object({
id: zId, id: zId,
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(), clip: zRect.nullable(),
}); });
export type EraserLine = z.infer<typeof zEraserline>; export type CanvasEraserLineState = z.infer<typeof zCanvasEraserLineState>;
const zRectShape = z.object({ const zCanvasRectState = z.object({
id: zId, id: zId,
type: z.literal('rect_shape'), type: z.literal('rect'),
x: z.number(), x: z.number(),
y: z.number(), y: z.number(),
width: z.number().min(1), width: z.number().min(1),
height: z.number().min(1), height: z.number().min(1),
color: zRgbaColor, color: zRgbaColor,
}); });
export type RectShape = z.infer<typeof zRectShape>; export type CanvasRectState = z.infer<typeof zCanvasRectState>;
const zFilter = z.enum(['LightnessToAlphaFilter']); const zFilter = z.enum(['LightnessToAlphaFilter']);
export type Filter = z.infer<typeof zFilter>; export type Filter = z.infer<typeof zFilter>;
const zImageObject = z.object({ const zCanvasImageState = z.object({
id: zId, id: zId,
type: z.literal('image'), type: z.literal('image'),
image: zImageWithDims, image: zImageWithDims,
@ -570,46 +570,46 @@ const zImageObject = z.object({
height: z.number().min(1), height: z.number().min(1),
filters: z.array(zFilter), filters: z.array(zFilter),
}); });
export type ImageObject = z.infer<typeof zImageObject>; export type CanvasImageState = z.infer<typeof zCanvasImageState>;
const zRenderableObject = z.discriminatedUnion('type', [zImageObject, zBrushLine, zEraserline, zRectShape]); const zCanvasObjectState = z.discriminatedUnion('type', [zCanvasImageState, zCanvasBrushLineState, zCanvasEraserLineState, zCanvasRectState]);
export type RenderableObject = z.infer<typeof zRenderableObject>; export type CanvasObjectState = z.infer<typeof zCanvasObjectState>;
export const zLayerEntity = z.object({ export const zCanvasLayerState = z.object({
id: zId, id: zId,
type: z.literal('layer'), type: z.literal('layer'),
isEnabled: z.boolean(), isEnabled: z.boolean(),
position: zCoordinate, position: zCoordinate,
opacity: zOpacity, opacity: zOpacity,
objects: z.array(zRenderableObject), objects: z.array(zCanvasObjectState),
}); });
export type LayerEntity = z.infer<typeof zLayerEntity>; export type CanvasLayerState = z.infer<typeof zCanvasLayerState>;
export const zIPAdapterEntity = z.object({ export const zCanvasIPAdapterState = z.object({
id: zId, id: zId,
type: z.literal('ip_adapter'), type: z.literal('ip_adapter'),
isEnabled: z.boolean(), isEnabled: z.boolean(),
weight: z.number().gte(-1).lte(2), weight: z.number().gte(-1).lte(2),
method: zIPMethodV2, method: zIPMethodV2,
imageObject: zImageObject.nullable(), imageObject: zCanvasImageState.nullable(),
model: zModelIdentifierField.nullable(), model: zModelIdentifierField.nullable(),
clipVisionModel: zCLIPVisionModelV2, clipVisionModel: zCLIPVisionModelV2,
beginEndStepPct: zBeginEndStepPct, beginEndStepPct: zBeginEndStepPct,
}); });
export type IPAdapterEntity = z.infer<typeof zIPAdapterEntity>; export type CanvasIPAdapterState = z.infer<typeof zCanvasIPAdapterState>;
export type IPAdapterConfig = Pick< export type IPAdapterConfig = Pick<
IPAdapterEntity, CanvasIPAdapterState,
'weight' | 'imageObject' | 'beginEndStepPct' | 'model' | 'clipVisionModel' | 'method' 'weight' | 'imageObject' | 'beginEndStepPct' | 'model' | 'clipVisionModel' | 'method'
>; >;
const zMaskObject = z const zMaskObject = z
.discriminatedUnion('type', [zOLD_VectorMaskLine, zOLD_VectorMaskRect, zBrushLine, zEraserline, zRectShape]) .discriminatedUnion('type', [zOLD_VectorMaskLine, zOLD_VectorMaskRect, zCanvasBrushLineState, zCanvasEraserLineState, zCanvasRectState])
.transform((val) => { .transform((val) => {
// Migrate old vector mask objects to new format // Migrate old vector mask objects to new format
if (val.type === 'vector_mask_line') { if (val.type === 'vector_mask_line') {
const { tool, ...rest } = val; const { tool, ...rest } = val;
if (tool === 'brush') { if (tool === 'brush') {
const asBrushline: BrushLine = { const asBrushline: CanvasBrushLineState = {
...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 },
@ -617,7 +617,7 @@ const zMaskObject = z
}; };
return asBrushline; return asBrushline;
} else if (tool === 'eraser') { } else if (tool === 'eraser') {
const asEraserLine: EraserLine = { const asEraserLine: CanvasEraserLineState = {
...rest, ...rest,
type: 'eraser_line', type: 'eraser_line',
clip: null, clip: null,
@ -625,9 +625,9 @@ const zMaskObject = z
return asEraserLine; return asEraserLine;
} }
} else if (val.type === 'vector_mask_rect') { } else if (val.type === 'vector_mask_rect') {
const asRectShape: RectShape = { const asRectShape: CanvasRectState = {
...val, ...val,
type: 'rect_shape', type: 'rect',
color: { r: 255, g: 255, b: 255, a: 1 }, color: { r: 255, g: 255, b: 255, a: 1 },
}; };
return asRectShape; return asRectShape;
@ -635,9 +635,9 @@ const zMaskObject = z
return val; return val;
} }
}) })
.pipe(z.discriminatedUnion('type', [zBrushLine, zEraserline, zRectShape])); .pipe(z.discriminatedUnion('type', [zCanvasBrushLineState, zCanvasEraserLineState, zCanvasRectState]));
export const zRegionEntity = z.object({ export const zCanvasRegionalGuidanceState = z.object({
id: zId, id: zId,
type: z.literal('regional_guidance'), type: z.literal('regional_guidance'),
isEnabled: z.boolean(), isEnabled: z.boolean(),
@ -647,12 +647,12 @@ export const zRegionEntity = z.object({
objects: z.array(zMaskObject), objects: z.array(zMaskObject),
positivePrompt: zParameterPositivePrompt.nullable(), positivePrompt: zParameterPositivePrompt.nullable(),
negativePrompt: zParameterNegativePrompt.nullable(), negativePrompt: zParameterNegativePrompt.nullable(),
ipAdapters: z.array(zIPAdapterEntity), ipAdapters: z.array(zCanvasIPAdapterState),
fill: zRgbColor, fill: zRgbColor,
autoNegative: zAutoNegative, autoNegative: zAutoNegative,
imageCache: zImageWithDims.nullable(), imageCache: zImageWithDims.nullable(),
}); });
export type RegionEntity = z.infer<typeof zRegionEntity>; export type CanvasRegionalGuidanceState = z.infer<typeof zCanvasRegionalGuidanceState>;
const zColorFill = z.object({ const zColorFill = z.object({
type: z.literal('color_fill'), type: z.literal('color_fill'),
@ -663,7 +663,7 @@ const zImageFill = z.object({
src: z.string(), src: z.string(),
}); });
const zFill = z.discriminatedUnion('type', [zColorFill, zImageFill]); const zFill = z.discriminatedUnion('type', [zColorFill, zImageFill]);
const zInpaintMaskEntity = z.object({ const zCanvasInpaintMaskState = z.object({
id: z.literal('inpaint_mask'), id: z.literal('inpaint_mask'),
type: z.literal('inpaint_mask'), type: z.literal('inpaint_mask'),
isEnabled: z.boolean(), isEnabled: z.boolean(),
@ -674,7 +674,7 @@ const zInpaintMaskEntity = z.object({
fill: zRgbColor, fill: zRgbColor,
imageCache: zImageWithDims.nullable(), imageCache: zImageWithDims.nullable(),
}); });
export type InpaintMaskEntity = z.infer<typeof zInpaintMaskEntity>; export type CanvasInpaintMaskState = z.infer<typeof zCanvasInpaintMaskState>;
const zInitialImageEntity = z.object({ const zInitialImageEntity = z.object({
id: z.literal('initial_image'), id: z.literal('initial_image'),
@ -682,11 +682,11 @@ const zInitialImageEntity = z.object({
isEnabled: z.boolean(), isEnabled: z.boolean(),
bbox: zRect.nullable(), bbox: zRect.nullable(),
bboxNeedsUpdate: z.boolean(), bboxNeedsUpdate: z.boolean(),
imageObject: zImageObject.nullable(), imageObject: zCanvasImageState.nullable(),
}); });
export type InitialImageEntity = z.infer<typeof zInitialImageEntity>; export type InitialImageEntity = z.infer<typeof zInitialImageEntity>;
const zControlAdapterEntityBase = z.object({ const zCanvasControlAdapterStateBase = z.object({
id: zId, id: zId,
type: z.literal('control_adapter'), type: z.literal('control_adapter'),
isEnabled: z.boolean(), isEnabled: z.boolean(),
@ -696,27 +696,27 @@ const zControlAdapterEntityBase = z.object({
opacity: zOpacity, opacity: zOpacity,
filters: z.array(zFilter), filters: z.array(zFilter),
weight: z.number().gte(-1).lte(2), weight: z.number().gte(-1).lte(2),
imageObject: zImageObject.nullable(), imageObject: zCanvasImageState.nullable(),
processedImageObject: zImageObject.nullable(), processedImageObject: zCanvasImageState.nullable(),
processorConfig: zProcessorConfig.nullable(), processorConfig: zProcessorConfig.nullable(),
processorPendingBatchId: z.string().nullable().default(null), processorPendingBatchId: z.string().nullable().default(null),
beginEndStepPct: zBeginEndStepPct, beginEndStepPct: zBeginEndStepPct,
model: zModelIdentifierField.nullable(), model: zModelIdentifierField.nullable(),
}); });
const zControlNetEntity = zControlAdapterEntityBase.extend({ const zCanvasControlNetState = zCanvasControlAdapterStateBase.extend({
adapterType: z.literal('controlnet'), adapterType: z.literal('controlnet'),
controlMode: zControlModeV2, controlMode: zControlModeV2,
}); });
export type ControlNetData = z.infer<typeof zControlNetEntity>; export type CanvasControlNetState = z.infer<typeof zCanvasControlNetState>;
const zT2IAdapterEntity = zControlAdapterEntityBase.extend({ const zCanvasT2IAdapteState = zCanvasControlAdapterStateBase.extend({
adapterType: z.literal('t2i_adapter'), adapterType: z.literal('t2i_adapter'),
}); });
export type T2IAdapterData = z.infer<typeof zT2IAdapterEntity>; export type CanvasT2IAdapterState = z.infer<typeof zCanvasT2IAdapteState>;
export const zControlAdapterEntity = z.discriminatedUnion('adapterType', [zControlNetEntity, zT2IAdapterEntity]); export const zCanvasControlAdapterState = z.discriminatedUnion('adapterType', [zCanvasControlNetState, zCanvasT2IAdapteState]);
export type ControlAdapterEntity = z.infer<typeof zControlAdapterEntity>; export type CanvasControlAdapterState = z.infer<typeof zCanvasControlAdapterState>;
export type ControlNetConfig = Pick< export type ControlNetConfig = Pick<
ControlNetData, CanvasControlNetState,
| 'adapterType' | 'adapterType'
| 'weight' | 'weight'
| 'imageObject' | 'imageObject'
@ -727,7 +727,7 @@ export type ControlNetConfig = Pick<
| 'controlMode' | 'controlMode'
>; >;
export type T2IAdapterConfig = Pick< export type T2IAdapterConfig = Pick<
T2IAdapterData, CanvasT2IAdapterState,
'adapterType' | 'weight' | 'imageObject' | 'processedImageObject' | 'processorConfig' | 'beginEndStepPct' | 'model' 'adapterType' | 'weight' | 'imageObject' | 'processedImageObject' | 'processorConfig' | 'beginEndStepPct' | 'model'
>; >;
@ -778,7 +778,7 @@ export const imageDTOToImageWithDims = ({ image_name, width, height }: ImageDTO)
height, height,
}); });
export const imageDTOToImageObject = (imageDTO: ImageDTO, overrides?: Partial<ImageObject>): ImageObject => { export const imageDTOToImageObject = (imageDTO: ImageDTO, overrides?: Partial<CanvasImageState>): CanvasImageState => {
const { width, height, image_name } = imageDTO; const { width, height, image_name } = imageDTO;
return { return {
id: getObjectId('image'), id: getObjectId('image'),
@ -803,11 +803,11 @@ export const isBoundingBoxScaleMethod = (v: unknown): v is BoundingBoxScaleMetho
zBoundingBoxScaleMethod.safeParse(v).success; zBoundingBoxScaleMethod.safeParse(v).success;
export type CanvasEntity = export type CanvasEntity =
| LayerEntity | CanvasLayerState
| ControlAdapterEntity | CanvasControlAdapterState
| RegionEntity | CanvasRegionalGuidanceState
| InpaintMaskEntity | CanvasInpaintMaskState
| IPAdapterEntity | CanvasIPAdapterState
| InitialImageEntity; | InitialImageEntity;
export type CanvasEntityIdentifier = Pick<CanvasEntity, 'id' | 'type'>; export type CanvasEntityIdentifier = Pick<CanvasEntity, 'id' | 'type'>;
@ -827,14 +827,14 @@ export type StagingAreaImage = {
export type CanvasV2State = { export type CanvasV2State = {
_version: 3; _version: 3;
selectedEntityIdentifier: CanvasEntityIdentifier | null; selectedEntityIdentifier: CanvasEntityIdentifier | null;
inpaintMask: InpaintMaskEntity; inpaintMask: CanvasInpaintMaskState;
layers: { layers: {
imageCache: ImageWithDims | null; imageCache: ImageWithDims | null;
entities: LayerEntity[]; entities: CanvasLayerState[];
}; };
controlAdapters: { entities: ControlAdapterEntity[] }; controlAdapters: { entities: CanvasControlAdapterState[] };
ipAdapters: { entities: IPAdapterEntity[] }; ipAdapters: { entities: CanvasIPAdapterState[] };
regions: { entities: RegionEntity[] }; regions: { entities: CanvasRegionalGuidanceState[] };
loras: LoRA[]; loras: LoRA[];
initialImage: InitialImageEntity; initialImage: InitialImageEntity;
tool: { tool: {
@ -932,7 +932,7 @@ export type RectShapeAddedArg = { id: string; rect: IRect; color: RgbaColor };
export type ImageObjectAddedArg = { id: string; imageDTO: ImageDTO; position?: Coordinate }; export type ImageObjectAddedArg = { id: string; imageDTO: ImageDTO; position?: Coordinate };
//#region Type guards //#region Type guards
export const isLine = (obj: RenderableObject): obj is BrushLine | EraserLine => { export const isLine = (obj: CanvasObjectState): obj is CanvasBrushLineState | CanvasEraserLineState => {
return obj.type === 'brush_line' || obj.type === 'eraser_line'; return obj.type === 'brush_line' || obj.type === 'eraser_line';
}; };
@ -949,7 +949,7 @@ export type RemoveIndexString<T> = {
export type GenerationMode = 'txt2img' | 'img2img' | 'inpaint' | 'outpaint'; export type GenerationMode = 'txt2img' | 'img2img' | 'inpaint' | 'outpaint';
export function isDrawableEntity(entity: CanvasEntity): entity is LayerEntity | RegionEntity | InpaintMaskEntity { export function isDrawableEntity(entity: CanvasEntity): entity is CanvasLayerState | CanvasRegionalGuidanceState | CanvasInpaintMaskState {
return entity.type === 'layer' || entity.type === 'regional_guidance' || entity.type === 'inpaint_mask'; return entity.type === 'layer' || entity.type === 'regional_guidance' || entity.type === 'inpaint_mask';
} }

View File

@ -1,4 +1,4 @@
import type { LayerEntity } from 'features/controlLayers/store/types'; import type { CanvasLayerState } from 'features/controlLayers/store/types';
import { MetadataItemView } from 'features/metadata/components/MetadataItemView'; import { MetadataItemView } from 'features/metadata/components/MetadataItemView';
import type { MetadataHandlers } from 'features/metadata/types'; import type { MetadataHandlers } from 'features/metadata/types';
import { handlers } from 'features/metadata/util/handlers'; import { handlers } from 'features/metadata/util/handlers';
@ -9,7 +9,7 @@ type Props = {
}; };
export const MetadataLayers = ({ metadata }: Props) => { export const MetadataLayers = ({ metadata }: Props) => {
const [layers, setLayers] = useState<LayerEntity[]>([]); const [layers, setLayers] = useState<CanvasLayerState[]>([]);
useEffect(() => { useEffect(() => {
const parse = async () => { const parse = async () => {
@ -40,8 +40,8 @@ const MetadataViewLayer = ({
handlers, handlers,
}: { }: {
label: string; label: string;
layer: LayerEntity; layer: CanvasLayerState;
handlers: MetadataHandlers<LayerEntity[], LayerEntity>; handlers: MetadataHandlers<CanvasLayerState[], CanvasLayerState>;
}) => { }) => {
const onRecall = useCallback(() => { const onRecall = useCallback(() => {
if (!handlers.recallItem) { if (!handlers.recallItem) {

View File

@ -2,7 +2,7 @@ import { getStore } from 'app/store/nanostores/store';
import { deepClone } from 'common/util/deepClone'; import { deepClone } from 'common/util/deepClone';
import { objectKeys } from 'common/util/objectKeys'; import { objectKeys } from 'common/util/objectKeys';
import { shouldConcatPromptsChanged } from 'features/controlLayers/store/canvasV2Slice'; import { shouldConcatPromptsChanged } from 'features/controlLayers/store/canvasV2Slice';
import type { LayerEntity, LoRA } from 'features/controlLayers/store/types'; import type { CanvasLayerState, LoRA } from 'features/controlLayers/store/types';
import type { import type {
AnyControlAdapterConfigMetadata, AnyControlAdapterConfigMetadata,
BuildMetadataHandlers, BuildMetadataHandlers,
@ -48,7 +48,7 @@ const renderControlAdapterValue: MetadataRenderValueFunc<AnyControlAdapterConfig
return `${value.model.key} (${value.model.base.toUpperCase()}) - ${value.weight}`; return `${value.model.key} (${value.model.base.toUpperCase()}) - ${value.weight}`;
} }
}; };
const renderLayerValue: MetadataRenderValueFunc<LayerEntity> = async (layer) => { const renderLayerValue: MetadataRenderValueFunc<CanvasLayerState> = async (layer) => {
if (layer.type === 'initial_image_layer') { if (layer.type === 'initial_image_layer') {
let rendered = t('controlLayers.globalInitialImageLayer'); let rendered = t('controlLayers.globalInitialImageLayer');
if (layer.image) { if (layer.image) {
@ -88,7 +88,7 @@ const renderLayerValue: MetadataRenderValueFunc<LayerEntity> = async (layer) =>
} }
assert(false, 'Unknown layer type'); assert(false, 'Unknown layer type');
}; };
const renderLayersValue: MetadataRenderValueFunc<LayerEntity[]> = async (layers) => { const renderLayersValue: MetadataRenderValueFunc<CanvasLayerState[]> = async (layers) => {
return `${layers.length} ${t('controlLayers.layers', { count: layers.length })}`; return `${layers.length} ${t('controlLayers.layers', { count: layers.length })}`;
}; };

View File

@ -1,6 +1,6 @@
import { getCAId, getImageObjectId, getIPAId, getLayerId } from 'features/controlLayers/konva/naming'; import { getCAId, getImageObjectId, getIPAId, getLayerId } from 'features/controlLayers/konva/naming';
import { defaultLoRAConfig } from 'features/controlLayers/store/lorasReducers'; import { defaultLoRAConfig } from 'features/controlLayers/store/lorasReducers';
import type { ControlAdapterEntity, IPAdapterEntity, LayerEntity, LoRA } from 'features/controlLayers/store/types'; import type { CanvasControlAdapterState, CanvasIPAdapterState, CanvasLayerState, LoRA } from 'features/controlLayers/store/types';
import { import {
CA_PROCESSOR_DATA, CA_PROCESSOR_DATA,
imageDTOToImageWithDims, imageDTOToImageWithDims,
@ -8,7 +8,7 @@ import {
initialIPAdapterV2, initialIPAdapterV2,
initialT2IAdapterV2, initialT2IAdapterV2,
isProcessorTypeV2, isProcessorTypeV2,
zLayerEntity, zCanvasLayerState,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import type { import type {
ControlNetConfigMetadata, ControlNetConfigMetadata,
@ -424,22 +424,22 @@ const parseAllIPAdapters: MetadataParseFunc<IPAdapterConfigMetadata[]> = async (
}; };
//#region Control Layers //#region Control Layers
const parseLayer: MetadataParseFunc<LayerEntity> = async (metadataItem) => zLayerEntity.parseAsync(metadataItem); const parseLayer: MetadataParseFunc<CanvasLayerState> = async (metadataItem) => zCanvasLayerState.parseAsync(metadataItem);
const parseLayers: MetadataParseFunc<LayerEntity[]> = async (metadata) => { const parseLayers: MetadataParseFunc<CanvasLayerState[]> = async (metadata) => {
// We need to support recalling pre-Control Layers metadata into Control Layers. A separate set of parsers handles // We need to support recalling pre-Control Layers metadata into Control Layers. A separate set of parsers handles
// taking pre-CL metadata and parsing it into layers. It doesn't always map 1-to-1, so this is best-effort. For // taking pre-CL metadata and parsing it into layers. It doesn't always map 1-to-1, so this is best-effort. For
// example, CL Control Adapters don't support resize mode, so we simply omit that property. // example, CL Control Adapters don't support resize mode, so we simply omit that property.
try { try {
const layers: LayerEntity[] = []; const layers: CanvasLayerState[] = [];
try { try {
const control_layers = await getProperty(metadata, 'control_layers'); const control_layers = await getProperty(metadata, 'control_layers');
const controlLayersRaw = await getProperty(control_layers, 'layers', isArray); const controlLayersRaw = await getProperty(control_layers, 'layers', isArray);
const controlLayersParseResults = await Promise.allSettled(controlLayersRaw.map(parseLayer)); const controlLayersParseResults = await Promise.allSettled(controlLayersRaw.map(parseLayer));
const controlLayers = controlLayersParseResults const controlLayers = controlLayersParseResults
.filter((result): result is PromiseFulfilledResult<LayerEntity> => result.status === 'fulfilled') .filter((result): result is PromiseFulfilledResult<CanvasLayerState> => result.status === 'fulfilled')
.map((result) => result.value); .map((result) => result.value);
layers.push(...controlLayers); layers.push(...controlLayers);
} catch { } catch {
@ -452,7 +452,7 @@ const parseLayers: MetadataParseFunc<LayerEntity[]> = async (metadata) => {
controlNetsRaw.map(async (cn) => await parseControlNetToControlAdapterLayer(cn)) controlNetsRaw.map(async (cn) => await parseControlNetToControlAdapterLayer(cn))
); );
const controlNetsAsLayers = controlNetsParseResults const controlNetsAsLayers = controlNetsParseResults
.filter((result): result is PromiseFulfilledResult<ControlAdapterEntity> => result.status === 'fulfilled') .filter((result): result is PromiseFulfilledResult<CanvasControlAdapterState> => result.status === 'fulfilled')
.map((result) => result.value); .map((result) => result.value);
layers.push(...controlNetsAsLayers); layers.push(...controlNetsAsLayers);
} catch { } catch {
@ -465,7 +465,7 @@ const parseLayers: MetadataParseFunc<LayerEntity[]> = async (metadata) => {
t2iAdaptersRaw.map(async (cn) => await parseT2IAdapterToControlAdapterLayer(cn)) t2iAdaptersRaw.map(async (cn) => await parseT2IAdapterToControlAdapterLayer(cn))
); );
const t2iAdaptersAsLayers = t2iAdaptersParseResults const t2iAdaptersAsLayers = t2iAdaptersParseResults
.filter((result): result is PromiseFulfilledResult<ControlAdapterEntity> => result.status === 'fulfilled') .filter((result): result is PromiseFulfilledResult<CanvasControlAdapterState> => result.status === 'fulfilled')
.map((result) => result.value); .map((result) => result.value);
layers.push(...t2iAdaptersAsLayers); layers.push(...t2iAdaptersAsLayers);
} catch { } catch {
@ -478,7 +478,7 @@ const parseLayers: MetadataParseFunc<LayerEntity[]> = async (metadata) => {
ipAdaptersRaw.map(async (cn) => await parseIPAdapterToIPAdapterLayer(cn)) ipAdaptersRaw.map(async (cn) => await parseIPAdapterToIPAdapterLayer(cn))
); );
const ipAdaptersAsLayers = ipAdaptersParseResults const ipAdaptersAsLayers = ipAdaptersParseResults
.filter((result): result is PromiseFulfilledResult<IPAdapterEntity> => result.status === 'fulfilled') .filter((result): result is PromiseFulfilledResult<CanvasIPAdapterState> => result.status === 'fulfilled')
.map((result) => result.value); .map((result) => result.value);
layers.push(...ipAdaptersAsLayers); layers.push(...ipAdaptersAsLayers);
} catch { } catch {
@ -498,14 +498,14 @@ const parseLayers: MetadataParseFunc<LayerEntity[]> = async (metadata) => {
} }
}; };
const parseInitialImageToInitialImageLayer: MetadataParseFunc<LayerEntity> = async (metadata) => { const parseInitialImageToInitialImageLayer: MetadataParseFunc<CanvasLayerState> = async (metadata) => {
// TODO(psyche): recall denoise strength // TODO(psyche): recall denoise strength
// const denoisingStrength = await getProperty(metadata, 'strength', isParameterStrength); // const denoisingStrength = await getProperty(metadata, 'strength', isParameterStrength);
const imageName = await getProperty(metadata, 'init_image', isString); const imageName = await getProperty(metadata, 'init_image', isString);
const imageDTO = await getImageDTO(imageName); const imageDTO = await getImageDTO(imageName);
assert(imageDTO, 'ImageDTO is null'); assert(imageDTO, 'ImageDTO is null');
const id = getLayerId(uuidv4()); const id = getLayerId(uuidv4());
const layer: LayerEntity = { const layer: CanvasLayerState = {
id, id,
type: 'layer', type: 'layer',
bbox: null, bbox: null,
@ -529,7 +529,7 @@ const parseInitialImageToInitialImageLayer: MetadataParseFunc<LayerEntity> = asy
return layer; return layer;
}; };
const parseControlNetToControlAdapterLayer: MetadataParseFunc<ControlAdapterEntity> = async (metadataItem) => { const parseControlNetToControlAdapterLayer: MetadataParseFunc<CanvasControlAdapterState> = async (metadataItem) => {
const control_model = await getProperty(metadataItem, 'control_model'); const control_model = await getProperty(metadataItem, 'control_model');
const key = await getModelKey(control_model, 'controlnet'); const key = await getModelKey(control_model, 'controlnet');
const controlNetModel = await fetchModelConfigWithTypeGuard(key, isControlNetModelConfig); const controlNetModel = await fetchModelConfigWithTypeGuard(key, isControlNetModelConfig);
@ -569,7 +569,7 @@ const parseControlNetToControlAdapterLayer: MetadataParseFunc<ControlAdapterEnti
const imageDTO = image ? await getImageDTO(image.image_name) : null; const imageDTO = image ? await getImageDTO(image.image_name) : null;
const processedImageDTO = processedImage ? await getImageDTO(processedImage.image_name) : null; const processedImageDTO = processedImage ? await getImageDTO(processedImage.image_name) : null;
const layer: ControlAdapterEntity = { const layer: CanvasControlAdapterState = {
id: getCAId(uuidv4()), id: getCAId(uuidv4()),
type: 'control_adapter', type: 'control_adapter',
bbox: null, bbox: null,
@ -593,7 +593,7 @@ const parseControlNetToControlAdapterLayer: MetadataParseFunc<ControlAdapterEnti
return layer; return layer;
}; };
const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc<ControlAdapterEntity> = async (metadataItem) => { const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc<CanvasControlAdapterState> = async (metadataItem) => {
const t2i_adapter_model = await getProperty(metadataItem, 't2i_adapter_model'); const t2i_adapter_model = await getProperty(metadataItem, 't2i_adapter_model');
const key = await getModelKey(t2i_adapter_model, 't2i_adapter'); const key = await getModelKey(t2i_adapter_model, 't2i_adapter');
const t2iAdapterModel = await fetchModelConfigWithTypeGuard(key, isT2IAdapterModelConfig); const t2iAdapterModel = await fetchModelConfigWithTypeGuard(key, isT2IAdapterModelConfig);
@ -630,7 +630,7 @@ const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc<ControlAdapterEnti
const imageDTO = image ? await getImageDTO(image.image_name) : null; const imageDTO = image ? await getImageDTO(image.image_name) : null;
const processedImageDTO = processedImage ? await getImageDTO(processedImage.image_name) : null; const processedImageDTO = processedImage ? await getImageDTO(processedImage.image_name) : null;
const layer: ControlAdapterEntity = { const layer: CanvasControlAdapterState = {
id: getCAId(uuidv4()), id: getCAId(uuidv4()),
bbox: null, bbox: null,
bboxNeedsUpdate: true, bboxNeedsUpdate: true,
@ -653,7 +653,7 @@ const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc<ControlAdapterEnti
return layer; return layer;
}; };
const parseIPAdapterToIPAdapterLayer: MetadataParseFunc<IPAdapterEntity> = async (metadataItem) => { const parseIPAdapterToIPAdapterLayer: MetadataParseFunc<CanvasIPAdapterState> = async (metadataItem) => {
const ip_adapter_model = await getProperty(metadataItem, 'ip_adapter_model'); const ip_adapter_model = await getProperty(metadataItem, 'ip_adapter_model');
const key = await getModelKey(ip_adapter_model, 'ip_adapter'); const key = await getModelKey(ip_adapter_model, 'ip_adapter');
const ipAdapterModel = await fetchModelConfigWithTypeGuard(key, isIPAdapterModelConfig); const ipAdapterModel = await fetchModelConfigWithTypeGuard(key, isIPAdapterModelConfig);
@ -685,7 +685,7 @@ const parseIPAdapterToIPAdapterLayer: MetadataParseFunc<IPAdapterEntity> = async
]; ];
const imageDTO = image ? await getImageDTO(image.image_name) : null; const imageDTO = image ? await getImageDTO(image.image_name) : null;
const layer: IPAdapterEntity = { const layer: CanvasIPAdapterState = {
id: getIPAId(uuidv4()), id: getIPAId(uuidv4()),
type: 'ip_adapter', type: 'ip_adapter',
isEnabled: true, isEnabled: true,

View File

@ -40,11 +40,11 @@ import {
vaeSelected, vaeSelected,
} from 'features/controlLayers/store/canvasV2Slice'; } from 'features/controlLayers/store/canvasV2Slice';
import type { import type {
ControlAdapterEntity, CanvasControlAdapterState,
IPAdapterEntity, CanvasIPAdapterState,
LayerEntity, CanvasLayerState,
LoRA, LoRA,
RegionEntity, CanvasRegionalGuidanceState,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { setHrfEnabled, setHrfMethod, setHrfStrength } from 'features/hrf/store/hrfSlice'; import { setHrfEnabled, setHrfMethod, setHrfStrength } from 'features/hrf/store/hrfSlice';
import type { import type {
@ -246,7 +246,7 @@ const recallIPAdapters: MetadataRecallFunc<IPAdapterConfigMetadata[]> = (ipAdapt
}); });
}; };
const recallCA: MetadataRecallFunc<ControlAdapterEntity> = async (ca) => { const recallCA: MetadataRecallFunc<CanvasControlAdapterState> = async (ca) => {
const { dispatch } = getStore(); const { dispatch } = getStore();
const clone = deepClone(ca); const clone = deepClone(ca);
if (clone.image) { if (clone.image) {
@ -275,7 +275,7 @@ const recallCA: MetadataRecallFunc<ControlAdapterEntity> = async (ca) => {
return; return;
}; };
const recallIPA: MetadataRecallFunc<IPAdapterEntity> = async (ipa) => { const recallIPA: MetadataRecallFunc<CanvasIPAdapterState> = async (ipa) => {
const { dispatch } = getStore(); const { dispatch } = getStore();
const clone = deepClone(ipa); const clone = deepClone(ipa);
if (clone.imageObject) { if (clone.imageObject) {
@ -298,7 +298,7 @@ const recallIPA: MetadataRecallFunc<IPAdapterEntity> = async (ipa) => {
return; return;
}; };
const recallRG: MetadataRecallFunc<RegionEntity> = async (rg) => { const recallRG: MetadataRecallFunc<CanvasRegionalGuidanceState> = async (rg) => {
const { dispatch } = getStore(); const { dispatch } = getStore();
const clone = deepClone(rg); const clone = deepClone(rg);
// Strip out the uploaded mask image property - this is an intermediate image // Strip out the uploaded mask image property - this is an intermediate image
@ -328,7 +328,7 @@ const recallRG: MetadataRecallFunc<RegionEntity> = async (rg) => {
}; };
//#region Control Layers //#region Control Layers
const recallLayer: MetadataRecallFunc<LayerEntity> = async (layer) => { const recallLayer: MetadataRecallFunc<CanvasLayerState> = async (layer) => {
const { dispatch } = getStore(); const { dispatch } = getStore();
const clone = deepClone(layer); const clone = deepClone(layer);
const invalidObjects: string[] = []; const invalidObjects: string[] = [];
@ -348,7 +348,7 @@ const recallLayer: MetadataRecallFunc<LayerEntity> = async (layer) => {
obj.id = getEraserLineId(clone.id, uuidv4()); obj.id = getEraserLineId(clone.id, uuidv4());
} else if (obj.type === 'image') { } else if (obj.type === 'image') {
obj.id = getImageObjectId(clone.id, uuidv4()); obj.id = getImageObjectId(clone.id, uuidv4());
} else if (obj.type === 'rect_shape') { } else if (obj.type === 'rect') {
obj.id = getRectShapeId(clone.id, uuidv4()); obj.id = getRectShapeId(clone.id, uuidv4());
} else { } else {
logger('metadata').error(`Unknown object type ${obj.type}`); logger('metadata').error(`Unknown object type ${obj.type}`);
@ -359,7 +359,7 @@ const recallLayer: MetadataRecallFunc<LayerEntity> = async (layer) => {
return; return;
}; };
const recallLayers: MetadataRecallFunc<LayerEntity[]> = (layers) => { const recallLayers: MetadataRecallFunc<CanvasLayerState[]> = (layers) => {
const { dispatch } = getStore(); const { dispatch } = getStore();
dispatch(layerAllDeleted()); dispatch(layerAllDeleted());
for (const l of layers) { for (const l of layers) {

View File

@ -1,5 +1,5 @@
import { getStore } from 'app/store/nanostores/store'; import { getStore } from 'app/store/nanostores/store';
import type { LayerEntity, LoRA } from 'features/controlLayers/store/types'; import type { CanvasLayerState, LoRA } from 'features/controlLayers/store/types';
import type { import type {
ControlNetConfigMetadata, ControlNetConfigMetadata,
IPAdapterConfigMetadata, IPAdapterConfigMetadata,
@ -109,7 +109,7 @@ const validateIPAdapters: MetadataValidateFunc<IPAdapterConfigMetadata[]> = (ipA
return new Promise((resolve) => resolve(validatedIPAdapters)); return new Promise((resolve) => resolve(validatedIPAdapters));
}; };
const validateLayer: MetadataValidateFunc<LayerEntity> = async (layer) => { const validateLayer: MetadataValidateFunc<CanvasLayerState> = async (layer) => {
if (layer.type === 'control_adapter_layer') { if (layer.type === 'control_adapter_layer') {
const model = layer.controlAdapter.model; const model = layer.controlAdapter.model;
assert(model, 'Control Adapter layer missing model'); assert(model, 'Control Adapter layer missing model');
@ -131,8 +131,8 @@ const validateLayer: MetadataValidateFunc<LayerEntity> = async (layer) => {
return layer; return layer;
}; };
const validateLayers: MetadataValidateFunc<LayerEntity[]> = async (layers) => { const validateLayers: MetadataValidateFunc<CanvasLayerState[]> = async (layers) => {
const validatedLayers: LayerEntity[] = []; const validatedLayers: CanvasLayerState[] = [];
for (const l of layers) { for (const l of layers) {
try { try {
const validated = await validateLayer(l); const validated = await validateLayer(l);

View File

@ -1,11 +1,11 @@
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { import type {
ControlAdapterEntity, CanvasControlAdapterState,
ControlNetData, CanvasControlNetState,
ImageWithDims, ImageWithDims,
ProcessorConfig, ProcessorConfig,
Rect, Rect,
T2IAdapterData, CanvasT2IAdapterState,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import type { ImageField } from 'features/nodes/types/common'; import type { ImageField } from 'features/nodes/types/common';
import { CONTROL_NET_COLLECT, T2I_ADAPTER_COLLECT } from 'features/nodes/util/graph/constants'; import { CONTROL_NET_COLLECT, T2I_ADAPTER_COLLECT } from 'features/nodes/util/graph/constants';
@ -15,12 +15,12 @@ import { assert } from 'tsafe';
export const addControlAdapters = async ( export const addControlAdapters = async (
manager: CanvasManager, manager: CanvasManager,
controlAdapters: ControlAdapterEntity[], controlAdapters: CanvasControlAdapterState[],
g: Graph, g: Graph,
bbox: Rect, bbox: Rect,
denoise: Invocation<'denoise_latents'>, denoise: Invocation<'denoise_latents'>,
base: BaseModelType base: BaseModelType
): Promise<ControlAdapterEntity[]> => { ): Promise<CanvasControlAdapterState[]> => {
const validControlAdapters = controlAdapters.filter((ca) => isValidControlAdapter(ca, base)); const validControlAdapters = controlAdapters.filter((ca) => isValidControlAdapter(ca, base));
for (const ca of validControlAdapters) { for (const ca of validControlAdapters) {
if (ca.adapterType === 'controlnet') { if (ca.adapterType === 'controlnet') {
@ -51,7 +51,7 @@ const addControlNetCollectorSafe = (g: Graph, denoise: Invocation<'denoise_laten
const addControlNetToGraph = async ( const addControlNetToGraph = async (
manager: CanvasManager, manager: CanvasManager,
ca: ControlNetData, ca: CanvasControlNetState,
g: Graph, g: Graph,
bbox: Rect, bbox: Rect,
denoise: Invocation<'denoise_latents'> denoise: Invocation<'denoise_latents'>
@ -96,7 +96,7 @@ const addT2IAdapterCollectorSafe = (g: Graph, denoise: Invocation<'denoise_laten
const addT2IAdapterToGraph = async ( const addT2IAdapterToGraph = async (
manager: CanvasManager, manager: CanvasManager,
ca: T2IAdapterData, ca: CanvasT2IAdapterState,
g: Graph, g: Graph,
bbox: Rect, bbox: Rect,
denoise: Invocation<'denoise_latents'> denoise: Invocation<'denoise_latents'>
@ -140,7 +140,7 @@ const buildControlImage = (
assert(false, 'Attempted to add unprocessed control image'); assert(false, 'Attempted to add unprocessed control image');
}; };
const isValidControlAdapter = (ca: ControlAdapterEntity, base: BaseModelType): boolean => { const isValidControlAdapter = (ca: CanvasControlAdapterState, base: BaseModelType): boolean => {
// Must be have a model that matches the current base and must have a control image // Must be have a model that matches the current base and must have a control image
const hasModel = Boolean(ca.model); const hasModel = Boolean(ca.model);
const modelMatchesBase = ca.model?.base === base; const modelMatchesBase = ca.model?.base === base;

View File

@ -1,15 +1,15 @@
import type { IPAdapterEntity } from 'features/controlLayers/store/types'; import type { CanvasIPAdapterState } from 'features/controlLayers/store/types';
import { IP_ADAPTER_COLLECT } from 'features/nodes/util/graph/constants'; import { IP_ADAPTER_COLLECT } from 'features/nodes/util/graph/constants';
import type { Graph } from 'features/nodes/util/graph/generation/Graph'; import type { Graph } from 'features/nodes/util/graph/generation/Graph';
import type { BaseModelType, Invocation } from 'services/api/types'; import type { BaseModelType, Invocation } from 'services/api/types';
import { assert } from 'tsafe'; import { assert } from 'tsafe';
export const addIPAdapters = ( export const addIPAdapters = (
ipAdapters: IPAdapterEntity[], ipAdapters: CanvasIPAdapterState[],
g: Graph, g: Graph,
denoise: Invocation<'denoise_latents'>, denoise: Invocation<'denoise_latents'>,
base: BaseModelType base: BaseModelType
): IPAdapterEntity[] => { ): CanvasIPAdapterState[] => {
const validIPAdapters = ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base)); const validIPAdapters = ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base));
for (const ipa of validIPAdapters) { for (const ipa of validIPAdapters) {
addIPAdapter(ipa, g, denoise); addIPAdapter(ipa, g, denoise);
@ -33,7 +33,7 @@ export const addIPAdapterCollectorSafe = (g: Graph, denoise: Invocation<'denoise
} }
}; };
const addIPAdapter = (ipa: IPAdapterEntity, g: Graph, denoise: Invocation<'denoise_latents'>) => { const addIPAdapter = (ipa: CanvasIPAdapterState, g: Graph, denoise: Invocation<'denoise_latents'>) => {
const { id, weight, model, clipVisionModel, method, beginEndStepPct, imageObject } = ipa; const { id, weight, model, clipVisionModel, method, beginEndStepPct, imageObject } = ipa;
assert(imageObject, 'IP Adapter image is required'); assert(imageObject, 'IP Adapter image is required');
assert(model, 'IP Adapter model is required'); assert(model, 'IP Adapter model is required');
@ -55,7 +55,7 @@ const addIPAdapter = (ipa: IPAdapterEntity, g: Graph, denoise: Invocation<'denoi
g.addEdge(ipAdapter, 'ip_adapter', ipAdapterCollect, 'item'); g.addEdge(ipAdapter, 'ip_adapter', ipAdapterCollect, 'item');
}; };
export const isValidIPAdapter = (ipa: IPAdapterEntity, base: BaseModelType): boolean => { export const isValidIPAdapter = (ipa: CanvasIPAdapterState, base: BaseModelType): boolean => {
// Must be have a model that matches the current base and must have a control image // Must be have a model that matches the current base and must have a control image
const hasModel = Boolean(ipa.model); const hasModel = Boolean(ipa.model);
const modelMatchesBase = ipa.model?.base === base; const modelMatchesBase = ipa.model?.base === base;

View File

@ -1,6 +1,6 @@
import type { LayerEntity } from 'features/controlLayers/store/types'; import type { CanvasLayerState } from 'features/controlLayers/store/types';
export const isValidLayer = (entity: LayerEntity) => { export const isValidLayer = (entity: CanvasLayerState) => {
return ( return (
entity.isEnabled && entity.isEnabled &&
// Boolean(entity.bbox) && TODO(psyche): Re-enable this check when we have a way to calculate bbox for all layers // Boolean(entity.bbox) && TODO(psyche): Re-enable this check when we have a way to calculate bbox for all layers

View File

@ -1,6 +1,6 @@
import { deepClone } from 'common/util/deepClone'; import { deepClone } from 'common/util/deepClone';
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import type { IPAdapterEntity, Rect, RegionEntity } from 'features/controlLayers/store/types'; import type { CanvasIPAdapterState, Rect, CanvasRegionalGuidanceState } from 'features/controlLayers/store/types';
import { import {
PROMPT_REGION_INVERT_TENSOR_MASK_PREFIX, PROMPT_REGION_INVERT_TENSOR_MASK_PREFIX,
PROMPT_REGION_MASK_TO_TENSOR_PREFIX, PROMPT_REGION_MASK_TO_TENSOR_PREFIX,
@ -28,7 +28,7 @@ import { assert } from 'tsafe';
export const addRegions = async ( export const addRegions = async (
manager: CanvasManager, manager: CanvasManager,
regions: RegionEntity[], regions: CanvasRegionalGuidanceState[],
g: Graph, g: Graph,
bbox: Rect, bbox: Rect,
base: BaseModelType, base: BaseModelType,
@ -37,7 +37,7 @@ export const addRegions = async (
negCond: Invocation<'compel'> | Invocation<'sdxl_compel_prompt'>, negCond: Invocation<'compel'> | Invocation<'sdxl_compel_prompt'>,
posCondCollect: Invocation<'collect'>, posCondCollect: Invocation<'collect'>,
negCondCollect: Invocation<'collect'> negCondCollect: Invocation<'collect'>
): Promise<RegionEntity[]> => { ): Promise<CanvasRegionalGuidanceState[]> => {
const isSDXL = base === 'sdxl'; const isSDXL = base === 'sdxl';
const validRegions = regions.filter((rg) => isValidRegion(rg, base)); const validRegions = regions.filter((rg) => isValidRegion(rg, base));
@ -173,7 +173,7 @@ export const addRegions = async (
} }
} }
const validRGIPAdapters: IPAdapterEntity[] = region.ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base)); const validRGIPAdapters: CanvasIPAdapterState[] = region.ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base));
for (const ipa of validRGIPAdapters) { for (const ipa of validRGIPAdapters) {
const ipAdapterCollect = addIPAdapterCollectorSafe(g, denoise); const ipAdapterCollect = addIPAdapterCollectorSafe(g, denoise);
@ -205,7 +205,7 @@ export const addRegions = async (
return validRegions; return validRegions;
}; };
export const isValidRegion = (rg: RegionEntity, base: BaseModelType) => { export const isValidRegion = (rg: CanvasRegionalGuidanceState, base: BaseModelType) => {
const hasTextPrompt = Boolean(rg.positivePrompt || rg.negativePrompt); const hasTextPrompt = Boolean(rg.positivePrompt || rg.negativePrompt);
const hasIPAdapter = rg.ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base)).length > 0; const hasIPAdapter = rg.ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base)).length > 0;
return hasTextPrompt || hasIPAdapter; return hasTextPrompt || hasIPAdapter;