mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): staging area barely works
This commit is contained in:
parent
9807a896f4
commit
7824cb7a1a
@ -1,7 +1,7 @@
|
|||||||
import { enqueueRequested } from 'app/store/actions';
|
import { enqueueRequested } from 'app/store/actions';
|
||||||
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
||||||
import { getNodeManager } from 'features/controlLayers/konva/nodeManager';
|
import { getNodeManager } from 'features/controlLayers/konva/nodeManager';
|
||||||
import { stagingAreaInitialized } from 'features/controlLayers/store/canvasV2Slice';
|
import { stagingAreaBatchIdAdded, stagingAreaInitialized } from 'features/controlLayers/store/canvasV2Slice';
|
||||||
import { isImageViewerOpenChanged } from 'features/gallery/store/gallerySlice';
|
import { isImageViewerOpenChanged } from 'features/gallery/store/gallerySlice';
|
||||||
import { prepareLinearUIBatch } from 'features/nodes/util/graph/buildLinearBatchConfig';
|
import { prepareLinearUIBatch } from 'features/nodes/util/graph/buildLinearBatchConfig';
|
||||||
import { buildSD1Graph } from 'features/nodes/util/graph/generation/buildSD1Graph';
|
import { buildSD1Graph } from 'features/nodes/util/graph/generation/buildSD1Graph';
|
||||||
@ -48,12 +48,16 @@ export const addEnqueueRequestedLinear = (startAppListening: AppStartListening)
|
|||||||
// TODO(psyche): update the backend schema, this is always provided
|
// TODO(psyche): update the backend schema, this is always provided
|
||||||
const batchId = enqueueResult.batch.batch_id;
|
const batchId = enqueueResult.batch.batch_id;
|
||||||
assert(batchId, 'No batch ID found in enqueue result');
|
assert(batchId, 'No batch ID found in enqueue result');
|
||||||
dispatch(
|
if (!state.canvasV2.stagingArea) {
|
||||||
stagingAreaInitialized({
|
dispatch(
|
||||||
batchIds: [batchId],
|
stagingAreaInitialized({
|
||||||
bbox: getState().canvasV2.bbox,
|
batchIds: [batchId],
|
||||||
})
|
bbox: state.canvasV2.bbox,
|
||||||
);
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dispatch(stagingAreaBatchIdAdded({ batchId }));
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
req.reset();
|
req.reset();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
import { getImageDataTransparency } from 'common/util/arrayBuffer';
|
import { getImageDataTransparency } from 'common/util/arrayBuffer';
|
||||||
import { CanvasBackground } from 'features/controlLayers/konva/renderers/background';
|
import { CanvasBackground } from 'features/controlLayers/konva/renderers/background';
|
||||||
import { CanvasPreview } from 'features/controlLayers/konva/renderers/preview';
|
import {
|
||||||
|
CanvasBbox,
|
||||||
|
CanvasDocumentSizeOverlay,
|
||||||
|
CanvasPreview,
|
||||||
|
CanvasStagingArea,
|
||||||
|
CanvasTool,
|
||||||
|
} from 'features/controlLayers/konva/renderers/preview';
|
||||||
import { konvaNodeToBlob, konvaNodeToImageData, previewBlob } from 'features/controlLayers/konva/util';
|
import { konvaNodeToBlob, konvaNodeToImageData, previewBlob } from 'features/controlLayers/konva/util';
|
||||||
import type {
|
import type {
|
||||||
BrushLineAddedArg,
|
BrushLineAddedArg,
|
||||||
@ -106,7 +112,7 @@ export class KonvaNodeManager {
|
|||||||
controlAdapters: Map<string, CanvasControlAdapter>;
|
controlAdapters: Map<string, CanvasControlAdapter>;
|
||||||
layers: Map<string, CanvasLayer>;
|
layers: Map<string, CanvasLayer>;
|
||||||
regions: Map<string, CanvasRegion>;
|
regions: Map<string, CanvasRegion>;
|
||||||
inpaintMask: CanvasInpaintMask | null;
|
inpaintMask: CanvasInpaintMask;
|
||||||
util: Util;
|
util: Util;
|
||||||
stateApi: StateApi;
|
stateApi: StateApi;
|
||||||
preview: CanvasPreview;
|
preview: CanvasPreview;
|
||||||
@ -134,23 +140,29 @@ export class KonvaNodeManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.preview = new CanvasPreview(
|
this.preview = new CanvasPreview(
|
||||||
this.stage,
|
new CanvasBbox(
|
||||||
this.stateApi.getBbox,
|
this.stateApi.getBbox,
|
||||||
this.stateApi.onBboxTransformed,
|
this.stateApi.onBboxTransformed,
|
||||||
this.stateApi.getShiftKey,
|
this.stateApi.getShiftKey,
|
||||||
this.stateApi.getCtrlKey,
|
this.stateApi.getCtrlKey,
|
||||||
this.stateApi.getMetaKey,
|
this.stateApi.getMetaKey,
|
||||||
this.stateApi.getAltKey
|
this.stateApi.getAltKey
|
||||||
|
),
|
||||||
|
new CanvasTool(),
|
||||||
|
new CanvasDocumentSizeOverlay(),
|
||||||
|
new CanvasStagingArea()
|
||||||
);
|
);
|
||||||
this.stage.add(this.preview.konvaLayer);
|
this.stage.add(this.preview.konvaLayer);
|
||||||
|
|
||||||
this.background = new CanvasBackground();
|
this.background = new CanvasBackground();
|
||||||
this.stage.add(this.background.konvaLayer);
|
this.stage.add(this.background.konvaLayer);
|
||||||
|
|
||||||
|
this.inpaintMask = new CanvasInpaintMask(this.stateApi.getInpaintMaskState(), this.stateApi.onPosChanged);
|
||||||
|
this.stage.add(this.inpaintMask.konvaLayer);
|
||||||
|
|
||||||
this.layers = new Map();
|
this.layers = new Map();
|
||||||
this.regions = new Map();
|
this.regions = new Map();
|
||||||
this.controlAdapters = new Map();
|
this.controlAdapters = new Map();
|
||||||
this.inpaintMask = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderLayers() {
|
renderLayers() {
|
||||||
@ -202,10 +214,6 @@ export class KonvaNodeManager {
|
|||||||
|
|
||||||
renderInpaintMask() {
|
renderInpaintMask() {
|
||||||
const inpaintMaskState = this.stateApi.getInpaintMaskState();
|
const inpaintMaskState = this.stateApi.getInpaintMaskState();
|
||||||
if (!this.inpaintMask) {
|
|
||||||
this.inpaintMask = new CanvasInpaintMask(inpaintMaskState, this.stateApi.onPosChanged);
|
|
||||||
this.stage.add(this.inpaintMask.konvaLayer);
|
|
||||||
}
|
|
||||||
const toolState = this.stateApi.getToolState();
|
const toolState = this.stateApi.getToolState();
|
||||||
const selectedEntity = this.stateApi.getSelectedEntity();
|
const selectedEntity = this.stateApi.getSelectedEntity();
|
||||||
const maskOpacity = this.stateApi.getMaskOpacity();
|
const maskOpacity = this.stateApi.getMaskOpacity();
|
||||||
@ -280,6 +288,10 @@ export class KonvaNodeManager {
|
|||||||
this.background.renderBackground(this.stage);
|
this.background.renderBackground(this.stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderStagingArea() {
|
||||||
|
this.preview.stagingArea.render(this.stateApi.getStagingAreaState());
|
||||||
|
}
|
||||||
|
|
||||||
fitDocument() {
|
fitDocument() {
|
||||||
this.preview.documentSizeOverlay.fitToStage(this.stage, this.stateApi.getDocument(), this.stateApi.setStageAttrs);
|
this.preview.documentSizeOverlay.fitToStage(this.stage, this.stateApi.getDocument(), this.stateApi.setStageAttrs);
|
||||||
}
|
}
|
||||||
|
@ -189,8 +189,8 @@ export class KonvaImage {
|
|||||||
image: imageEl,
|
image: imageEl,
|
||||||
});
|
});
|
||||||
this.konvaImageGroup.add(this.konvaImage);
|
this.konvaImageGroup.add(this.konvaImage);
|
||||||
this.imageName = imageName;
|
|
||||||
}
|
}
|
||||||
|
this.imageName = imageName;
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
this.isError = false;
|
this.isError = false;
|
||||||
this.konvaPlaceholderGroup.visible(false);
|
this.konvaPlaceholderGroup.visible(false);
|
||||||
|
@ -101,11 +101,11 @@ export class CanvasStagingArea {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stagingArea.selectedImageIndex) {
|
if (stagingArea.selectedImageIndex !== null) {
|
||||||
const imageDTO = stagingArea.images[stagingArea.selectedImageIndex];
|
const imageDTO = stagingArea.images[stagingArea.selectedImageIndex];
|
||||||
assert(imageDTO, 'Image must exist');
|
assert(imageDTO, 'Image must exist');
|
||||||
if (this.image) {
|
if (this.image) {
|
||||||
if (this.image.imageName !== imageDTO.image_name) {
|
if (!this.image.isLoading && !this.image.isError && this.image.imageName !== imageDTO.image_name) {
|
||||||
await this.image.updateImageSource(imageDTO.image_name);
|
await this.image.updateImageSource(imageDTO.image_name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -114,8 +114,8 @@ export class CanvasStagingArea {
|
|||||||
imageObject: {
|
imageObject: {
|
||||||
id: 'staging-area-image',
|
id: 'staging-area-image',
|
||||||
type: 'image',
|
type: 'image',
|
||||||
x: 0,
|
x: stagingArea.bbox.x,
|
||||||
y: 0,
|
y: stagingArea.bbox.y,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
filters: [],
|
filters: [],
|
||||||
@ -126,6 +126,8 @@ export class CanvasStagingArea {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
this.group.add(this.image.konvaImageGroup);
|
||||||
|
await this.image.updateImageSource(imageDTO.image_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,7 +377,6 @@ export class CanvasBbox {
|
|||||||
NO_ANCHORS: string[] = [];
|
NO_ANCHORS: string[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
stage: Konva.Stage,
|
|
||||||
getBbox: () => IRect,
|
getBbox: () => IRect,
|
||||||
onBboxTransformed: (bbox: IRect) => void,
|
onBboxTransformed: (bbox: IRect) => void,
|
||||||
getShiftKey: () => boolean,
|
getShiftKey: () => boolean,
|
||||||
@ -446,6 +447,8 @@ export class CanvasBbox {
|
|||||||
anchorDragBoundFunc: (_oldAbsPos, newAbsPos) => {
|
anchorDragBoundFunc: (_oldAbsPos, newAbsPos) => {
|
||||||
// This function works with absolute position - that is, a position in "physical" pixels on the screen, as opposed
|
// This function works with absolute position - that is, a position in "physical" pixels on the screen, as opposed
|
||||||
// to konva's internal coordinate system.
|
// to konva's internal coordinate system.
|
||||||
|
const stage = this.transformer.getStage();
|
||||||
|
assert(stage, 'Stage must exist');
|
||||||
|
|
||||||
// We need to snap the anchors to the grid. If the user is holding ctrl/meta, we use the finer 8px grid.
|
// We need to snap the anchors to the grid. If the user is holding ctrl/meta, we use the finer 8px grid.
|
||||||
const gridSize = getCtrlKey() || getMetaKey() ? 8 : 64;
|
const gridSize = getCtrlKey() || getMetaKey() ? 8 : 64;
|
||||||
@ -588,26 +591,23 @@ export class CanvasPreview {
|
|||||||
stagingArea: CanvasStagingArea;
|
stagingArea: CanvasStagingArea;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
stage: Konva.Stage,
|
bbox: CanvasBbox,
|
||||||
getBbox: () => IRect,
|
tool: CanvasTool,
|
||||||
onBboxTransformed: (bbox: IRect) => void,
|
documentSizeOverlay: CanvasDocumentSizeOverlay,
|
||||||
getShiftKey: () => boolean,
|
stagingArea: CanvasStagingArea
|
||||||
getCtrlKey: () => boolean,
|
|
||||||
getMetaKey: () => boolean,
|
|
||||||
getAltKey: () => boolean
|
|
||||||
) {
|
) {
|
||||||
this.konvaLayer = new Konva.Layer({ listening: true });
|
this.konvaLayer = new Konva.Layer({ listening: true });
|
||||||
|
|
||||||
this.bbox = new CanvasBbox(stage, getBbox, onBboxTransformed, getShiftKey, getCtrlKey, getMetaKey, getAltKey);
|
this.bbox = bbox;
|
||||||
this.konvaLayer.add(this.bbox.group);
|
this.konvaLayer.add(this.bbox.group);
|
||||||
|
|
||||||
this.tool = new CanvasTool();
|
this.tool = tool;
|
||||||
this.konvaLayer.add(this.tool.group);
|
this.konvaLayer.add(this.tool.group);
|
||||||
|
|
||||||
this.documentSizeOverlay = new CanvasDocumentSizeOverlay();
|
this.documentSizeOverlay = documentSizeOverlay;
|
||||||
this.konvaLayer.add(this.documentSizeOverlay.group);
|
this.konvaLayer.add(this.documentSizeOverlay.group);
|
||||||
|
|
||||||
this.stagingArea = new CanvasStagingArea();
|
this.stagingArea = stagingArea;
|
||||||
this.konvaLayer.add(this.stagingArea.group);
|
this.konvaLayer.add(this.stagingArea.group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,7 +343,7 @@ export const initializeRenderer = (
|
|||||||
// the entire state over when needed.
|
// the entire state over when needed.
|
||||||
const debouncedUpdateBboxes = debounce(updateBboxes, 300);
|
const debouncedUpdateBboxes = debounce(updateBboxes, 300);
|
||||||
|
|
||||||
const renderCanvas = () => {
|
const renderCanvas = async () => {
|
||||||
canvasV2 = store.getState().canvasV2;
|
canvasV2 = store.getState().canvasV2;
|
||||||
|
|
||||||
if (prevCanvasV2 === canvasV2 && !isFirstRender) {
|
if (prevCanvasV2 === canvasV2 && !isFirstRender) {
|
||||||
@ -408,6 +408,11 @@ export const initializeRenderer = (
|
|||||||
// debouncedUpdateBboxes(stage, canvasV2.layers, canvasV2.controlAdapters, canvasV2.regions, onBboxChanged);
|
// debouncedUpdateBboxes(stage, canvasV2.layers, canvasV2.controlAdapters, canvasV2.regions, onBboxChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFirstRender || canvasV2.stagingArea !== prevCanvasV2.stagingArea) {
|
||||||
|
logIfDebugging('Rendering staging area');
|
||||||
|
manager.renderStagingArea();
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isFirstRender ||
|
isFirstRender ||
|
||||||
canvasV2.layers.entities !== prevCanvasV2.layers.entities ||
|
canvasV2.layers.entities !== prevCanvasV2.layers.entities ||
|
||||||
|
Loading…
Reference in New Issue
Block a user