mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): fix layer debug
This commit is contained in:
parent
8911017bd1
commit
e7523bd1d9
@ -26,7 +26,7 @@ export const LayerColorPicker = ({ id }: Props) => {
|
|||||||
<ColorPreview previewColor={layer.color} />
|
<ColorPreview previewColor={layer.color} />
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent>
|
||||||
<PopoverBody w={64} h={64}>
|
<PopoverBody minH={64}>
|
||||||
<RgbColorPicker color={layer.color} onChange={onColorChange} withNumberInput />
|
<RgbColorPicker color={layer.color} onChange={onColorChange} withNumberInput />
|
||||||
</PopoverBody>
|
</PopoverBody>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
|
@ -5,7 +5,13 @@ import { LayerBoundingBox } from 'features/regionalPrompts/components/LayerBound
|
|||||||
import { LineComponent } from 'features/regionalPrompts/components/LineComponent';
|
import { LineComponent } from 'features/regionalPrompts/components/LineComponent';
|
||||||
import { RectComponent } from 'features/regionalPrompts/components/RectComponent';
|
import { RectComponent } from 'features/regionalPrompts/components/RectComponent';
|
||||||
import { useLayer } from 'features/regionalPrompts/hooks/layerStateHooks';
|
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 { getKonvaLayerBbox } from 'features/regionalPrompts/util/bbox';
|
||||||
import type { Group as KonvaGroupType } from 'konva/lib/Group';
|
import type { Group as KonvaGroupType } from 'konva/lib/Group';
|
||||||
import type { Layer as KonvaLayerType } from 'konva/lib/Layer';
|
import type { Layer as KonvaLayerType } from 'konva/lib/Layer';
|
||||||
@ -19,7 +25,8 @@ type Props = {
|
|||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const filterChildren = (item: KonvaNodeType<KonvaNodeConfigType>) => item.name() !== 'regionalPromptLayerObjectGroup';
|
export const selectPromptLayerObjectGroup = (item: KonvaNodeType<KonvaNodeConfigType>) =>
|
||||||
|
item.name() !== REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME;
|
||||||
|
|
||||||
export const LayerComponent: React.FC<Props> = ({ id }) => {
|
export const LayerComponent: React.FC<Props> = ({ id }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -74,7 +81,7 @@ export const LayerComponent: React.FC<Props> = ({ id }) => {
|
|||||||
onChangeBbox(null);
|
onChangeBbox(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onChangeBbox(getKonvaLayerBbox(layerRef.current, filterChildren));
|
onChangeBbox(getKonvaLayerBbox(layerRef.current, selectPromptLayerObjectGroup));
|
||||||
}, [tool, layer.objects, onChangeBbox]);
|
}, [tool, layer.objects, onChangeBbox]);
|
||||||
|
|
||||||
if (!layer.isVisible) {
|
if (!layer.isVisible) {
|
||||||
@ -85,8 +92,8 @@ export const LayerComponent: React.FC<Props> = ({ id }) => {
|
|||||||
<>
|
<>
|
||||||
<KonvaLayer
|
<KonvaLayer
|
||||||
ref={layerRef}
|
ref={layerRef}
|
||||||
id={`layer-${layer.id}`}
|
id={layer.id}
|
||||||
name="regionalPromptLayer"
|
name={REGIONAL_PROMPT_LAYER_NAME}
|
||||||
onDragEnd={onDragEnd}
|
onDragEnd={onDragEnd}
|
||||||
onDragMove={onDragMove}
|
onDragMove={onDragMove}
|
||||||
dragBoundFunc={dragBoundFunc}
|
dragBoundFunc={dragBoundFunc}
|
||||||
@ -94,7 +101,7 @@ export const LayerComponent: React.FC<Props> = ({ id }) => {
|
|||||||
>
|
>
|
||||||
<KonvaGroup
|
<KonvaGroup
|
||||||
id={`layer-${layer.id}-group`}
|
id={`layer-${layer.id}-group`}
|
||||||
name="regionalPromptLayerObjectGroup"
|
name={REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME}
|
||||||
ref={groupRef}
|
ref={groupRef}
|
||||||
listening={false}
|
listening={false}
|
||||||
>
|
>
|
||||||
|
@ -8,19 +8,23 @@ import { LayerListItem } from 'features/regionalPrompts/components/LayerListItem
|
|||||||
import { RegionalPromptsStage } from 'features/regionalPrompts/components/RegionalPromptsStage';
|
import { RegionalPromptsStage } from 'features/regionalPrompts/components/RegionalPromptsStage';
|
||||||
import { ToolChooser } from 'features/regionalPrompts/components/ToolChooser';
|
import { ToolChooser } from 'features/regionalPrompts/components/ToolChooser';
|
||||||
import { selectRegionalPromptsSlice } from 'features/regionalPrompts/store/regionalPromptsSlice';
|
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';
|
import { ImageSizeLinear } from 'features/settingsAccordions/components/ImageSettingsAccordion/ImageSizeLinear';
|
||||||
|
|
||||||
const selectLayerIdsReversed = createSelector(selectRegionalPromptsSlice, (regionalPrompts) =>
|
const selectLayerIdsReversed = createSelector(selectRegionalPromptsSlice, (regionalPrompts) =>
|
||||||
regionalPrompts.layers.map((l) => l.id).reverse()
|
regionalPrompts.layers.map((l) => l.id).reverse()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const debugBlobs = () => {
|
||||||
|
getRegionalPromptLayerBlobs(true);
|
||||||
|
};
|
||||||
|
|
||||||
export const RegionalPromptsEditor = () => {
|
export const RegionalPromptsEditor = () => {
|
||||||
const layerIdsReversed = useAppSelector(selectLayerIdsReversed);
|
const layerIdsReversed = useAppSelector(selectLayerIdsReversed);
|
||||||
return (
|
return (
|
||||||
<Flex gap={4}>
|
<Flex gap={4}>
|
||||||
<Flex flexDir="column" gap={4} flexShrink={0}>
|
<Flex flexDir="column" gap={4} flexShrink={0}>
|
||||||
<Button onClick={getLayerBlobs}>DEBUG LAYERS</Button>
|
<Button onClick={debugBlobs}>DEBUG LAYERS</Button>
|
||||||
<AddLayerButton />
|
<AddLayerButton />
|
||||||
<BrushSize />
|
<BrushSize />
|
||||||
<ImageSizeLinear />
|
<ImageSizeLinear />
|
||||||
|
@ -270,3 +270,5 @@ export const getStage = (): Konva.Stage => {
|
|||||||
assert(stage);
|
assert(stage);
|
||||||
return stage;
|
return stage;
|
||||||
};
|
};
|
||||||
|
export const REGIONAL_PROMPT_LAYER_NAME = 'regionalPromptLayer';
|
||||||
|
export const REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME = 'regionalPromptLayerObjectGroup';
|
||||||
|
@ -1,26 +1,51 @@
|
|||||||
import { getStore } from 'app/store/nanostores/store';
|
import { getStore } from 'app/store/nanostores/store';
|
||||||
import openBase64ImageInTab from 'common/util/openBase64ImageInTab';
|
import openBase64ImageInTab from 'common/util/openBase64ImageInTab';
|
||||||
import { blobToDataURL } from 'features/canvas/util/blobToDataURL';
|
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';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
export const getLayerBlobs = async () => {
|
export const getRegionalPromptLayerBlobs = async (preview: boolean = false): Promise<Record<string, Blob>> => {
|
||||||
const state = getStore().getState();
|
const state = getStore().getState();
|
||||||
const stage = $stage.get();
|
const stage = $stage.get();
|
||||||
assert(stage !== null, 'Stage is null');
|
assert(stage !== null, 'Stage is null');
|
||||||
const stageLayers = stage.getLayers().filter((l) => l.name() === 'regionalPromptLayer');
|
const regionalPromptLayers = stage.getLayers().filter((l) => l.name() === REGIONAL_PROMPT_LAYER_NAME);
|
||||||
for (const layer of stageLayers) {
|
|
||||||
|
// 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<string, Blob> = {};
|
||||||
|
|
||||||
|
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<Blob>((resolve) => {
|
const blob = await new Promise<Blob>((resolve) => {
|
||||||
layer.toBlob({
|
offscreenStage.toBlob({
|
||||||
callback: (blob) => {
|
callback: (blob) => {
|
||||||
assert(blob, 'Blob is null');
|
assert(blob, 'Blob is null');
|
||||||
resolve(blob);
|
resolve(blob);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
blobs[layer.id()] = blob;
|
||||||
|
|
||||||
|
if (preview) {
|
||||||
const base64 = await blobToDataURL(blob);
|
const base64 = await blobToDataURL(blob);
|
||||||
const prompt = state.regionalPrompts.layers.find((l) => l.id === layer.id())?.prompt;
|
const prompt = state.regionalPrompts.layers.find((l) => l.id === layer.id())?.prompt;
|
||||||
assert(prompt !== undefined, 'Prompt is undefined');
|
openBase64ImageInTab([{ base64, caption: prompt ?? '' }]);
|
||||||
openBase64ImageInTab([{ base64, caption: prompt }]);
|
|
||||||
}
|
}
|
||||||
|
layerClone.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return blobs;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user