Skip to content

Commit

Permalink
feat(ui): add ref image drop targets to canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
psychedelicious authored and hipsterusername committed Sep 16, 2024
1 parent 41efd81 commit 7fe1135
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { createAction } from '@reduxjs/toolkit';
import { logger } from 'app/logging/logger';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import { selectDefaultControlAdapter } from 'features/controlLayers/hooks/addLayerHooks';
import { deepClone } from 'common/util/deepClone';
import { selectDefaultControlAdapter, selectDefaultIPAdapter } from 'features/controlLayers/hooks/addLayerHooks';
import { getPrefixedId } from 'features/controlLayers/konva/util';
import {
controlLayerAdded,
entityRasterized,
entitySelected,
rasterLayerAdded,
referenceImageAdded,
referenceImageIPAdapterImageChanged,
rgAdded,
rgIPAdapterImageChanged,
} from 'features/controlLayers/store/canvasSlice';
import { selectCanvasSlice } from 'features/controlLayers/store/selectors';
import type { CanvasControlLayerState, CanvasRasterLayerState } from 'features/controlLayers/store/types';
import { imageDTOToImageObject } from 'features/controlLayers/store/util';
import type {
CanvasControlLayerState,
CanvasRasterLayerState,
CanvasReferenceImageState,
CanvasRegionalGuidanceState,
} from 'features/controlLayers/store/types';
import { imageDTOToImageObject, imageDTOToImageWithDims } from 'features/controlLayers/store/util';
import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types';
import { isValidDrop } from 'features/dnd/util/isValidDrop';
import { imageToCompareChanged, selectionChanged } from 'features/gallery/store/gallerySlice';
Expand Down Expand Up @@ -122,6 +131,36 @@ export const addImageDroppedListener = (startAppListening: AppStartListening) =>
return;
}

if (
overData.actionType === 'ADD_REGIONAL_REFERENCE_IMAGE_FROM_IMAGE' &&
activeData.payloadType === 'IMAGE_DTO' &&
activeData.payload.imageDTO
) {
const state = getState();
const ipAdapter = deepClone(selectDefaultIPAdapter(state));
ipAdapter.image = imageDTOToImageWithDims(activeData.payload.imageDTO);
const overrides: Partial<CanvasRegionalGuidanceState> = {
referenceImages: [{ id: getPrefixedId('regional_guidance_reference_image'), ipAdapter }],
};
dispatch(rgAdded({ overrides, isSelected: true }));
return;
}

if (
overData.actionType === 'ADD_GLOBAL_REFERENCE_IMAGE_FROM_IMAGE' &&
activeData.payloadType === 'IMAGE_DTO' &&
activeData.payload.imageDTO
) {
const state = getState();
const ipAdapter = deepClone(selectDefaultIPAdapter(state));
ipAdapter.image = imageDTOToImageWithDims(activeData.payload.imageDTO);
const overrides: Partial<CanvasReferenceImageState> = {
ipAdapter,
};
dispatch(referenceImageAdded({ overrides, isSelected: true }));
return;
}

