refactor(ui): use "entity" instead of "data" for canvas

This commit is contained in:
psychedelicious 2024-06-17 17:16:13 +10:00
parent 844590a571
commit e7df53e260
19 changed files with 112 additions and 112 deletions

View File

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

View File

@ -7,7 +7,7 @@ import {
} from 'features/controlLayers/konva/naming';
import { createBboxRect } from 'features/controlLayers/konva/renderers/objects';
import { imageDataToDataURL } from "features/controlLayers/konva/util";
import type { ControlAdapterData, LayerData, RegionalGuidanceData } from 'features/controlLayers/store/types';
import type { ControlAdapterEntity, LayerEntity, RegionEntity } from 'features/controlLayers/store/types';
import Konva from 'konva';
import type { IRect } from 'konva/lib/types';
import { assert } from 'tsafe';
@ -186,7 +186,7 @@ const filterCAChildren = (node: Konva.Node): boolean => node.name() === CA_LAYER
*/
export const updateBboxes = (
stage: Konva.Stage,
entityStates: (ControlAdapterData | LayerData | RegionalGuidanceData)[],
entityStates: (ControlAdapterEntity | LayerEntity | RegionEntity)[],
onBboxChanged: (layerId: string, bbox: IRect | null) => void
): void => {
for (const entityState of entityStates) {

View File

@ -1,6 +1,6 @@
import { LightnessToAlphaFilter } from 'features/controlLayers/konva/filters';
import { CA_LAYER_IMAGE_NAME, CA_LAYER_NAME, getCAImageId } from 'features/controlLayers/konva/naming';
import type { ControlAdapterData } from 'features/controlLayers/store/types';
import type { ControlAdapterEntity } from 'features/controlLayers/store/types';
import Konva from 'konva';
import type { ImageDTO } from 'services/api/types';
@ -14,7 +14,7 @@ import type { ImageDTO } from 'services/api/types';
* @param stage The konva stage
* @param ca The control adapter layer state
*/
const createCALayer = (stage: Konva.Stage, ca: ControlAdapterData): Konva.Layer => {
const createCALayer = (stage: Konva.Stage, ca: ControlAdapterEntity): Konva.Layer => {
const konvaLayer = new Konva.Layer({
id: ca.id,
name: CA_LAYER_NAME,
@ -50,7 +50,7 @@ const createCALayerImage = (konvaLayer: Konva.Layer, imageEl: HTMLImageElement):
const updateCALayerImageSource = async (
stage: Konva.Stage,
konvaLayer: Konva.Layer,
ca: ControlAdapterData,
ca: ControlAdapterEntity,
getImageDTO: (imageName: string) => Promise<ImageDTO | null>
): Promise<void> => {
const image = ca.processedImage ?? ca.image;
@ -90,7 +90,7 @@ const updateCALayerImageSource = async (
* @param ca The control adapter layer state
*/
const updateCALayerImageAttrs = (stage: Konva.Stage, konvaImage: Konva.Image, ca: ControlAdapterData): void => {
const updateCALayerImageAttrs = (stage: Konva.Stage, konvaImage: Konva.Image, ca: ControlAdapterEntity): void => {
let needsCache = false;
// TODO(psyche): `node.filters()` returns null if no filters; report upstream
const filters = konvaImage.filters() ?? [];
@ -128,7 +128,7 @@ const updateCALayerImageAttrs = (stage: Konva.Stage, konvaImage: Konva.Image, ca
*/
export const renderCALayer = (
stage: Konva.Stage,
ca: ControlAdapterData,
ca: ControlAdapterEntity,
getImageDTO: (imageName: string) => Promise<ImageDTO | null>
): void => {
const konvaLayer = stage.findOne<Konva.Layer>(`#${ca.id}`) ?? createCALayer(stage, ca);
@ -157,7 +157,7 @@ export const renderCALayer = (
export const renderControlAdapters = (
stage: Konva.Stage,
controlAdapters: ControlAdapterData[],
controlAdapters: ControlAdapterEntity[],
getImageDTO: (imageName: string) => Promise<ImageDTO | null>
): void => {
// Destroy nonexistent layers

View File

@ -8,10 +8,10 @@ import { renderRGLayer } from 'features/controlLayers/konva/renderers/rgLayer';
import { mapId, selectRenderableLayers } from 'features/controlLayers/konva/util';
import type {
CanvasEntity,
ControlAdapterData,
LayerData,
ControlAdapterEntity,
LayerEntity,
PosChangedArg,
RegionalGuidanceData,
RegionEntity,
Tool,
} from 'features/controlLayers/store/types';
import type Konva from 'konva';
@ -33,9 +33,9 @@ import type { ImageDTO } from 'services/api/types';
*/
const renderLayers = (
stage: Konva.Stage,
layers: LayerData[],
controlAdapters: ControlAdapterData[],
regions: RegionalGuidanceData[],
layers: LayerEntity[],
controlAdapters: ControlAdapterEntity[],
regions: RegionEntity[],
rgGlobalOpacity: number,
tool: Tool,
selectedEntity: CanvasEntity | null,
@ -96,9 +96,9 @@ export const debouncedRenderers: typeof renderers = getDebouncedRenderers();
export const arrangeEntities = (
stage: Konva.Stage,
layers: LayerData[],
controlAdapters: ControlAdapterData[],
regions: RegionalGuidanceData[]
layers: LayerEntity[],
controlAdapters: ControlAdapterEntity[],
regions: RegionEntity[]
): void => {
let zIndex = 0;
stage.findOne<Konva.Layer>(`#${BACKGROUND_LAYER_ID}`)?.zIndex(++zIndex);

View File

@ -14,7 +14,7 @@ import {
createRectShape,
} from 'features/controlLayers/konva/renderers/objects';
import { mapId, selectRasterObjects } from 'features/controlLayers/konva/util';
import type { CanvasEntity, LayerData, PosChangedArg, Tool } from 'features/controlLayers/store/types';
import type { CanvasEntity, LayerEntity, PosChangedArg, Tool } from 'features/controlLayers/store/types';
import Konva from 'konva';
/**
@ -29,7 +29,7 @@ import Konva from 'konva';
*/
const createRasterLayer = (
stage: Konva.Stage,
layerState: LayerData,
layerState: LayerEntity,
onPosChanged?: (arg: PosChangedArg, entityType: CanvasEntity['type']) => void
): Konva.Layer => {
// This layer hasn't been added to the konva state yet
@ -62,7 +62,7 @@ const createRasterLayer = (
*/
export const renderRasterLayer = async (
stage: Konva.Stage,
layerState: LayerData,
layerState: LayerEntity,
tool: Tool,
onPosChanged?: (arg: PosChangedArg, entityType: CanvasEntity['type']) => void
) => {
@ -146,7 +146,7 @@ export const renderRasterLayer = async (
export const renderLayers = (
stage: Konva.Stage,
layers: LayerData[],
layers: LayerEntity[],
tool: Tool,
onPosChanged?: (arg: PosChangedArg, entityType: CanvasEntity['type']) => void
): void => {

View File

@ -18,7 +18,7 @@ import {
createRectShape,
} from 'features/controlLayers/konva/renderers/objects';
import { mapId, selectVectorMaskObjects } from 'features/controlLayers/konva/util';
import type { CanvasEntity, PosChangedArg, RegionalGuidanceData, Tool } from 'features/controlLayers/store/types';
import type { CanvasEntity, PosChangedArg, RegionEntity, Tool } from 'features/controlLayers/store/types';
import Konva from 'konva';
/**
@ -46,7 +46,7 @@ const createCompositingRect = (konvaLayer: Konva.Layer): Konva.Rect => {
*/
const createRGLayer = (
stage: Konva.Stage,
rg: RegionalGuidanceData,
rg: RegionEntity,
onPosChanged?: (arg: PosChangedArg, entityType: CanvasEntity['type']) => void
): Konva.Layer => {
// This layer hasn't been added to the konva state yet
@ -80,7 +80,7 @@ const createRGLayer = (
*/
export const renderRGLayer = (
stage: Konva.Stage,
rg: RegionalGuidanceData,
rg: RegionEntity,
globalMaskLayerOpacity: number,
tool: Tool,
selectedEntity: CanvasEntity | null,
@ -234,7 +234,7 @@ export const renderRGLayer = (
export const renderRegions = (
stage: Konva.Stage,
regions: RegionalGuidanceData[],
regions: RegionEntity[],
maskOpacity: number,
tool: Tool,
selectedEntity: CanvasEntity | null,

View File

@ -9,7 +9,7 @@ import { v4 as uuidv4 } from 'uuid';
import type {
CanvasV2State,
ControlAdapterData,
ControlAdapterEntity,
ControlModeV2,
ControlNetConfig,
ControlNetData,
@ -50,7 +50,7 @@ export const controlAdaptersReducers = {
payload: { id: uuidv4(), ...payload },
}),
},
caRecalled: (state, action: PayloadAction<{ data: ControlAdapterData }>) => {
caRecalled: (state, action: PayloadAction<{ data: ControlAdapterEntity }>) => {
const { data } = action.payload;
state.controlAdapters.push(data);
state.selectedEntityIdentifier = { type: 'control_adapter', id: data.id };

View File

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

View File

@ -10,7 +10,7 @@ import type {
CanvasV2State,
EraserLineAddedArg,
ImageObjectAddedArg,
LayerData,
LayerEntity,
PointAddedToLineArg,
RectShapeAddedArg,
} from './types';
@ -42,7 +42,7 @@ export const layersReducers = {
},
prepare: () => ({ payload: { id: uuidv4() } }),
},
layerRecalled: (state, action: PayloadAction<{ data: LayerData }>) => {
layerRecalled: (state, action: PayloadAction<{ data: LayerEntity }>) => {
const { data } = action.payload;
state.layers.push(data);
state.selectedEntityIdentifier = { type: 'layer', id: data.id };

View File

@ -14,10 +14,10 @@ import { v4 as uuidv4 } from 'uuid';
import type {
BrushLineAddedArg,
EraserLineAddedArg,
IPAdapterData,
IPAdapterEntity,
PointAddedToLineArg,
RectShapeAddedArg,
RegionalGuidanceData,
RegionEntity,
RgbColor,
} from './types';
import { isLine } from './types';
@ -55,7 +55,7 @@ export const regionsReducers = {
rgAdded: {
reducer: (state, action: PayloadAction<{ id: string }>) => {
const { id } = action.payload;
const rg: RegionalGuidanceData = {
const rg: RegionEntity = {
id,
type: 'regional_guidance',
isEnabled: true,
@ -87,7 +87,7 @@ export const regionsReducers = {
rg.bboxNeedsUpdate = false;
rg.imageCache = null;
},
rgRecalled: (state, action: PayloadAction<{ data: RegionalGuidanceData }>) => {
rgRecalled: (state, action: PayloadAction<{ data: RegionEntity }>) => {
const { data } = action.payload;
state.regions.push(data);
state.selectedEntityIdentifier = { type: 'regional_guidance', id: data.id };
@ -194,7 +194,7 @@ export const regionsReducers = {
}
rg.autoNegative = autoNegative;
},
rgIPAdapterAdded: (state, action: PayloadAction<{ id: string; ipAdapter: IPAdapterData }>) => {
rgIPAdapterAdded: (state, action: PayloadAction<{ id: string; ipAdapter: IPAdapterEntity }>) => {
const { id, ipAdapter } = action.payload;
const rg = selectRG(state, id);
if (!rg) {

View File

@ -573,7 +573,7 @@ const zRect = z.object({
height: z.number().min(1),
});
export const zLayerData = z.object({
export const zLayerEntity = z.object({
id: zId,
type: z.literal('layer'),
isEnabled: z.boolean(),
@ -584,9 +584,9 @@ export const zLayerData = z.object({
opacity: zOpacity,
objects: z.array(zLayerObject),
});
export type LayerData = z.infer<typeof zLayerData>;
export type LayerEntity = z.infer<typeof zLayerEntity>;
export const zIPAdapterData = z.object({
export const zIPAdapterEntity = z.object({
id: zId,
type: z.literal('ip_adapter'),
isEnabled: z.boolean(),
@ -597,9 +597,9 @@ export const zIPAdapterData = z.object({
clipVisionModel: zCLIPVisionModelV2,
beginEndStepPct: zBeginEndStepPct,
});
export type IPAdapterData = z.infer<typeof zIPAdapterData>;
export type IPAdapterEntity = z.infer<typeof zIPAdapterEntity>;
export type IPAdapterConfig = Pick<
IPAdapterData,
IPAdapterEntity,
'weight' | 'image' | 'beginEndStepPct' | 'model' | 'clipVisionModel' | 'method'
>;
@ -636,7 +636,7 @@ const zMaskObject = z
})
.pipe(z.discriminatedUnion('type', [zBrushLine, zEraserline, zRectShape]));
export const zRegionalGuidanceData = z.object({
export const zRegionEntity = z.object({
id: zId,
type: z.literal('regional_guidance'),
isEnabled: z.boolean(),
@ -647,12 +647,12 @@ export const zRegionalGuidanceData = z.object({
objects: z.array(zMaskObject),
positivePrompt: zParameterPositivePrompt.nullable(),
negativePrompt: zParameterNegativePrompt.nullable(),
ipAdapters: z.array(zIPAdapterData),
ipAdapters: z.array(zIPAdapterEntity),
fill: zRgbColor,
autoNegative: zAutoNegative,
imageCache: zImageWithDims.nullable(),
});
export type RegionalGuidanceData = z.infer<typeof zRegionalGuidanceData>;
export type RegionEntity = z.infer<typeof zRegionEntity>;
const zColorFill = z.object({
type: z.literal('color_fill'),
@ -680,7 +680,7 @@ export type InpaintMaskData = z.infer<typeof zInpaintMaskData>;
const zFilter = z.enum(['none', 'LightnessToAlphaFilter']);
export type Filter = z.infer<typeof zFilter>;
const zControlAdapterDataBase = z.object({
const zControlAdapterEntityBase = z.object({
id: zId,
type: z.literal('control_adapter'),
isEnabled: z.boolean(),
@ -698,18 +698,18 @@ const zControlAdapterDataBase = z.object({
beginEndStepPct: zBeginEndStepPct,
model: zModelIdentifierField.nullable(),
});
const zControlNetData = zControlAdapterDataBase.extend({
const zControlNetEntity = zControlAdapterEntityBase.extend({
adapterType: z.literal('controlnet'),
controlMode: zControlModeV2,
});
export type ControlNetData = z.infer<typeof zControlNetData>;
const zT2IAdapterData = zControlAdapterDataBase.extend({
export type ControlNetData = z.infer<typeof zControlNetEntity>;
const zT2IAdapterEntity = zControlAdapterEntityBase.extend({
adapterType: z.literal('t2i_adapter'),
});
export type T2IAdapterData = z.infer<typeof zT2IAdapterData>;
export type T2IAdapterData = z.infer<typeof zT2IAdapterEntity>;
export const zControlAdapterData = z.discriminatedUnion('adapterType', [zControlNetData, zT2IAdapterData]);
export type ControlAdapterData = z.infer<typeof zControlAdapterData>;
export const zControlAdapterEntity = z.discriminatedUnion('adapterType', [zControlNetEntity, zT2IAdapterEntity]);
export type ControlAdapterEntity = z.infer<typeof zControlAdapterEntity>;
export type ControlNetConfig = Pick<
ControlNetData,
| 'adapterType'
@ -778,7 +778,7 @@ export type BoundingBoxScaleMethod = z.infer<typeof zBoundingBoxScaleMethod>;
export const isBoundingBoxScaleMethod = (v: unknown): v is BoundingBoxScaleMethod =>
zBoundingBoxScaleMethod.safeParse(v).success;
export type CanvasEntity = LayerData | IPAdapterData | ControlAdapterData | RegionalGuidanceData | InpaintMaskData;
export type CanvasEntity = LayerEntity | IPAdapterEntity | ControlAdapterEntity | RegionEntity | InpaintMaskData;
export type CanvasEntityIdentifier = Pick<CanvasEntity, 'id' | 'type'>;
export type Dimensions = {
@ -796,10 +796,10 @@ export type LoRA = {
export type CanvasV2State = {
_version: 3;
selectedEntityIdentifier: CanvasEntityIdentifier | null;
layers: LayerData[];
controlAdapters: ControlAdapterData[];
ipAdapters: IPAdapterData[];
regions: RegionalGuidanceData[];
layers: LayerEntity[];
controlAdapters: ControlAdapterEntity[];
ipAdapters: IPAdapterEntity[];
regions: RegionEntity[];
loras: LoRA[];
tool: {
selected: Tool;

View File

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

View File

@ -2,7 +2,7 @@ import { getStore } from 'app/store/nanostores/store';
import { deepClone } from 'common/util/deepClone';
import { objectKeys } from 'common/util/objectKeys';
import { shouldConcatPromptsChanged } from 'features/controlLayers/store/canvasV2Slice';
import type { LayerData, LoRA } from 'features/controlLayers/store/types';
import type { LayerEntity, LoRA } from 'features/controlLayers/store/types';
import type {
AnyControlAdapterConfigMetadata,
BuildMetadataHandlers,
@ -48,7 +48,7 @@ const renderControlAdapterValue: MetadataRenderValueFunc<AnyControlAdapterConfig
return `${value.model.key} (${value.model.base.toUpperCase()}) - ${value.weight}`;
}
};
const renderLayerValue: MetadataRenderValueFunc<LayerData> = async (layer) => {
const renderLayerValue: MetadataRenderValueFunc<LayerEntity> = async (layer) => {
if (layer.type === 'initial_image_layer') {
let rendered = t('controlLayers.globalInitialImageLayer');
if (layer.image) {
@ -88,7 +88,7 @@ const renderLayerValue: MetadataRenderValueFunc<LayerData> = async (layer) => {
}
assert(false, 'Unknown layer type');
};
const renderLayersValue: MetadataRenderValueFunc<LayerData[]> = async (layers) => {
const renderLayersValue: MetadataRenderValueFunc<LayerEntity[]> = async (layers) => {
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 { defaultLoRAConfig } from 'features/controlLayers/store/lorasReducers';
import type { ControlAdapterData, IPAdapterData, LayerData, LoRA } from 'features/controlLayers/store/types';
import type { ControlAdapterEntity, IPAdapterEntity, LayerEntity, LoRA } from 'features/controlLayers/store/types';
import {
CA_PROCESSOR_DATA,
imageDTOToImageWithDims,
@ -8,7 +8,7 @@ import {
initialIPAdapterV2,
initialT2IAdapterV2,
isProcessorTypeV2,
zLayerData,
zLayerEntity,
} from 'features/controlLayers/store/types';
import type {
ControlNetConfigMetadata,
@ -424,22 +424,22 @@ const parseAllIPAdapters: MetadataParseFunc<IPAdapterConfigMetadata[]> = async (
};
//#region Control Layers
const parseLayer: MetadataParseFunc<LayerData> = async (metadataItem) => zLayerData.parseAsync(metadataItem);
const parseLayer: MetadataParseFunc<LayerEntity> = async (metadataItem) => zLayerEntity.parseAsync(metadataItem);
const parseLayers: MetadataParseFunc<LayerData[]> = async (metadata) => {
const parseLayers: MetadataParseFunc<LayerEntity[]> = async (metadata) => {
// 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
// example, CL Control Adapters don't support resize mode, so we simply omit that property.
try {
const layers: LayerData[] = [];
const layers: LayerEntity[] = [];
try {
const control_layers = await getProperty(metadata, 'control_layers');
const controlLayersRaw = await getProperty(control_layers, 'layers', isArray);
const controlLayersParseResults = await Promise.allSettled(controlLayersRaw.map(parseLayer));
const controlLayers = controlLayersParseResults
.filter((result): result is PromiseFulfilledResult<LayerData> => result.status === 'fulfilled')
.filter((result): result is PromiseFulfilledResult<LayerEntity> => result.status === 'fulfilled')
.map((result) => result.value);
layers.push(...controlLayers);
} catch {
@ -452,7 +452,7 @@ const parseLayers: MetadataParseFunc<LayerData[]> = async (metadata) => {
controlNetsRaw.map(async (cn) => await parseControlNetToControlAdapterLayer(cn))
);
const controlNetsAsLayers = controlNetsParseResults
.filter((result): result is PromiseFulfilledResult<ControlAdapterData> => result.status === 'fulfilled')
.filter((result): result is PromiseFulfilledResult<ControlAdapterEntity> => result.status === 'fulfilled')
.map((result) => result.value);
layers.push(...controlNetsAsLayers);
} catch {
@ -465,7 +465,7 @@ const parseLayers: MetadataParseFunc<LayerData[]> = async (metadata) => {
t2iAdaptersRaw.map(async (cn) => await parseT2IAdapterToControlAdapterLayer(cn))
);
const t2iAdaptersAsLayers = t2iAdaptersParseResults
.filter((result): result is PromiseFulfilledResult<ControlAdapterData> => result.status === 'fulfilled')
.filter((result): result is PromiseFulfilledResult<ControlAdapterEntity> => result.status === 'fulfilled')
.map((result) => result.value);
layers.push(...t2iAdaptersAsLayers);
} catch {
@ -478,7 +478,7 @@ const parseLayers: MetadataParseFunc<LayerData[]> = async (metadata) => {
ipAdaptersRaw.map(async (cn) => await parseIPAdapterToIPAdapterLayer(cn))
);
const ipAdaptersAsLayers = ipAdaptersParseResults
.filter((result): result is PromiseFulfilledResult<IPAdapterData> => result.status === 'fulfilled')
.filter((result): result is PromiseFulfilledResult<IPAdapterEntity> => result.status === 'fulfilled')
.map((result) => result.value);
layers.push(...ipAdaptersAsLayers);
} catch {
@ -498,14 +498,14 @@ const parseLayers: MetadataParseFunc<LayerData[]> = async (metadata) => {
}
};
const parseInitialImageToInitialImageLayer: MetadataParseFunc<LayerData> = async (metadata) => {
const parseInitialImageToInitialImageLayer: MetadataParseFunc<LayerEntity> = async (metadata) => {
// TODO(psyche): recall denoise strength
// const denoisingStrength = await getProperty(metadata, 'strength', isParameterStrength);
const imageName = await getProperty(metadata, 'init_image', isString);
const imageDTO = await getImageDTO(imageName);
assert(imageDTO, 'ImageDTO is null');
const id = getLayerId(uuidv4());
const layer: LayerData = {
const layer: LayerEntity = {
id,
type: 'layer',
bbox: null,
@ -529,7 +529,7 @@ const parseInitialImageToInitialImageLayer: MetadataParseFunc<LayerData> = async
return layer;
};
const parseControlNetToControlAdapterLayer: MetadataParseFunc<ControlAdapterData> = async (metadataItem) => {
const parseControlNetToControlAdapterLayer: MetadataParseFunc<ControlAdapterEntity> = async (metadataItem) => {
const control_model = await getProperty(metadataItem, 'control_model');
const key = await getModelKey(control_model, 'controlnet');
const controlNetModel = await fetchModelConfigWithTypeGuard(key, isControlNetModelConfig);
@ -569,7 +569,7 @@ const parseControlNetToControlAdapterLayer: MetadataParseFunc<ControlAdapterData
const imageDTO = image ? await getImageDTO(image.image_name) : null;
const processedImageDTO = processedImage ? await getImageDTO(processedImage.image_name) : null;
const layer: ControlAdapterData = {
const layer: ControlAdapterEntity = {
id: getCAId(uuidv4()),
type: 'control_adapter',
bbox: null,
@ -593,7 +593,7 @@ const parseControlNetToControlAdapterLayer: MetadataParseFunc<ControlAdapterData
return layer;
};
const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc<ControlAdapterData> = async (metadataItem) => {
const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc<ControlAdapterEntity> = async (metadataItem) => {
const t2i_adapter_model = await getProperty(metadataItem, 't2i_adapter_model');
const key = await getModelKey(t2i_adapter_model, 't2i_adapter');
const t2iAdapterModel = await fetchModelConfigWithTypeGuard(key, isT2IAdapterModelConfig);
@ -630,7 +630,7 @@ const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc<ControlAdapterData
const imageDTO = image ? await getImageDTO(image.image_name) : null;
const processedImageDTO = processedImage ? await getImageDTO(processedImage.image_name) : null;
const layer: ControlAdapterData = {
const layer: ControlAdapterEntity = {
id: getCAId(uuidv4()),
bbox: null,
bboxNeedsUpdate: true,
@ -653,7 +653,7 @@ const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc<ControlAdapterData
return layer;
};
const parseIPAdapterToIPAdapterLayer: MetadataParseFunc<IPAdapterData> = async (metadataItem) => {
const parseIPAdapterToIPAdapterLayer: MetadataParseFunc<IPAdapterEntity> = async (metadataItem) => {
const ip_adapter_model = await getProperty(metadataItem, 'ip_adapter_model');
const key = await getModelKey(ip_adapter_model, 'ip_adapter');
const ipAdapterModel = await fetchModelConfigWithTypeGuard(key, isIPAdapterModelConfig);
@ -685,7 +685,7 @@ const parseIPAdapterToIPAdapterLayer: MetadataParseFunc<IPAdapterData> = async (
];
const imageDTO = image ? await getImageDTO(image.image_name) : null;
const layer: IPAdapterData = {
const layer: IPAdapterEntity = {
id: getIPAId(uuidv4()),
type: 'ip_adapter',
isEnabled: true,

View File

@ -40,11 +40,11 @@ import {
widthChanged,
} from 'features/controlLayers/store/canvasV2Slice';
import type {
ControlAdapterData,
IPAdapterData,
LayerData,
ControlAdapterEntity,
IPAdapterEntity,
LayerEntity,
LoRA,
RegionalGuidanceData,
RegionEntity,
} from 'features/controlLayers/store/types';
import { setHrfEnabled, setHrfMethod, setHrfStrength } from 'features/hrf/store/hrfSlice';
import type {
@ -246,7 +246,7 @@ const recallIPAdapters: MetadataRecallFunc<IPAdapterConfigMetadata[]> = (ipAdapt
});
};
const recallCA: MetadataRecallFunc<ControlAdapterData> = async (ca) => {
const recallCA: MetadataRecallFunc<ControlAdapterEntity> = async (ca) => {
const { dispatch } = getStore();
const clone = deepClone(ca);
if (clone.image) {
@ -275,7 +275,7 @@ const recallCA: MetadataRecallFunc<ControlAdapterData> = async (ca) => {
return;
};
const recallIPA: MetadataRecallFunc<IPAdapterData> = async (ipa) => {
const recallIPA: MetadataRecallFunc<IPAdapterEntity> = async (ipa) => {
const { dispatch } = getStore();
const clone = deepClone(ipa);
if (clone.image) {
@ -298,7 +298,7 @@ const recallIPA: MetadataRecallFunc<IPAdapterData> = async (ipa) => {
return;
};
const recallRG: MetadataRecallFunc<RegionalGuidanceData> = async (rg) => {
const recallRG: MetadataRecallFunc<RegionEntity> = async (rg) => {
const { dispatch } = getStore();
const clone = deepClone(rg);
// Strip out the uploaded mask image property - this is an intermediate image
@ -328,7 +328,7 @@ const recallRG: MetadataRecallFunc<RegionalGuidanceData> = async (rg) => {
};
//#region Control Layers
const recallLayer: MetadataRecallFunc<LayerData> = async (layer) => {
const recallLayer: MetadataRecallFunc<LayerEntity> = async (layer) => {
const { dispatch } = getStore();
const clone = deepClone(layer);
const invalidObjects: string[] = [];
@ -359,7 +359,7 @@ const recallLayer: MetadataRecallFunc<LayerData> = async (layer) => {
return;
};
const recallLayers: MetadataRecallFunc<LayerData[]> = (layers) => {
const recallLayers: MetadataRecallFunc<LayerEntity[]> = (layers) => {
const { dispatch } = getStore();
dispatch(layerAllDeleted());
for (const l of layers) {

View File

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

View File

@ -1,5 +1,5 @@
import type {
ControlAdapterData,
ControlAdapterEntity,
ControlNetData,
ImageWithDims,
ProcessorConfig,
@ -12,11 +12,11 @@ import type { BaseModelType, Invocation } from 'services/api/types';
import { assert } from 'tsafe';
export const addControlAdapters = (
controlAdapters: ControlAdapterData[],
controlAdapters: ControlAdapterEntity[],
g: Graph,
denoise: Invocation<'denoise_latents'>,
base: BaseModelType
): ControlAdapterData[] => {
): ControlAdapterEntity[] => {
const validControlAdapters = controlAdapters.filter((ca) => isValidControlAdapter(ca, base));
for (const ca of validControlAdapters) {
if (ca.adapterType === 'controlnet') {
@ -122,7 +122,7 @@ const buildControlImage = (
assert(false, 'Attempted to add unprocessed control image');
};
const isValidControlAdapter = (ca: ControlAdapterData, base: BaseModelType): boolean => {
const isValidControlAdapter = (ca: ControlAdapterEntity, base: BaseModelType): boolean => {
// Must be have a model that matches the current base and must have a control image
const hasModel = Boolean(ca.model);
const modelMatchesBase = ca.model?.base === base;

View File

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

View File

@ -5,7 +5,7 @@ import { RG_LAYER_NAME } from 'features/controlLayers/konva/naming';
import { renderers } from 'features/controlLayers/konva/renderers/layers';
import { blobToDataURL } from "features/controlLayers/konva/util";
import { rgMaskImageUploaded } from 'features/controlLayers/store/canvasV2Slice';
import type { Dimensions, IPAdapterData, RegionalGuidanceData } from 'features/controlLayers/store/types';
import type { Dimensions, IPAdapterEntity, RegionEntity } from 'features/controlLayers/store/types';
import {
PROMPT_REGION_INVERT_TENSOR_MASK_PREFIX,
PROMPT_REGION_MASK_TO_TENSOR_PREFIX,
@ -36,7 +36,7 @@ import { assert } from 'tsafe';
*/
export const addRegions = async (
regions: RegionalGuidanceData[],
regions: RegionEntity[],
g: Graph,
documentSize: Dimensions,
bbox: IRect,
@ -46,7 +46,7 @@ export const addRegions = async (
negCond: Invocation<'compel'> | Invocation<'sdxl_compel_prompt'>,
posCondCollect: Invocation<'collect'>,
negCondCollect: Invocation<'collect'>
): Promise<RegionalGuidanceData[]> => {
): Promise<RegionEntity[]> => {
const isSDXL = base === 'sdxl';
const validRegions = regions.filter((rg) => isValidRegion(rg, base));
@ -186,7 +186,7 @@ export const addRegions = async (
}
}
const validRGIPAdapters: IPAdapterData[] = rg.ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base));
const validRGIPAdapters: IPAdapterEntity[] = rg.ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base));
for (const ipa of validRGIPAdapters) {
const ipAdapterCollect = addIPAdapterCollectorSafe(g, denoise);
@ -218,13 +218,13 @@ export const addRegions = async (
return validRegions;
};
export const isValidRegion = (rg: RegionalGuidanceData, base: BaseModelType) => {
export const isValidRegion = (rg: RegionEntity, base: BaseModelType) => {
const hasTextPrompt = Boolean(rg.positivePrompt || rg.negativePrompt);
const hasIPAdapter = rg.ipAdapters.filter((ipa) => isValidIPAdapter(ipa, base)).length > 0;
return hasTextPrompt || hasIPAdapter;
};
export const getMaskImage = async (rg: RegionalGuidanceData, blob: Blob): Promise<ImageDTO> => {
export const getMaskImage = async (rg: RegionEntity, blob: Blob): Promise<ImageDTO> => {
const { id, imageCache } = rg;
if (imageCache) {
const imageDTO = await getImageDTO(imageCache.name);
@ -253,7 +253,7 @@ export const getMaskImage = async (rg: RegionalGuidanceData, blob: Blob): Promis
*/
export const getRGMaskBlobs = async (
regions: RegionalGuidanceData[],
regions: RegionEntity[],
documentSize: Dimensions,
bbox: IRect,
preview: boolean = false