mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
refactor(ui): split up canvas entity renderers, temp disable preview
This commit is contained in:
parent
15ad4e3f5e
commit
007e2553a8
@ -5,7 +5,14 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { HeadsUpDisplay } from 'features/controlLayers/components/HeadsUpDisplay';
|
||||
import { setStageEventHandlers } from 'features/controlLayers/konva/events';
|
||||
import { renderBackgroundLayer } from 'features/controlLayers/konva/renderers/background';
|
||||
import { debouncedRenderers, renderers as normalRenderers } from 'features/controlLayers/konva/renderers/layers';
|
||||
import { renderControlAdapters } from 'features/controlLayers/konva/renderers/caLayer';
|
||||
import {
|
||||
arrangeEntities,
|
||||
debouncedRenderers,
|
||||
renderers as normalRenderers,
|
||||
} from 'features/controlLayers/konva/renderers/layers';
|
||||
import { renderLayers } from 'features/controlLayers/konva/renderers/rasterLayer';
|
||||
import { renderRegions } from 'features/controlLayers/konva/renderers/rgLayer';
|
||||
import {
|
||||
$bbox,
|
||||
$currentFill,
|
||||
@ -352,18 +359,22 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
|
||||
|
||||
useLayoutEffect(() => {
|
||||
log.trace('Rendering layers');
|
||||
renderers.renderLayers(
|
||||
stage,
|
||||
layers,
|
||||
controlAdapters,
|
||||
regions,
|
||||
maskOpacity,
|
||||
tool.selected,
|
||||
selectedEntity,
|
||||
getImageDTO,
|
||||
onPosChanged
|
||||
);
|
||||
}, [controlAdapters, layers, maskOpacity, onPosChanged, regions, renderers, selectedEntity, stage, tool.selected]);
|
||||
renderLayers(stage, layers, tool.selected, onPosChanged);
|
||||
}, [layers, onPosChanged, stage, tool.selected]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
log.trace('Rendering regions');
|
||||
renderRegions(stage, regions, maskOpacity, tool.selected, selectedEntity, onPosChanged);
|
||||
}, [maskOpacity, onPosChanged, regions, selectedEntity, stage, tool.selected]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
log.trace('Rendering layers');
|
||||
renderControlAdapters(stage, controlAdapters, getImageDTO);
|
||||
}, [controlAdapters, stage]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
arrangeEntities(stage, layers, controlAdapters, regions);
|
||||
}, [layers, controlAdapters, regions, stage]);
|
||||
|
||||
// useLayoutEffect(() => {
|
||||
// if (asPreview) {
|
||||
|
@ -43,6 +43,8 @@ export const RASTER_LAYER_IMAGE_NAME = 'raster_layer.image';
|
||||
|
||||
export const INPAINT_MASK_LAYER_NAME = 'inpaint_mask_layer';
|
||||
|
||||
export const BACKGROUND_LAYER_ID = 'background_layer';
|
||||
|
||||
// Getters for non-singleton layer and object IDs
|
||||
export const getRGId = (entityId: string) => `${RG_LAYER_NAME}_${entityId}`;
|
||||
export const getLayerId = (entityId: string) => `${RASTER_LAYER_NAME}_${entityId}`;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { getArbitraryBaseColor } from '@invoke-ai/ui-library';
|
||||
import { BACKGROUND_LAYER_ID } from 'features/controlLayers/konva/naming';
|
||||
import Konva from 'konva';
|
||||
|
||||
const baseGridLineColor = getArbitraryBaseColor(27);
|
||||
@ -23,13 +24,13 @@ const getGridSpacing = (scale: number): number => {
|
||||
return 256;
|
||||
};
|
||||
|
||||
const getBackgroundLayer = (stage: Konva.Stage): Konva.Layer => {
|
||||
let background = stage.findOne<Konva.Layer>('#background');
|
||||
export const getBackgroundLayer = (stage: Konva.Stage): Konva.Layer => {
|
||||
let background = stage.findOne<Konva.Layer>(`#${BACKGROUND_LAYER_ID}`);
|
||||
if (background) {
|
||||
return background;
|
||||
}
|
||||
|
||||
background = new Konva.Layer({ id: 'background' });
|
||||
background = new Konva.Layer({ id: BACKGROUND_LAYER_ID });
|
||||
stage.add(background);
|
||||
return background;
|
||||
};
|
||||
|
@ -92,10 +92,9 @@ const updateCALayerImageSource = async (
|
||||
|
||||
const updateCALayerImageAttrs = (stage: Konva.Stage, konvaImage: Konva.Image, ca: ControlAdapterData): void => {
|
||||
let needsCache = false;
|
||||
// Konva erroneously reports NaN for width and height when the stage is hidden. This causes errors when caching,
|
||||
// but it doesn't seem to break anything.
|
||||
// TODO(psyche): Investigate and report upstream.
|
||||
const filter = konvaImage.filters()[0] ?? null;
|
||||
// TODO(psyche): `node.filters()` returns null if no filters; report upstream
|
||||
const filters = konvaImage.filters() ?? [];
|
||||
const filter = filters[0] ?? null;
|
||||
const filterNeedsUpdate = (filter === null && ca.filter !== 'none') || (filter && filter.name !== ca.filter);
|
||||
if (
|
||||
konvaImage.x() !== ca.x ||
|
||||
@ -130,13 +129,9 @@ const updateCALayerImageAttrs = (stage: Konva.Stage, konvaImage: Konva.Image, ca
|
||||
export const renderCALayer = (
|
||||
stage: Konva.Stage,
|
||||
ca: ControlAdapterData,
|
||||
zIndex: number,
|
||||
getImageDTO: (imageName: string) => Promise<ImageDTO | null>
|
||||
): void => {
|
||||
const konvaLayer = stage.findOne<Konva.Layer>(`#${ca.id}`) ?? createCALayer(stage, ca);
|
||||
|
||||
konvaLayer.zIndex(zIndex);
|
||||
|
||||
const konvaImage = konvaLayer.findOne<Konva.Image>(`.${CA_LAYER_IMAGE_NAME}`);
|
||||
const canvasImageSource = konvaImage?.image();
|
||||
|
||||
@ -159,3 +154,19 @@ export const renderCALayer = (
|
||||
updateCALayerImageAttrs(stage, konvaImage, ca);
|
||||
}
|
||||
};
|
||||
|
||||
export const renderControlAdapters = (
|
||||
stage: Konva.Stage,
|
||||
controlAdapters: ControlAdapterData[],
|
||||
getImageDTO: (imageName: string) => Promise<ImageDTO | null>
|
||||
): void => {
|
||||
// Destroy nonexistent layers
|
||||
for (const konvaLayer of stage.find<Konva.Layer>(`.${CA_LAYER_NAME}`)) {
|
||||
if (!controlAdapters.find((ca) => ca.id === konvaLayer.id())) {
|
||||
konvaLayer.destroy();
|
||||
}
|
||||
}
|
||||
for (const ca of controlAdapters) {
|
||||
renderCALayer(stage, ca, getImageDTO);
|
||||
}
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { DEBOUNCE_MS } from 'features/controlLayers/konva/constants';
|
||||
import { PREVIEW_LAYER_ID } from 'features/controlLayers/konva/naming';
|
||||
import { BACKGROUND_LAYER_ID, PREVIEW_LAYER_ID } from 'features/controlLayers/konva/naming';
|
||||
import { updateBboxes } from 'features/controlLayers/konva/renderers/bbox';
|
||||
import { renderCALayer } from 'features/controlLayers/konva/renderers/caLayer';
|
||||
import { renderBboxPreview, renderToolPreview } from 'features/controlLayers/konva/renderers/previewLayer';
|
||||
@ -93,3 +93,23 @@ const getDebouncedRenderers = (ms = DEBOUNCE_MS): typeof renderers => ({
|
||||
* All the renderers for the Konva stage, debounced.
|
||||
*/
|
||||
export const debouncedRenderers: typeof renderers = getDebouncedRenderers();
|
||||
|
||||
export const arrangeEntities = (
|
||||
stage: Konva.Stage,
|
||||
layers: LayerData[],
|
||||
controlAdapters: ControlAdapterData[],
|
||||
regions: RegionalGuidanceData[]
|
||||
): void => {
|
||||
let zIndex = 0;
|
||||
stage.findOne<Konva.Layer>(`#${BACKGROUND_LAYER_ID}`)?.zIndex(++zIndex);
|
||||
for (const layer of layers) {
|
||||
stage.findOne<Konva.Layer>(`#${layer.id}`)?.zIndex(++zIndex);
|
||||
}
|
||||
for (const ca of controlAdapters) {
|
||||
stage.findOne<Konva.Layer>(`#${ca.id}`)?.zIndex(++zIndex);
|
||||
}
|
||||
for (const rg of regions) {
|
||||
stage.findOne<Konva.Layer>(`#${rg.id}`)?.zIndex(++zIndex);
|
||||
}
|
||||
stage.findOne<Konva.Layer>(`#${PREVIEW_LAYER_ID}`)?.zIndex(++zIndex);
|
||||
};
|
||||
|
@ -64,7 +64,6 @@ export const renderRasterLayer = async (
|
||||
stage: Konva.Stage,
|
||||
layerState: LayerData,
|
||||
tool: Tool,
|
||||
zIndex: number,
|
||||
onPosChanged?: (arg: PosChangedArg, entityType: CanvasEntity['type']) => void
|
||||
) => {
|
||||
const konvaLayer =
|
||||
@ -75,7 +74,6 @@ export const renderRasterLayer = async (
|
||||
listening: tool === 'move', // The layer only listens when using the move tool - otherwise the stage is handling mouse events
|
||||
x: Math.floor(layerState.x),
|
||||
y: Math.floor(layerState.y),
|
||||
zIndex,
|
||||
});
|
||||
|
||||
const konvaObjectGroup =
|
||||
@ -145,3 +143,20 @@ export const renderRasterLayer = async (
|
||||
|
||||
konvaObjectGroup.opacity(layerState.opacity);
|
||||
};
|
||||
|
||||
export const renderLayers = (
|
||||
stage: Konva.Stage,
|
||||
layers: LayerData[],
|
||||
tool: Tool,
|
||||
onPosChanged?: (arg: PosChangedArg, entityType: CanvasEntity['type']) => void
|
||||
): void => {
|
||||
// Destroy nonexistent layers
|
||||
for (const konvaLayer of stage.find<Konva.Layer>(`.${RASTER_LAYER_NAME}`)) {
|
||||
if (!layers.find((l) => l.id === konvaLayer.id())) {
|
||||
konvaLayer.destroy();
|
||||
}
|
||||
}
|
||||
for (const layer of layers) {
|
||||
renderRasterLayer(stage, layer, tool, onPosChanged);
|
||||
}
|
||||
};
|
||||
|
@ -83,7 +83,6 @@ export const renderRGLayer = (
|
||||
rg: RegionalGuidanceData,
|
||||
globalMaskLayerOpacity: number,
|
||||
tool: Tool,
|
||||
zIndex: number,
|
||||
selectedEntity: CanvasEntity | null,
|
||||
onPosChanged?: (arg: PosChangedArg, entityType: CanvasEntity['type']) => void
|
||||
): void => {
|
||||
@ -94,7 +93,6 @@ export const renderRGLayer = (
|
||||
listening: tool === 'move', // The layer only listens when using the move tool - otherwise the stage is handling mouse events
|
||||
x: Math.floor(rg.x),
|
||||
y: Math.floor(rg.y),
|
||||
zIndex,
|
||||
});
|
||||
|
||||
// Convert the color to a string, stripping the alpha - the object group will handle opacity.
|
||||
@ -233,3 +231,22 @@ export const renderRGLayer = (
|
||||
bboxRect.visible(false);
|
||||
}
|
||||
};
|
||||
|
||||
export const renderRegions = (
|
||||
stage: Konva.Stage,
|
||||
regions: RegionalGuidanceData[],
|
||||
maskOpacity: number,
|
||||
tool: Tool,
|
||||
selectedEntity: CanvasEntity | null,
|
||||
onPosChanged?: (arg: PosChangedArg, entityType: CanvasEntity['type']) => void
|
||||
): void => {
|
||||
// Destroy nonexistent layers
|
||||
for (const konvaLayer of stage.find<Konva.Layer>(`.${RG_LAYER_NAME}`)) {
|
||||
if (!regions.find((rg) => rg.id === konvaLayer.id())) {
|
||||
konvaLayer.destroy();
|
||||
}
|
||||
}
|
||||
for (const rg of regions) {
|
||||
renderRGLayer(stage, rg, maskOpacity, tool, selectedEntity, onPosChanged);
|
||||
}
|
||||
};
|
||||
|
@ -2,15 +2,14 @@ import { Flex } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { StageComponent } from 'features/controlLayers/components/StageComponent';
|
||||
import { $isPreviewVisible } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { AspectRatioIconPreview } from 'features/parameters/components/ImageSize/AspectRatioIconPreview';
|
||||
import { memo } from 'react';
|
||||
|
||||
export const AspectRatioCanvasPreview = memo(() => {
|
||||
const isPreviewVisible = useStore($isPreviewVisible);
|
||||
|
||||
if (!isPreviewVisible) {
|
||||
return <AspectRatioIconPreview />;
|
||||
}
|
||||
// if (!isPreviewVisible) {
|
||||
// return <AspectRatioIconPreview />;
|
||||
// }
|
||||
|
||||
return (
|
||||
<Flex w="full" h="full" alignItems="center" justifyContent="center" position="relative">
|
||||
|
Loading…
Reference in New Issue
Block a user