mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): split out session state from canvas rendering state
This commit is contained in:
parent
a58b91b221
commit
100832c66d
@ -1,10 +1,10 @@
|
||||
import { logger } from 'app/logging/logger';
|
||||
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
||||
import {
|
||||
rasterLayerAdded,
|
||||
sessionStagingAreaImageAccepted,
|
||||
sessionStagingAreaReset,
|
||||
} from 'features/controlLayers/store/canvasV2Slice';
|
||||
} from 'features/controlLayers/store/canvasSessionSlice';
|
||||
import { rasterLayerAdded } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import type { CanvasRasterLayerState } from 'features/controlLayers/store/types';
|
||||
import { imageDTOToImageObject } from 'features/controlLayers/store/types';
|
||||
import { toast } from 'features/toast/toast';
|
||||
@ -55,7 +55,7 @@ export const addStagingListeners = (startAppListening: AppStartListening) => {
|
||||
effect: (action, api) => {
|
||||
const { index } = action.payload;
|
||||
const state = api.getState();
|
||||
const stagingAreaImage = state.canvasV2.session.stagedImages[index];
|
||||
const stagingAreaImage = state.canvasSession.stagedImages[index];
|
||||
|
||||
assert(stagingAreaImage, 'No staged image found to accept');
|
||||
const { x, y } = state.canvasV2.bbox.rect;
|
||||
|
@ -5,7 +5,7 @@ import type { SerializableObject } from 'common/types';
|
||||
import type { Result } from 'common/util/result';
|
||||
import { isErr, withResult, withResultAsync } from 'common/util/result';
|
||||
import { $canvasManager } from 'features/controlLayers/konva/CanvasManager';
|
||||
import { sessionStagingAreaReset, sessionStartedStaging } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { sessionStagingAreaReset, sessionStartedStaging } from 'features/controlLayers/store/canvasSessionSlice';
|
||||
import { prepareLinearUIBatch } from 'features/nodes/util/graph/buildLinearBatchConfig';
|
||||
import { buildSD1Graph } from 'features/nodes/util/graph/generation/buildSD1Graph';
|
||||
import { buildSDXLGraph } from 'features/nodes/util/graph/generation/buildSDXLGraph';
|
||||
@ -31,13 +31,13 @@ export const addEnqueueRequestedLinear = (startAppListening: AppStartListening)
|
||||
|
||||
let didStartStaging = false;
|
||||
|
||||
if (!state.canvasV2.session.isStaging && state.canvasV2.session.mode === 'compose') {
|
||||
if (!state.canvasSession.isStaging && state.canvasSession.mode === 'compose') {
|
||||
dispatch(sessionStartedStaging());
|
||||
didStartStaging = true;
|
||||
}
|
||||
|
||||
const abortStaging = () => {
|
||||
if (didStartStaging && getState().canvasV2.session.isStaging) {
|
||||
if (didStartStaging && getState().canvasSession.isStaging) {
|
||||
dispatch(sessionStagingAreaReset());
|
||||
}
|
||||
};
|
||||
|
@ -6,6 +6,7 @@ import { errorHandler } from 'app/store/enhancers/reduxRemember/errors';
|
||||
import type { SerializableObject } from 'common/types';
|
||||
import { deepClone } from 'common/util/deepClone';
|
||||
import { changeBoardModalSlice } from 'features/changeBoardModal/store/slice';
|
||||
import { canvasSessionPersistConfig, canvasSessionSlice } from 'features/controlLayers/store/canvasSessionSlice';
|
||||
import { canvasSettingsPersistConfig, canvasSettingsSlice } from 'features/controlLayers/store/canvasSettingsSlice';
|
||||
import { canvasV2PersistConfig, canvasV2Slice } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { paramsPersistConfig, paramsSlice } from 'features/controlLayers/store/paramsSlice';
|
||||
@ -63,6 +64,7 @@ const allReducers = {
|
||||
[paramsSlice.name]: paramsSlice.reducer,
|
||||
[toolSlice.name]: toolSlice.reducer,
|
||||
[canvasSettingsSlice.name]: canvasSettingsSlice.reducer,
|
||||
[canvasSessionSlice.name]: canvasSessionSlice.reducer,
|
||||
};
|
||||
|
||||
const rootReducer = combineReducers(allReducers);
|
||||
@ -107,6 +109,7 @@ const persistConfigs: { [key in keyof typeof allReducers]?: PersistConfig } = {
|
||||
[paramsPersistConfig.name]: paramsPersistConfig,
|
||||
[toolPersistConfig.name]: toolPersistConfig,
|
||||
[canvasSettingsPersistConfig.name]: canvasSettingsPersistConfig,
|
||||
[canvasSessionPersistConfig.name]: canvasSessionPersistConfig,
|
||||
};
|
||||
|
||||
const unserialize: UnserializeFunction = (data, key) => {
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { Button, ButtonGroup } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { sessionModeChanged } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { sessionModeChanged } from 'features/controlLayers/store/canvasSessionSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const CanvasModeSwitcher = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const mode = useAppSelector((s) => s.canvasV2.session.mode);
|
||||
const mode = useAppSelector((s) => s.canvasSession.mode);
|
||||
const onClickGenerate = useCallback(() => dispatch(sessionModeChanged({ mode: 'generate' })), [dispatch]);
|
||||
const onClickCompose = useCallback(() => dispatch(sessionModeChanged({ mode: 'compose' })), [dispatch]);
|
||||
|
||||
|
@ -33,9 +33,11 @@ export const CanvasEditor = memo(() => {
|
||||
<ControlLayersToolbar />
|
||||
<StageComponent />
|
||||
<Flex position="absolute" bottom={16} gap={2} align="center" justify="center">
|
||||
<StagingAreaIsStagingGate>
|
||||
<StagingAreaToolbar />
|
||||
</StagingAreaIsStagingGate>
|
||||
<CanvasManagerProviderGate>
|
||||
<StagingAreaIsStagingGate>
|
||||
<StagingAreaToolbar />
|
||||
</StagingAreaIsStagingGate>
|
||||
</CanvasManagerProviderGate>
|
||||
</Flex>
|
||||
<Flex position="absolute" bottom={16}>
|
||||
<CanvasManagerProviderGate>
|
||||
|
@ -3,7 +3,7 @@ import type { PropsWithChildren } from 'react';
|
||||
import { memo } from 'react';
|
||||
|
||||
export const StagingAreaIsStagingGate = memo((props: PropsWithChildren) => {
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
|
||||
if (!isStaging) {
|
||||
return null;
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
sessionStagedImageDiscarded,
|
||||
sessionStagingAreaImageAccepted,
|
||||
sessionStagingAreaReset,
|
||||
} from 'features/controlLayers/store/canvasV2Slice';
|
||||
} from 'features/controlLayers/store/canvasSessionSlice';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -27,7 +27,7 @@ import { useChangeImageIsIntermediateMutation } from 'services/api/endpoints/ima
|
||||
|
||||
export const StagingAreaToolbar = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const session = useAppSelector((s) => s.canvasV2.session);
|
||||
const session = useAppSelector((s) => s.canvasSession);
|
||||
const canvasManager = useCanvasManager();
|
||||
const shouldShowStagedImage = useStore(canvasManager.stateApi.$shouldShowStagedImage);
|
||||
const images = useMemo(() => session.stagedImages, [session]);
|
||||
|
@ -14,7 +14,7 @@ export const ToolBboxButton = memo(() => {
|
||||
const isSelected = useToolIsSelected('bbox');
|
||||
const isFiltering = useIsFiltering();
|
||||
const isTransforming = useIsTransforming();
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
const isDisabled = useMemo(() => {
|
||||
return isTransforming || isFiltering || isStaging;
|
||||
}, [isFiltering, isStaging, isTransforming]);
|
||||
|
@ -13,7 +13,7 @@ export const ToolBrushButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isFiltering = useIsFiltering();
|
||||
const isTransforming = useIsTransforming();
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
const selectBrush = useSelectTool('brush');
|
||||
const isSelected = useToolIsSelected('brush');
|
||||
const isDrawingToolAllowed = useAppSelector((s) => {
|
||||
|
@ -14,7 +14,7 @@ export const ToolColorPickerButton = memo(() => {
|
||||
const isTransforming = useIsTransforming();
|
||||
const selectColorPicker = useSelectTool('colorPicker');
|
||||
const isSelected = useToolIsSelected('colorPicker');
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
|
||||
const isDisabled = useMemo(() => {
|
||||
return isTransforming || isFiltering || isStaging;
|
||||
|
@ -13,7 +13,7 @@ export const ToolEraserButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isFiltering = useIsFiltering();
|
||||
const isTransforming = useIsTransforming();
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
const selectEraser = useSelectTool('eraser');
|
||||
const isSelected = useToolIsSelected('eraser');
|
||||
const isDrawingToolAllowed = useAppSelector((s) => {
|
||||
|
@ -15,7 +15,7 @@ export const ToolMoveButton = memo(() => {
|
||||
const isTransforming = useIsTransforming();
|
||||
const selectMove = useSelectTool('move');
|
||||
const isSelected = useToolIsSelected('move');
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
const isDrawingToolAllowed = useAppSelector((s) => {
|
||||
if (!s.canvasV2.selectedEntityIdentifier?.type) {
|
||||
return false;
|
||||
|
@ -15,7 +15,7 @@ export const ToolRectButton = memo(() => {
|
||||
const isSelected = useToolIsSelected('rect');
|
||||
const isFiltering = useIsFiltering();
|
||||
const isTransforming = useIsTransforming();
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
const isDrawingToolAllowed = useAppSelector((s) => {
|
||||
if (!s.canvasV2.selectedEntityIdentifier?.type) {
|
||||
return false;
|
||||
|
@ -12,7 +12,7 @@ export const ToolViewButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isTransforming = useIsTransforming();
|
||||
const isFiltering = useIsFiltering();
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
const selectView = useSelectTool('view');
|
||||
const isSelected = useToolIsSelected('view');
|
||||
const isDisabled = useMemo(() => {
|
||||
|
@ -15,7 +15,7 @@ export function useCanvasDeleteLayerHotkey() {
|
||||
useAssertSingleton(useCanvasDeleteLayerHotkey.name);
|
||||
const dispatch = useAppDispatch();
|
||||
const selectedEntityIdentifier = useAppSelector(selectSelectedEntityIdentifier);
|
||||
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
|
||||
const isStaging = useAppSelector((s) => s.canvasSession.isStaging);
|
||||
|
||||
const deleteSelectedLayer = useCallback(() => {
|
||||
if (selectedEntityIdentifier === null) {
|
||||
|
@ -4,6 +4,7 @@ import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
|
||||
import { CanvasMaskAdapter } from 'features/controlLayers/konva/CanvasMaskAdapter';
|
||||
import { CanvasModuleBase } from 'features/controlLayers/konva/CanvasModuleBase';
|
||||
import { getPrefixedId } from 'features/controlLayers/konva/util';
|
||||
import type { CanvasSessionState } from 'features/controlLayers/store/canvasSessionSlice';
|
||||
import type { CanvasSettingsState } from 'features/controlLayers/store/canvasSettingsSlice';
|
||||
import type { CanvasV2State } from 'features/controlLayers/store/types';
|
||||
import type { Logger } from 'roarr';
|
||||
@ -19,6 +20,9 @@ export class CanvasRenderingModule extends CanvasModuleBase {
|
||||
|
||||
state: CanvasV2State | null = null;
|
||||
settings: CanvasSettingsState | null = null;
|
||||
session: CanvasSessionState | null = null;
|
||||
|
||||
isFirstRender = true;
|
||||
|
||||
constructor(manager: CanvasManager) {
|
||||
super();
|
||||
@ -30,42 +34,79 @@ export class CanvasRenderingModule extends CanvasModuleBase {
|
||||
}
|
||||
|
||||
render = async () => {
|
||||
const state = this.manager.stateApi.getCanvasState();
|
||||
const settings = this.manager.stateApi.getSettings();
|
||||
|
||||
if (!this.state || !this.settings) {
|
||||
if (!this.state || !this.settings || !this.session) {
|
||||
this.log.trace('First render');
|
||||
}
|
||||
|
||||
await this.renderCanvas();
|
||||
this.renderSettings();
|
||||
await this.renderSession();
|
||||
|
||||
// We have no prev state for the first render
|
||||
if (this.isFirstRender) {
|
||||
this.isFirstRender = false;
|
||||
this.manager.setCanvasManager();
|
||||
}
|
||||
};
|
||||
|
||||
renderCanvas = async () => {
|
||||
const state = this.manager.stateApi.getCanvasState();
|
||||
|
||||
const prevState = this.state;
|
||||
this.state = state;
|
||||
|
||||
const prevSettings = this.settings;
|
||||
this.settings = settings;
|
||||
|
||||
if (prevState === state && prevSettings === settings) {
|
||||
if (prevState === state) {
|
||||
// No changes to state - no need to render
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderBackground(settings, prevSettings);
|
||||
await this.renderRasterLayers(state, prevState);
|
||||
await this.renderControlLayers(prevState, state);
|
||||
await this.renderRegionalGuidance(prevState, state);
|
||||
await this.renderInpaintMasks(state, prevState);
|
||||
await this.renderBbox(state, prevState);
|
||||
await this.renderStagingArea(state, prevState);
|
||||
this.arrangeEntities(state, prevState);
|
||||
|
||||
this.manager.stateApi.$toolState.set(this.manager.stateApi.getToolState());
|
||||
this.manager.stateApi.$selectedEntityIdentifier.set(state.selectedEntityIdentifier);
|
||||
this.manager.stateApi.$selectedEntity.set(this.manager.stateApi.getSelectedEntity());
|
||||
this.manager.stateApi.$currentFill.set(this.manager.stateApi.getCurrentFill());
|
||||
};
|
||||
|
||||
// We have no prev state for the first render
|
||||
if (!prevState && !prevSettings) {
|
||||
this.manager.setCanvasManager();
|
||||
renderSettings = () => {
|
||||
const settings = this.manager.stateApi.getSettings();
|
||||
|
||||
if (!this.settings) {
|
||||
this.log.trace('First settings render');
|
||||
}
|
||||
|
||||
const prevSettings = this.settings;
|
||||
this.settings = settings;
|
||||
|
||||
if (prevSettings === settings) {
|
||||
// No changes to state - no need to render
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderBackground(settings, prevSettings);
|
||||
};
|
||||
|
||||
renderSession = async () => {
|
||||
const session = this.manager.stateApi.getSession();
|
||||
|
||||
if (!this.session) {
|
||||
this.log.trace('First session render');
|
||||
}
|
||||
|
||||
const prevSession = this.session;
|
||||
this.session = session;
|
||||
|
||||
if (prevSession === session) {
|
||||
// No changes to state - no need to render
|
||||
return;
|
||||
}
|
||||
|
||||
await this.renderStagingArea(session, prevSession);
|
||||
};
|
||||
|
||||
getLoggingContext = (): SerializableObject => {
|
||||
@ -210,8 +251,8 @@ export class CanvasRenderingModule extends CanvasModuleBase {
|
||||
}
|
||||
};
|
||||
|
||||
renderStagingArea = async (state: CanvasV2State, prevState: CanvasV2State | null) => {
|
||||
if (!prevState || state.session !== prevState.session) {
|
||||
renderStagingArea = async (session: CanvasSessionState, prevSession: CanvasSessionState | null) => {
|
||||
if (!prevSession || session !== prevSession) {
|
||||
await this.manager.preview.stagingArea.render();
|
||||
}
|
||||
};
|
||||
|
@ -165,7 +165,7 @@ export class CanvasStateApiModule extends CanvasModuleBase {
|
||||
return this.getCanvasState().inpaintMasks;
|
||||
};
|
||||
getSession = () => {
|
||||
return this.getCanvasState().session;
|
||||
return this.store.getState().canvasSession;
|
||||
};
|
||||
getIsSelected = (id: string) => {
|
||||
return this.getCanvasState().selectedEntityIdentifier?.id === id;
|
||||
|
@ -0,0 +1,83 @@
|
||||
import { createAction, createSlice, type PayloadAction } from '@reduxjs/toolkit';
|
||||
import type { PersistConfig } from 'app/store/store';
|
||||
import { canvasV2Slice } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import type { SessionMode, StagingAreaImage } from 'features/controlLayers/store/types';
|
||||
|
||||
export type CanvasSessionState = {
|
||||
mode: SessionMode;
|
||||
isStaging: boolean;
|
||||
stagedImages: StagingAreaImage[];
|
||||
selectedStagedImageIndex: number;
|
||||
};
|
||||
|
||||
const initialState: CanvasSessionState = {
|
||||
mode: 'generate',
|
||||
isStaging: false,
|
||||
stagedImages: [],
|
||||
selectedStagedImageIndex: 0,
|
||||
};
|
||||
|
||||
export const canvasSessionSlice = createSlice({
|
||||
name: 'canvasSession',
|
||||
initialState,
|
||||
reducers: {
|
||||
sessionStartedStaging: (state) => {
|
||||
state.isStaging = true;
|
||||
state.selectedStagedImageIndex = 0;
|
||||
},
|
||||
sessionImageStaged: (state, action: PayloadAction<{ stagingAreaImage: StagingAreaImage }>) => {
|
||||
const { stagingAreaImage } = action.payload;
|
||||
state.stagedImages.push(stagingAreaImage);
|
||||
state.selectedStagedImageIndex = state.stagedImages.length - 1;
|
||||
},
|
||||
sessionNextStagedImageSelected: (state) => {
|
||||
state.selectedStagedImageIndex = (state.selectedStagedImageIndex + 1) % state.stagedImages.length;
|
||||
},
|
||||
sessionPrevStagedImageSelected: (state) => {
|
||||
state.selectedStagedImageIndex =
|
||||
(state.selectedStagedImageIndex - 1 + state.stagedImages.length) % state.stagedImages.length;
|
||||
},
|
||||
sessionStagedImageDiscarded: (state, action: PayloadAction<{ index: number }>) => {
|
||||
const { index } = action.payload;
|
||||
state.stagedImages.splice(index, 1);
|
||||
state.selectedStagedImageIndex = Math.min(state.selectedStagedImageIndex, state.stagedImages.length - 1);
|
||||
if (state.stagedImages.length === 0) {
|
||||
state.isStaging = false;
|
||||
}
|
||||
},
|
||||
sessionStagingAreaReset: (state) => {
|
||||
state.isStaging = false;
|
||||
state.stagedImages = [];
|
||||
state.selectedStagedImageIndex = 0;
|
||||
},
|
||||
sessionModeChanged: (state, action: PayloadAction<{ mode: SessionMode }>) => {
|
||||
const { mode } = action.payload;
|
||||
state.mode = mode;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
sessionStartedStaging,
|
||||
sessionImageStaged,
|
||||
sessionStagedImageDiscarded,
|
||||
sessionStagingAreaReset,
|
||||
sessionNextStagedImageSelected,
|
||||
sessionPrevStagedImageSelected,
|
||||
sessionModeChanged,
|
||||
} = canvasSessionSlice.actions;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
const migrate = (state: any): any => {
|
||||
return state;
|
||||
};
|
||||
|
||||
export const canvasSessionPersistConfig: PersistConfig<CanvasSessionState> = {
|
||||
name: canvasSessionSlice.name,
|
||||
initialState,
|
||||
migrate,
|
||||
persistDenylist: [],
|
||||
};
|
||||
export const sessionStagingAreaImageAccepted = createAction<{ index: number }>(
|
||||
`${canvasV2Slice.name}/sessionStagingAreaImageAccepted`
|
||||
);
|
@ -1,5 +1,5 @@
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { createAction, createSlice } from '@reduxjs/toolkit';
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { PersistConfig } from 'app/store/store';
|
||||
import { moveOneToEnd, moveOneToStart, moveToEnd, moveToStart } from 'common/util/arrayUtils';
|
||||
import { deepClone } from 'common/util/deepClone';
|
||||
@ -13,7 +13,6 @@ import { modelChanged } from 'features/controlLayers/store/paramsSlice';
|
||||
import { rasterLayersReducers } from 'features/controlLayers/store/rasterLayersReducers';
|
||||
import { regionsReducers } from 'features/controlLayers/store/regionsReducers';
|
||||
import { selectAllEntities, selectAllEntitiesOfType, selectEntity } from 'features/controlLayers/store/selectors';
|
||||
import { sessionReducers } from 'features/controlLayers/store/sessionReducers';
|
||||
import { getScaledBoundingBoxDimensions } from 'features/controlLayers/util/getScaledBoundingBoxDimensions';
|
||||
import { simplifyFlatNumbersArray } from 'features/controlLayers/util/simplify';
|
||||
import { calculateNewSize } from 'features/parameters/components/DocumentSize/calculateNewSize';
|
||||
@ -65,12 +64,6 @@ const initialState: CanvasV2State = {
|
||||
height: 512,
|
||||
},
|
||||
},
|
||||
session: {
|
||||
mode: 'generate',
|
||||
isStaging: false,
|
||||
stagedImages: [],
|
||||
selectedStagedImageIndex: 0,
|
||||
},
|
||||
};
|
||||
|
||||
export const canvasV2Slice = createSlice({
|
||||
@ -86,7 +79,6 @@ export const canvasV2Slice = createSlice({
|
||||
...bboxReducers,
|
||||
// move out
|
||||
...lorasReducers,
|
||||
...sessionReducers,
|
||||
entitySelected: (state, action: PayloadAction<EntityIdentifierPayload>) => {
|
||||
const { entityIdentifier } = action.payload;
|
||||
state.selectedEntityIdentifier = entityIdentifier;
|
||||
@ -339,7 +331,6 @@ export const canvasV2Slice = createSlice({
|
||||
state.bbox.rect.height = state.bbox.optimalDimension;
|
||||
const size = pick(state.bbox.rect, 'width', 'height');
|
||||
state.bbox.scaledSize = getScaledBoundingBoxDimensions(size, state.bbox.optimalDimension);
|
||||
state.session = deepClone(initialState.session);
|
||||
|
||||
state.ipAdapters = deepClone(initialState.ipAdapters);
|
||||
state.rasterLayers = deepClone(initialState.rasterLayers);
|
||||
@ -458,14 +449,6 @@ export const {
|
||||
// inpaintMaskRecalled,
|
||||
inpaintMaskFillColorChanged,
|
||||
inpaintMaskFillStyleChanged,
|
||||
// Staging
|
||||
sessionStartedStaging,
|
||||
sessionImageStaged,
|
||||
sessionStagedImageDiscarded,
|
||||
sessionStagingAreaReset,
|
||||
sessionNextStagedImageSelected,
|
||||
sessionPrevStagedImageSelected,
|
||||
sessionModeChanged,
|
||||
} = canvasV2Slice.actions;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
@ -479,7 +462,3 @@ export const canvasV2PersistConfig: PersistConfig<CanvasV2State> = {
|
||||
migrate,
|
||||
persistDenylist: [],
|
||||
};
|
||||
|
||||
export const sessionStagingAreaImageAccepted = createAction<{ index: number }>(
|
||||
`${canvasV2Slice.name}/sessionStagingAreaImageAccepted`
|
||||
);
|
||||
|
@ -1,43 +0,0 @@
|
||||
import type { PayloadAction, SliceCaseReducers } from '@reduxjs/toolkit';
|
||||
import type { CanvasV2State, SessionMode, StagingAreaImage } from 'features/controlLayers/store/types';
|
||||
|
||||
export const sessionReducers = {
|
||||
sessionStartedStaging: (state) => {
|
||||
state.session.isStaging = true;
|
||||
state.session.selectedStagedImageIndex = 0;
|
||||
},
|
||||
sessionImageStaged: (state, action: PayloadAction<{ stagingAreaImage: StagingAreaImage }>) => {
|
||||
const { stagingAreaImage } = action.payload;
|
||||
state.session.stagedImages.push(stagingAreaImage);
|
||||
state.session.selectedStagedImageIndex = state.session.stagedImages.length - 1;
|
||||
},
|
||||
sessionNextStagedImageSelected: (state) => {
|
||||
state.session.selectedStagedImageIndex =
|
||||
(state.session.selectedStagedImageIndex + 1) % state.session.stagedImages.length;
|
||||
},
|
||||
sessionPrevStagedImageSelected: (state) => {
|
||||
state.session.selectedStagedImageIndex =
|
||||
(state.session.selectedStagedImageIndex - 1 + state.session.stagedImages.length) %
|
||||
state.session.stagedImages.length;
|
||||
},
|
||||
sessionStagedImageDiscarded: (state, action: PayloadAction<{ index: number }>) => {
|
||||
const { index } = action.payload;
|
||||
state.session.stagedImages.splice(index, 1);
|
||||
state.session.selectedStagedImageIndex = Math.min(
|
||||
state.session.selectedStagedImageIndex,
|
||||
state.session.stagedImages.length - 1
|
||||
);
|
||||
if (state.session.stagedImages.length === 0) {
|
||||
state.session.isStaging = false;
|
||||
}
|
||||
},
|
||||
sessionStagingAreaReset: (state) => {
|
||||
state.session.isStaging = false;
|
||||
state.session.stagedImages = [];
|
||||
state.session.selectedStagedImageIndex = 0;
|
||||
},
|
||||
sessionModeChanged: (state, action: PayloadAction<{ mode: SessionMode }>) => {
|
||||
const { mode } = action.payload;
|
||||
state.session.mode = mode;
|
||||
},
|
||||
} satisfies SliceCaseReducers<CanvasV2State>;
|
@ -730,12 +730,6 @@ export type CanvasV2State = {
|
||||
scaleMethod: BoundingBoxScaleMethod;
|
||||
optimalDimension: number;
|
||||
};
|
||||
session: {
|
||||
mode: SessionMode;
|
||||
isStaging: boolean;
|
||||
stagedImages: StagingAreaImage[];
|
||||
selectedStagedImageIndex: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type StageAttrs = {
|
||||
|
@ -21,9 +21,9 @@ export const addInpaint = async (
|
||||
): Promise<Invocation<'canvas_v2_mask_and_crop'>> => {
|
||||
denoise.denoising_start = denoising_start;
|
||||
|
||||
const { params, canvasV2 } = state;
|
||||
const { bbox, session } = canvasV2;
|
||||
const { mode } = session;
|
||||
const { params, canvasV2, canvasSession } = state;
|
||||
const { bbox } = canvasV2;
|
||||
const { mode } = canvasSession;
|
||||
|
||||
const initialImage = await manager.compositor.getCompositeRasterLayerImageDTO(bbox.rect);
|
||||
const maskImage = await manager.compositor.getCompositeInpaintMaskImageDTO(bbox.rect);
|
||||
|
@ -22,9 +22,9 @@ export const addOutpaint = async (
|
||||
): Promise<Invocation<'canvas_v2_mask_and_crop'>> => {
|
||||
denoise.denoising_start = denoising_start;
|
||||
|
||||
const { params, canvasV2 } = state;
|
||||
const { bbox, session } = canvasV2;
|
||||
const { mode } = session;
|
||||
const { params, canvasV2, canvasSession } = state;
|
||||
const { bbox } = canvasV2;
|
||||
const { mode } = canvasSession;
|
||||
|
||||
const initialImage = await manager.compositor.getCompositeRasterLayerImageDTO(bbox.rect);
|
||||
const maskImage = await manager.compositor.getCompositeInpaintMaskImageDTO(bbox.rect);
|
||||
|
@ -31,8 +31,8 @@ export const buildSD1Graph = async (
|
||||
const generationMode = manager.compositor.getGenerationMode();
|
||||
log.debug({ generationMode }, 'Building SD1/SD2 graph');
|
||||
|
||||
const { canvasV2, params, canvasSettings } = state;
|
||||
const { bbox, session } = canvasV2;
|
||||
const { canvasV2, params, canvasSettings, canvasSession } = state;
|
||||
const { bbox } = canvasV2;
|
||||
|
||||
const {
|
||||
model,
|
||||
@ -274,7 +274,7 @@ export const buildSD1Graph = async (
|
||||
canvasOutput = addWatermarker(g, canvasOutput);
|
||||
}
|
||||
|
||||
const shouldSaveToGallery = session.mode === 'generate' || canvasSettings.autoSave;
|
||||
const shouldSaveToGallery = canvasSession.mode === 'generate' || canvasSettings.autoSave;
|
||||
|
||||
g.updateNode(canvasOutput, {
|
||||
id: getPrefixedId('canvas_output'),
|
||||
|
@ -31,8 +31,8 @@ export const buildSDXLGraph = async (
|
||||
const generationMode = manager.compositor.getGenerationMode();
|
||||
log.debug({ generationMode }, 'Building SDXL graph');
|
||||
|
||||
const { params, canvasV2, canvasSettings } = state;
|
||||
const { bbox, session } = canvasV2;
|
||||
const { params, canvasV2, canvasSettings, canvasSession } = state;
|
||||
const { bbox } = canvasV2;
|
||||
|
||||
const {
|
||||
model,
|
||||
@ -277,7 +277,7 @@ export const buildSDXLGraph = async (
|
||||
canvasOutput = addWatermarker(g, canvasOutput);
|
||||
}
|
||||
|
||||
const shouldSaveToGallery = session.mode === 'generate' || canvasSettings.autoSave;
|
||||
const shouldSaveToGallery = canvasSession.mode === 'generate' || canvasSettings.autoSave;
|
||||
|
||||
g.updateNode(canvasOutput, {
|
||||
id: getPrefixedId('canvas_output'),
|
||||
|
@ -2,7 +2,7 @@ import { logger } from 'app/logging/logger';
|
||||
import type { AppDispatch, RootState } from 'app/store/store';
|
||||
import type { SerializableObject } from 'common/types';
|
||||
import { deepClone } from 'common/util/deepClone';
|
||||
import { sessionImageStaged } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { sessionImageStaged } from 'features/controlLayers/store/canvasSessionSlice';
|
||||
import { boardIdSelected, galleryViewChanged, imageSelected, offsetChanged } from 'features/gallery/store/gallerySlice';
|
||||
import { $nodeExecutionStates, upsertExecutionState } from 'features/nodes/hooks/useExecutionState';
|
||||
import { zNodeStatus } from 'features/nodes/types/invocation';
|
||||
@ -114,7 +114,7 @@ export const buildOnInvocationComplete = (
|
||||
};
|
||||
|
||||
const handleOriginCanvas = async (data: S['InvocationCompleteEvent']) => {
|
||||
const session = getState().canvasV2.session;
|
||||
const session = getState().canvasSession;
|
||||
|
||||
const imageDTO = await getResultImageDTO(data);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user