| import type { AppDispatch, RootState } from 'app/store/store'; |
| import { deepClone } from 'common/util/deepClone'; |
| import { selectDefaultIPAdapter } from 'features/controlLayers/hooks/addLayerHooks'; |
| import { CanvasEntityAdapterBase } from 'features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterBase'; |
| import { getPrefixedId } from 'features/controlLayers/konva/util'; |
| import { canvasReset } from 'features/controlLayers/store/actions'; |
| import { |
| bboxChangedFromCanvas, |
| controlLayerAdded, |
| entityRasterized, |
| inpaintMaskAdded, |
| rasterLayerAdded, |
| referenceImageAdded, |
| referenceImageIPAdapterImageChanged, |
| rgAdded, |
| rgIPAdapterImageChanged, |
| } from 'features/controlLayers/store/canvasSlice'; |
| import { selectBboxModelBase, selectBboxRect } from 'features/controlLayers/store/selectors'; |
| import type { |
| CanvasControlLayerState, |
| CanvasEntityIdentifier, |
| CanvasEntityType, |
| CanvasInpaintMaskState, |
| CanvasRasterLayerState, |
| CanvasRegionalGuidanceState, |
| CanvasRenderableEntityIdentifier, |
| } from 'features/controlLayers/store/types'; |
| import { imageDTOToImageObject, imageDTOToImageWithDims, initialControlNet } from 'features/controlLayers/store/util'; |
| import { calculateNewSize } from 'features/controlLayers/util/getScaledBoundingBoxDimensions'; |
| import { imageToCompareChanged, selectionChanged } from 'features/gallery/store/gallerySlice'; |
| import type { BoardId } from 'features/gallery/store/types'; |
| import { fieldImageValueChanged } from 'features/nodes/store/nodesSlice'; |
| import type { FieldIdentifier } from 'features/nodes/types/field'; |
| import { upscaleInitialImageChanged } from 'features/parameters/store/upscaleSlice'; |
| import { getOptimalDimension } from 'features/parameters/util/optimalDimension'; |
| import { imagesApi } from 'services/api/endpoints/images'; |
| import type { ImageDTO } from 'services/api/types'; |
| import type { Equals } from 'tsafe'; |
| import { assert } from 'tsafe'; |
|
|
| export const setGlobalReferenceImage = (arg: { |
| imageDTO: ImageDTO; |
| entityIdentifier: CanvasEntityIdentifier<'reference_image'>; |
| dispatch: AppDispatch; |
| }) => { |
| const { imageDTO, entityIdentifier, dispatch } = arg; |
| dispatch(referenceImageIPAdapterImageChanged({ entityIdentifier, imageDTO })); |
| }; |
|
|
| export const setRegionalGuidanceReferenceImage = (arg: { |
| imageDTO: ImageDTO; |
| entityIdentifier: CanvasEntityIdentifier<'regional_guidance'>; |
| referenceImageId: string; |
| dispatch: AppDispatch; |
| }) => { |
| const { imageDTO, entityIdentifier, referenceImageId, dispatch } = arg; |
| dispatch(rgIPAdapterImageChanged({ entityIdentifier, referenceImageId, imageDTO })); |
| }; |
|
|
| export const setUpscaleInitialImage = (arg: { imageDTO: ImageDTO; dispatch: AppDispatch }) => { |
| const { imageDTO, dispatch } = arg; |
| dispatch(upscaleInitialImageChanged(imageDTO)); |
| }; |
|
|
| export const setNodeImageFieldImage = (arg: { |
| imageDTO: ImageDTO; |
| fieldIdentifer: FieldIdentifier; |
| dispatch: AppDispatch; |
| }) => { |
| const { imageDTO, fieldIdentifer, dispatch } = arg; |
| dispatch(fieldImageValueChanged({ ...fieldIdentifer, value: imageDTO })); |
| }; |
|
|
| export const setComparisonImage = (arg: { imageDTO: ImageDTO; dispatch: AppDispatch }) => { |
| const { imageDTO, dispatch } = arg; |
| dispatch(imageToCompareChanged(imageDTO)); |
| }; |
|
|
| export const createNewCanvasEntityFromImage = (arg: { |
| imageDTO: ImageDTO; |
| type: CanvasEntityType | 'regional_guidance_with_reference_image'; |
| dispatch: AppDispatch; |
| getState: () => RootState; |
| }) => { |
| const { type, imageDTO, dispatch, getState } = arg; |
| const state = getState(); |
| const imageObject = imageDTOToImageObject(imageDTO); |
| const { x, y } = selectBboxRect(state); |
| const overrides = { |
| objects: [imageObject], |
| position: { x, y }, |
| }; |
| switch (type) { |
| case 'raster_layer': { |
| dispatch(rasterLayerAdded({ overrides, isSelected: true })); |
| break; |
| } |
| case 'control_layer': { |
| dispatch( |
| controlLayerAdded({ |
| overrides: { ...overrides, controlAdapter: deepClone(initialControlNet) }, |
| isSelected: true, |
| }) |
| ); |
| break; |
| } |
| case 'inpaint_mask': { |
| dispatch(inpaintMaskAdded({ overrides, isSelected: true })); |
| break; |
| } |
| case 'regional_guidance': { |
| dispatch(rgAdded({ overrides, isSelected: true })); |
| break; |
| } |
| case 'reference_image': { |
| const ipAdapter = selectDefaultIPAdapter(getState()); |
| ipAdapter.image = imageDTOToImageWithDims(imageDTO); |
| dispatch(referenceImageAdded({ overrides: { ipAdapter }, isSelected: true })); |
| break; |
| } |
| case 'regional_guidance_with_reference_image': { |
| const ipAdapter = selectDefaultIPAdapter(getState()); |
| ipAdapter.image = imageDTOToImageWithDims(imageDTO); |
| const referenceImages = [{ id: getPrefixedId('regional_guidance_reference_image'), ipAdapter }]; |
| dispatch(rgAdded({ overrides: { referenceImages }, isSelected: true })); |
| break; |
| } |
| } |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export const newCanvasFromImage = (arg: { |
| imageDTO: ImageDTO; |
| type: CanvasEntityType | 'regional_guidance_with_reference_image'; |
| dispatch: AppDispatch; |
| getState: () => RootState; |
| }) => { |
| const { type, imageDTO, dispatch, getState } = arg; |
| const state = getState(); |
|
|
| const base = selectBboxModelBase(state); |
| |
| const ratio = imageDTO.width / imageDTO.height; |
| const optimalDimension = getOptimalDimension(base); |
| const { width, height } = calculateNewSize(ratio, optimalDimension ** 2, base); |
|
|
| const imageObject = imageDTOToImageObject(imageDTO); |
| const { x, y } = selectBboxRect(state); |
|
|
| const addInitCallback = (id: string) => { |
| CanvasEntityAdapterBase.registerInitCallback(async (adapter) => { |
| |
| if (adapter.id !== id) { |
| return false; |
| } |
| |
| await adapter.transformer.startTransform({ silent: true }); |
| adapter.transformer.fitToBboxFill(); |
| await adapter.transformer.applyTransform(); |
| return true; |
| }); |
| }; |
|
|
| switch (type) { |
| case 'raster_layer': { |
| const overrides = { |
| id: getPrefixedId('raster_layer'), |
| objects: [imageObject], |
| position: { x, y }, |
| } satisfies Partial<CanvasRasterLayerState>; |
| addInitCallback(overrides.id); |
| dispatch(canvasReset()); |
| |
| dispatch(bboxChangedFromCanvas({ x: 0, y: 0, width, height })); |
| dispatch(rasterLayerAdded({ overrides, isSelected: true })); |
| break; |
| } |
| case 'control_layer': { |
| const overrides = { |
| id: getPrefixedId('control_layer'), |
| objects: [imageObject], |
| position: { x, y }, |
| controlAdapter: deepClone(initialControlNet), |
| } satisfies Partial<CanvasControlLayerState>; |
| addInitCallback(overrides.id); |
| dispatch(canvasReset()); |
| |
| dispatch(bboxChangedFromCanvas({ x: 0, y: 0, width, height })); |
| dispatch(controlLayerAdded({ overrides, isSelected: true })); |
| break; |
| } |
| case 'inpaint_mask': { |
| const overrides = { |
| id: getPrefixedId('inpaint_mask'), |
| objects: [imageObject], |
| position: { x, y }, |
| } satisfies Partial<CanvasInpaintMaskState>; |
| addInitCallback(overrides.id); |
| dispatch(canvasReset()); |
| |
| dispatch(bboxChangedFromCanvas({ x: 0, y: 0, width, height })); |
| dispatch(inpaintMaskAdded({ overrides, isSelected: true })); |
| break; |
| } |
| case 'regional_guidance': { |
| const overrides = { |
| id: getPrefixedId('regional_guidance'), |
| objects: [imageObject], |
| position: { x, y }, |
| } satisfies Partial<CanvasRegionalGuidanceState>; |
| addInitCallback(overrides.id); |
| dispatch(canvasReset()); |
| |
| dispatch(bboxChangedFromCanvas({ x: 0, y: 0, width, height })); |
| dispatch(rgAdded({ overrides, isSelected: true })); |
| break; |
| } |
| case 'reference_image': { |
| const ipAdapter = selectDefaultIPAdapter(getState()); |
| ipAdapter.image = imageDTOToImageWithDims(imageDTO); |
| dispatch(canvasReset()); |
| dispatch(referenceImageAdded({ overrides: { ipAdapter }, isSelected: true })); |
| break; |
| } |
| case 'regional_guidance_with_reference_image': { |
| const ipAdapter = selectDefaultIPAdapter(getState()); |
| ipAdapter.image = imageDTOToImageWithDims(imageDTO); |
| const referenceImages = [{ id: getPrefixedId('regional_guidance_reference_image'), ipAdapter }]; |
| dispatch(canvasReset()); |
| dispatch(rgAdded({ overrides: { referenceImages }, isSelected: true })); |
| break; |
| } |
| default: |
| assert<Equals<typeof type, never>>(false); |
| } |
| }; |
|
|
| export const replaceCanvasEntityObjectsWithImage = (arg: { |
| imageDTO: ImageDTO; |
| entityIdentifier: CanvasRenderableEntityIdentifier; |
| dispatch: AppDispatch; |
| getState: () => RootState; |
| }) => { |
| const { imageDTO, entityIdentifier, dispatch, getState } = arg; |
| const imageObject = imageDTOToImageObject(imageDTO); |
| const { x, y } = selectBboxRect(getState()); |
| dispatch( |
| entityRasterized({ |
| entityIdentifier, |
| imageObject, |
| position: { x, y }, |
| replaceObjects: true, |
| isSelected: true, |
| }) |
| ); |
| }; |
|
|
| export const addImagesToBoard = (arg: { imageDTOs: ImageDTO[]; boardId: BoardId; dispatch: AppDispatch }) => { |
| const { imageDTOs, boardId, dispatch } = arg; |
| dispatch(imagesApi.endpoints.addImagesToBoard.initiate({ imageDTOs, board_id: boardId }, { track: false })); |
| dispatch(selectionChanged([])); |
| }; |
|
|
| export const removeImagesFromBoard = (arg: { imageDTOs: ImageDTO[]; dispatch: AppDispatch }) => { |
| const { imageDTOs, dispatch } = arg; |
| dispatch(imagesApi.endpoints.removeImagesFromBoard.initiate({ imageDTOs }, { track: false })); |
| dispatch(selectionChanged([])); |
| }; |
|
|