From e7523bd1d99b7f003e3945cf247f65cae82e8bbd Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 12 Apr 2024 16:28:00 +1000 Subject: [PATCH] fix(ui): fix layer debug --- .../components/LayerColorPicker.tsx | 2 +- .../components/LayerComponent.tsx | 19 +++++--- .../components/RegionalPromptsEditor.tsx | 8 +++- .../store/regionalPromptsSlice.ts | 2 + .../regionalPrompts/util/getLayerBlobs.ts | 43 +++++++++++++++---- 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/LayerColorPicker.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/LayerColorPicker.tsx index c0c221c099..a3bbcdb875 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/components/LayerColorPicker.tsx +++ b/invokeai/frontend/web/src/features/regionalPrompts/components/LayerColorPicker.tsx @@ -26,7 +26,7 @@ export const LayerColorPicker = ({ id }: Props) => { - + diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/LayerComponent.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/LayerComponent.tsx index 030df4943f..4a21abcbfe 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/components/LayerComponent.tsx +++ b/invokeai/frontend/web/src/features/regionalPrompts/components/LayerComponent.tsx @@ -5,7 +5,13 @@ import { LayerBoundingBox } from 'features/regionalPrompts/components/LayerBound import { LineComponent } from 'features/regionalPrompts/components/LineComponent'; import { RectComponent } from 'features/regionalPrompts/components/RectComponent'; import { useLayer } from 'features/regionalPrompts/hooks/layerStateHooks'; -import { $stage, layerBboxChanged, layerTranslated } from 'features/regionalPrompts/store/regionalPromptsSlice'; +import { + $stage, + layerBboxChanged, + layerTranslated, + REGIONAL_PROMPT_LAYER_NAME, + REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME, +} from 'features/regionalPrompts/store/regionalPromptsSlice'; import { getKonvaLayerBbox } from 'features/regionalPrompts/util/bbox'; import type { Group as KonvaGroupType } from 'konva/lib/Group'; import type { Layer as KonvaLayerType } from 'konva/lib/Layer'; @@ -19,7 +25,8 @@ type Props = { id: string; }; -const filterChildren = (item: KonvaNodeType) => item.name() !== 'regionalPromptLayerObjectGroup'; +export const selectPromptLayerObjectGroup = (item: KonvaNodeType) => + item.name() !== REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME; export const LayerComponent: React.FC = ({ id }) => { const dispatch = useAppDispatch(); @@ -74,7 +81,7 @@ export const LayerComponent: React.FC = ({ id }) => { onChangeBbox(null); return; } - onChangeBbox(getKonvaLayerBbox(layerRef.current, filterChildren)); + onChangeBbox(getKonvaLayerBbox(layerRef.current, selectPromptLayerObjectGroup)); }, [tool, layer.objects, onChangeBbox]); if (!layer.isVisible) { @@ -85,8 +92,8 @@ export const LayerComponent: React.FC = ({ id }) => { <> = ({ id }) => { > diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx index b39ab6587b..e161a4780f 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx +++ b/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx @@ -8,19 +8,23 @@ import { LayerListItem } from 'features/regionalPrompts/components/LayerListItem import { RegionalPromptsStage } from 'features/regionalPrompts/components/RegionalPromptsStage'; import { ToolChooser } from 'features/regionalPrompts/components/ToolChooser'; import { selectRegionalPromptsSlice } from 'features/regionalPrompts/store/regionalPromptsSlice'; -import { getLayerBlobs } from 'features/regionalPrompts/util/getLayerBlobs'; +import { getRegionalPromptLayerBlobs } from 'features/regionalPrompts/util/getLayerBlobs'; import { ImageSizeLinear } from 'features/settingsAccordions/components/ImageSettingsAccordion/ImageSizeLinear'; const selectLayerIdsReversed = createSelector(selectRegionalPromptsSlice, (regionalPrompts) => regionalPrompts.layers.map((l) => l.id).reverse() ); +const debugBlobs = () => { + getRegionalPromptLayerBlobs(true); +}; + export const RegionalPromptsEditor = () => { const layerIdsReversed = useAppSelector(selectLayerIdsReversed); return ( - + diff --git a/invokeai/frontend/web/src/features/regionalPrompts/store/regionalPromptsSlice.ts b/invokeai/frontend/web/src/features/regionalPrompts/store/regionalPromptsSlice.ts index faafffa936..a3b1025a12 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/store/regionalPromptsSlice.ts +++ b/invokeai/frontend/web/src/features/regionalPrompts/store/regionalPromptsSlice.ts @@ -270,3 +270,5 @@ export const getStage = (): Konva.Stage => { assert(stage); return stage; }; +export const REGIONAL_PROMPT_LAYER_NAME = 'regionalPromptLayer'; +export const REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME = 'regionalPromptLayerObjectGroup'; diff --git a/invokeai/frontend/web/src/features/regionalPrompts/util/getLayerBlobs.ts b/invokeai/frontend/web/src/features/regionalPrompts/util/getLayerBlobs.ts index a491de6a59..c7e9f324dc 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/util/getLayerBlobs.ts +++ b/invokeai/frontend/web/src/features/regionalPrompts/util/getLayerBlobs.ts @@ -1,26 +1,51 @@ import { getStore } from 'app/store/nanostores/store'; import openBase64ImageInTab from 'common/util/openBase64ImageInTab'; import { blobToDataURL } from 'features/canvas/util/blobToDataURL'; -import { $stage } from 'features/regionalPrompts/store/regionalPromptsSlice'; +import { selectPromptLayerObjectGroup } from 'features/regionalPrompts/components/LayerComponent'; +import { $stage, REGIONAL_PROMPT_LAYER_NAME } from 'features/regionalPrompts/store/regionalPromptsSlice'; +import Konva from 'konva'; import { assert } from 'tsafe'; -export const getLayerBlobs = async () => { +export const getRegionalPromptLayerBlobs = async (preview: boolean = false): Promise> => { const state = getStore().getState(); const stage = $stage.get(); assert(stage !== null, 'Stage is null'); - const stageLayers = stage.getLayers().filter((l) => l.name() === 'regionalPromptLayer'); - for (const layer of stageLayers) { + const regionalPromptLayers = stage.getLayers().filter((l) => l.name() === REGIONAL_PROMPT_LAYER_NAME); + + // We need to reconstruct each layer to only output the desired data. This logic mirrors the logic in + // `getKonvaLayerBbox()` in `invokeai/frontend/web/src/features/regionalPrompts/util/bbox.ts` + const offscreenStageContainer = document.createElement('div'); + const offscreenStage = new Konva.Stage({ + container: offscreenStageContainer, + width: stage.width(), + height: stage.height(), + }); + + const blobs: Record = {}; + + for (const layer of regionalPromptLayers) { + const layerClone = layer.clone(); + for (const child of layerClone.getChildren(selectPromptLayerObjectGroup)) { + child.destroy(); + } + offscreenStage.add(layerClone); const blob = await new Promise((resolve) => { - layer.toBlob({ + offscreenStage.toBlob({ callback: (blob) => { assert(blob, 'Blob is null'); resolve(blob); }, }); }); - const base64 = await blobToDataURL(blob); - const prompt = state.regionalPrompts.layers.find((l) => l.id === layer.id())?.prompt; - assert(prompt !== undefined, 'Prompt is undefined'); - openBase64ImageInTab([{ base64, caption: prompt }]); + blobs[layer.id()] = blob; + + if (preview) { + const base64 = await blobToDataURL(blob); + const prompt = state.regionalPrompts.layers.find((l) => l.id === layer.id())?.prompt; + openBase64ImageInTab([{ base64, caption: prompt ?? '' }]); + } + layerClone.destroy(); } + + return blobs; };