/**
* Image dropped on Raster layer
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Flex } from '@invoke-ai/ui-library';
import { Grid, GridItem } from '@invoke-ai/ui-library';
import IAIDroppable from 'common/components/IAIDroppable';
import type { AddControlLayerFromImageDropData, AddRasterLayerFromImageDropData } from 'features/dnd/types';
import type {
AddControlLayerFromImageDropData,
AddGlobalReferenceImageFromImageDropData,
AddRasterLayerFromImageDropData,
AddRegionalReferenceImageFromImageDropData,
} from 'features/dnd/types';
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
import { memo } from 'react';

Expand All @@ -14,6 +19,16 @@ const addControlLayerFromImageDropData: AddControlLayerFromImageDropData = {
actionType: 'ADD_CONTROL_LAYER_FROM_IMAGE',
};

const addRegionalReferenceImageFromImageDropData: AddRegionalReferenceImageFromImageDropData = {
id: 'add-control-layer-from-image-drop-data',
actionType: 'ADD_REGIONAL_REFERENCE_IMAGE_FROM_IMAGE',
};

const addGlobalReferenceImageFromImageDropData: AddGlobalReferenceImageFromImageDropData = {
id: 'add-control-layer-from-image-drop-data',
actionType: 'ADD_GLOBAL_REFERENCE_IMAGE_FROM_IMAGE',
};

export const CanvasDropArea = memo(() => {
const imageViewer = useImageViewer();

Expand All @@ -23,12 +38,29 @@ export const CanvasDropArea = memo(() => {

return (
<>
<Flex position="absolute" top={0} right={0} bottom="50%" left={0} gap={2} pointerEvents="none">
<IAIDroppable dropLabel="Create Raster Layer" data={addRasterLayerFromImageDropData} />
</Flex>
<Flex position="absolute" top="50%" right={0} bottom={0} left={0} gap={2} pointerEvents="none">
<IAIDroppable dropLabel="Create Control Layer" data={addControlLayerFromImageDropData} />
</Flex>
<Grid
gridTemplateRows="1fr 1fr"
gridTemplateColumns="1fr 1fr"
position="absolute"
top={0}
right={0}
bottom={0}
left={0}
pointerEvents="none"
>
<GridItem position="relative">
<IAIDroppable dropLabel="New Raster Layer" data={addRasterLayerFromImageDropData} />
</GridItem>
<GridItem position="relative">
<IAIDroppable dropLabel="New Control Layer" data={addControlLayerFromImageDropData} />
</GridItem>
<GridItem position="relative">
<IAIDroppable dropLabel="New Regional Reference Image" data={addRegionalReferenceImageFromImageDropData} />
</GridItem>
<GridItem position="relative">
<IAIDroppable dropLabel="New Global Reference Image" data={addGlobalReferenceImageFromImageDropData} />
</GridItem>
</Grid>
</>
);
});
Expand Down
12 changes: 11 additions & 1 deletion invokeai/frontend/web/src/features/dnd/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export type AddControlLayerFromImageDropData = BaseDropData & {
actionType: 'ADD_CONTROL_LAYER_FROM_IMAGE';
};

export type AddRegionalReferenceImageFromImageDropData = BaseDropData & {
actionType: 'ADD_REGIONAL_REFERENCE_IMAGE_FROM_IMAGE';
};

export type AddGlobalReferenceImageFromImageDropData = BaseDropData & {
actionType: 'ADD_GLOBAL_REFERENCE_IMAGE_FROM_IMAGE';
};

export type ReplaceLayerImageDropData = BaseDropData & {
actionType: 'REPLACE_LAYER_WITH_IMAGE';
context: {
Expand Down Expand Up @@ -88,7 +96,9 @@ export type TypesafeDroppableData =
| UpscaleInitialImageDropData
| AddRasterLayerFromImageDropData
| AddControlLayerFromImageDropData
| ReplaceLayerImageDropData;
| ReplaceLayerImageDropData
| AddRegionalReferenceImageFromImageDropData
| AddGlobalReferenceImageFromImageDropData;

type BaseDragData = {
id: string;
Expand Down
2 changes: 2 additions & 0 deletions invokeai/frontend/web/src/features/dnd/util/isValidDrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export const isValidDrop = (overData?: TypesafeDroppableData | null, activeData?
case 'SET_NODES_IMAGE':
case 'SELECT_FOR_COMPARE':
case 'REPLACE_LAYER_WITH_IMAGE':
case 'ADD_GLOBAL_REFERENCE_IMAGE_FROM_IMAGE':
case 'ADD_REGIONAL_REFERENCE_IMAGE_FROM_IMAGE':
return payloadType === 'IMAGE_DTO';
case 'ADD_TO_BOARD': {
// If the board is the same, don't allow the drop
Expand Down

0 comments on commit 7fe1135

Please sign in to comment.