mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
refactor(ui): update size/prompts state
This commit is contained in:
parent
5fc7a03669
commit
ccceba7565
@ -79,15 +79,15 @@ const handleMainModels: ModelHandler = (models, state, dispatch, log) => {
|
||||
const optimalDimension = getOptimalDimension(defaultModelInList);
|
||||
if (
|
||||
getIsSizeOptimal(
|
||||
state.canvasV2.size.width,
|
||||
state.canvasV2.size.height,
|
||||
state.canvasV2.document.width,
|
||||
state.canvasV2.document.height,
|
||||
optimalDimension
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const { width, height } = calculateNewSize(
|
||||
state.canvasV2.size.aspectRatio.value,
|
||||
state.canvasV2.document.aspectRatio.value,
|
||||
optimalDimension * optimalDimension
|
||||
);
|
||||
|
||||
|
@ -1,11 +1,7 @@
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectControlAdaptersV2Slice } from 'features/controlLayers/store/controlAdaptersSlice';
|
||||
import { selectCanvasV2Slice } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { selectIPAdaptersSlice } from 'features/controlLayers/store/ipAdaptersSlice';
|
||||
import { selectLayersSlice } from 'features/controlLayers/store/layersSlice';
|
||||
import { selectRegionalGuidanceSlice } from 'features/controlLayers/store/regionalGuidanceSlice';
|
||||
import type { CanvasEntity } from 'features/controlLayers/store/types';
|
||||
import { selectDynamicPromptsSlice } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import { getShouldProcessPrompt } from 'features/dynamicPrompts/util/getShouldProcessPrompt';
|
||||
@ -40,32 +36,13 @@ const createSelector = (templates: Templates) =>
|
||||
selectWorkflowSettingsSlice,
|
||||
selectDynamicPromptsSlice,
|
||||
selectCanvasV2Slice,
|
||||
selectLayersSlice,
|
||||
selectControlAdaptersV2Slice,
|
||||
selectRegionalGuidanceSlice,
|
||||
selectIPAdaptersSlice,
|
||||
activeTabNameSelector,
|
||||
selectUpscalelice,
|
||||
selectConfigSlice,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(
|
||||
generation,
|
||||
system,
|
||||
nodes,
|
||||
workflowSettings,
|
||||
dynamicPrompts,
|
||||
canvasV2,
|
||||
layersState,
|
||||
controlAdaptersState,
|
||||
regionalGuidanceState,
|
||||
ipAdaptersState,
|
||||
activeTabName,
|
||||
upscale,
|
||||
config
|
||||
) => {
|
||||
const { model } = generation;
|
||||
const { size } = canvasV2;
|
||||
const { positivePrompt } = canvasV2.prompts;
|
||||
(generation, system, nodes, workflowSettings, dynamicPrompts, canvasV2, upscale, config, activeTabName) => {
|
||||
const { model, positivePrompt } = generation;
|
||||
const { bbox } = canvasV2;
|
||||
|
||||
const { isConnected } = system;
|
||||
|
||||
@ -149,7 +126,7 @@ const createSelector = (templates: Templates) =>
|
||||
reasons.push({ content: i18n.t('parameters.invoke.noModelSelected') });
|
||||
}
|
||||
|
||||
controlAdaptersState.controlAdapters
|
||||
canvasV2.controlAdapters
|
||||
.filter((ca) => ca.isEnabled)
|
||||
.forEach((ca, i) => {
|
||||
const layerLiteral = i18n.t('controlLayers.layers_one');
|
||||
@ -174,7 +151,7 @@ const createSelector = (templates: Templates) =>
|
||||
// T2I Adapters require images have dimensions that are multiples of 64 (SD1.5) or 32 (SDXL)
|
||||
if (!ca.controlMode) {
|
||||
const multiple = model?.base === 'sdxl' ? 32 : 64;
|
||||
if (size.width % multiple !== 0 || size.height % multiple !== 0) {
|
||||
if (bbox.width % multiple !== 0 || bbox.height % multiple !== 0) {
|
||||
problems.push(i18n.t('parameters.invoke.layer.t2iAdapterIncompatibleDimensions', { multiple }));
|
||||
}
|
||||
}
|
||||
@ -185,7 +162,7 @@ const createSelector = (templates: Templates) =>
|
||||
}
|
||||
});
|
||||
|
||||
ipAdaptersState.ipAdapters
|
||||
canvasV2.ipAdapters
|
||||
.filter((ipa) => ipa.isEnabled)
|
||||
.forEach((ipa, i) => {
|
||||
const layerLiteral = i18n.t('controlLayers.layers_one');
|
||||
@ -213,7 +190,7 @@ const createSelector = (templates: Templates) =>
|
||||
}
|
||||
});
|
||||
|
||||
regionalGuidanceState.regions
|
||||
canvasV2.regions
|
||||
.filter((rg) => rg.isEnabled)
|
||||
.forEach((rg, i) => {
|
||||
const layerLiteral = i18n.t('controlLayers.layers_one');
|
||||
@ -250,7 +227,7 @@ const createSelector = (templates: Templates) =>
|
||||
}
|
||||
});
|
||||
|
||||
layersState.layers
|
||||
canvasV2.layers
|
||||
.filter((l) => l.isEnabled)
|
||||
.forEach((l, i) => {
|
||||
const layerLiteral = i18n.t('controlLayers.layers_one');
|
||||
|
@ -35,7 +35,6 @@ import {
|
||||
rgLinePointAdded,
|
||||
rgRectAdded,
|
||||
rgTranslated,
|
||||
selectCanvasV2Slice,
|
||||
toolBufferChanged,
|
||||
toolChanged,
|
||||
} from 'features/controlLayers/store/canvasV2Slice';
|
||||
@ -65,50 +64,51 @@ const log = logger('controlLayers');
|
||||
|
||||
const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null, asPreview: boolean) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const canvasV2State = useAppSelector(selectCanvasV2Slice);
|
||||
const controlAdapters = useAppSelector((s) => s.canvasV2.controlAdapters);
|
||||
const ipAdapters = useAppSelector((s) => s.canvasV2.ipAdapters);
|
||||
const layers = useAppSelector((s) => s.canvasV2.layers);
|
||||
const regions = useAppSelector((s) => s.canvasV2.regions);
|
||||
const tool = useAppSelector((s) => s.canvasV2.tool);
|
||||
const selectedEntityIdentifier = useAppSelector((s) => s.canvasV2.selectedEntityIdentifier);
|
||||
const maskFillOpacity = useAppSelector((s) => s.canvasV2.maskFillOpacity);
|
||||
const bbox = useAppSelector((s) => s.canvasV2.bbox);
|
||||
const lastCursorPos = useStore($lastCursorPos);
|
||||
const lastMouseDownPos = useStore($lastMouseDownPos);
|
||||
const isMouseDown = useStore($isMouseDown);
|
||||
const isDrawing = useStore($isDrawing);
|
||||
const selectedEntity = useMemo(() => {
|
||||
const identifier = canvasV2State.selectedEntityIdentifier;
|
||||
const identifier = selectedEntityIdentifier;
|
||||
if (!identifier) {
|
||||
return null;
|
||||
} else if (identifier.type === 'layer') {
|
||||
return canvasV2State.layers.find((i) => i.id === identifier.id) ?? null;
|
||||
return layers.find((i) => i.id === identifier.id) ?? null;
|
||||
} else if (identifier.type === 'control_adapter') {
|
||||
return canvasV2State.controlAdapters.find((i) => i.id === identifier.id) ?? null;
|
||||
return controlAdapters.find((i) => i.id === identifier.id) ?? null;
|
||||
} else if (identifier.type === 'ip_adapter') {
|
||||
return canvasV2State.ipAdapters.find((i) => i.id === identifier.id) ?? null;
|
||||
return ipAdapters.find((i) => i.id === identifier.id) ?? null;
|
||||
} else if (identifier.type === 'regional_guidance') {
|
||||
return canvasV2State.regions.find((i) => i.id === identifier.id) ?? null;
|
||||
return regions.find((i) => i.id === identifier.id) ?? null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}, [
|
||||
canvasV2State.controlAdapters,
|
||||
canvasV2State.ipAdapters,
|
||||
canvasV2State.layers,
|
||||
canvasV2State.regions,
|
||||
canvasV2State.selectedEntityIdentifier,
|
||||
]);
|
||||
}, [controlAdapters, ipAdapters, layers, regions, selectedEntityIdentifier]);
|
||||
|
||||
const currentFill = useMemo(() => {
|
||||
if (selectedEntity && selectedEntity.type === 'regional_guidance') {
|
||||
return { ...selectedEntity.fill, a: canvasV2State.maskFillOpacity };
|
||||
return { ...selectedEntity.fill, a: maskFillOpacity };
|
||||
}
|
||||
return canvasV2State.tool.fill;
|
||||
}, [canvasV2State.maskFillOpacity, canvasV2State.tool.fill, selectedEntity]);
|
||||
return tool.fill;
|
||||
}, [maskFillOpacity, selectedEntity, tool.fill]);
|
||||
|
||||
const renderers = useMemo(() => (asPreview ? debouncedRenderers : normalRenderers), [asPreview]);
|
||||
const dpr = useDevicePixelRatio({ round: false });
|
||||
|
||||
useLayoutEffect(() => {
|
||||
$toolState.set(canvasV2State.tool);
|
||||
$toolState.set(tool);
|
||||
$selectedEntity.set(selectedEntity);
|
||||
$bbox.set(canvasV2State.bbox);
|
||||
$bbox.set(bbox);
|
||||
$currentFill.set(currentFill);
|
||||
}, [selectedEntity, canvasV2State.tool, canvasV2State.bbox, currentFill]);
|
||||
}, [selectedEntity, tool, bbox, currentFill]);
|
||||
|
||||
const onPosChanged = useCallback(
|
||||
(arg: PosChangedArg, entityType: CanvasEntity['type']) => {
|
||||
@ -305,7 +305,7 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
|
||||
log.trace('Rendering tool preview');
|
||||
renderers.renderToolPreview(
|
||||
stage,
|
||||
canvasV2State.tool,
|
||||
tool,
|
||||
currentFill,
|
||||
selectedEntity,
|
||||
lastCursorPos,
|
||||
@ -315,7 +315,6 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
|
||||
);
|
||||
}, [
|
||||
asPreview,
|
||||
canvasV2State.tool,
|
||||
currentFill,
|
||||
isDrawing,
|
||||
isMouseDown,
|
||||
@ -324,6 +323,7 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
|
||||
renderers,
|
||||
selectedEntity,
|
||||
stage,
|
||||
tool,
|
||||
]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
@ -334,8 +334,8 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
|
||||
log.trace('Rendering bbox preview');
|
||||
renderers.renderBboxPreview(
|
||||
stage,
|
||||
canvasV2State.bbox,
|
||||
canvasV2State.tool.selected,
|
||||
bbox,
|
||||
tool.selected,
|
||||
$bbox.get,
|
||||
onBboxTransformed,
|
||||
$shift.get,
|
||||
@ -343,31 +343,31 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
|
||||
$meta.get,
|
||||
$alt.get
|
||||
);
|
||||
}, [asPreview, canvasV2State.bbox, canvasV2State.tool.selected, onBboxTransformed, renderers, stage]);
|
||||
}, [asPreview, bbox, onBboxTransformed, renderers, stage, tool.selected]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
log.trace('Rendering layers');
|
||||
renderers.renderLayers(
|
||||
stage,
|
||||
canvasV2State.layers,
|
||||
canvasV2State.controlAdapters,
|
||||
canvasV2State.regions,
|
||||
canvasV2State.maskFillOpacity,
|
||||
canvasV2State.tool.selected,
|
||||
layers,
|
||||
controlAdapters,
|
||||
regions,
|
||||
maskFillOpacity,
|
||||
tool.selected,
|
||||
selectedEntity,
|
||||
getImageDTO,
|
||||
onPosChanged
|
||||
);
|
||||
}, [
|
||||
stage,
|
||||
renderers,
|
||||
controlAdapters,
|
||||
layers,
|
||||
maskFillOpacity,
|
||||
onPosChanged,
|
||||
canvasV2State.tool.selected,
|
||||
regions,
|
||||
renderers,
|
||||
selectedEntity,
|
||||
canvasV2State.layers,
|
||||
canvasV2State.controlAdapters,
|
||||
canvasV2State.regions,
|
||||
canvasV2State.maskFillOpacity,
|
||||
stage,
|
||||
tool.selected,
|
||||
]);
|
||||
|
||||
// useLayoutEffect(() => {
|
||||
|
@ -21,13 +21,6 @@ import { DEFAULT_RGBA_COLOR } from './types';
|
||||
const initialState: CanvasV2State = {
|
||||
_version: 3,
|
||||
selectedEntityIdentifier: null,
|
||||
prompts: {
|
||||
positivePrompt: '',
|
||||
negativePrompt: '',
|
||||
positivePrompt2: '',
|
||||
negativePrompt2: '',
|
||||
shouldConcatPrompts: true,
|
||||
},
|
||||
tool: {
|
||||
selected: 'bbox',
|
||||
selectedBuffer: null,
|
||||
@ -40,7 +33,7 @@ const initialState: CanvasV2State = {
|
||||
width: 50,
|
||||
},
|
||||
},
|
||||
size: {
|
||||
document: {
|
||||
width: 512,
|
||||
height: 512,
|
||||
aspectRatio: deepClone(initialAspectRatioState),
|
||||
@ -66,41 +59,26 @@ export const canvasV2Slice = createSlice({
|
||||
...ipAdaptersReducers,
|
||||
...controlAdaptersReducers,
|
||||
...regionsReducers,
|
||||
positivePromptChanged: (state, action: PayloadAction<string>) => {
|
||||
state.prompts.positivePrompt = action.payload;
|
||||
},
|
||||
negativePromptChanged: (state, action: PayloadAction<string>) => {
|
||||
state.prompts.negativePrompt = action.payload;
|
||||
},
|
||||
positivePrompt2Changed: (state, action: PayloadAction<string>) => {
|
||||
state.prompts.positivePrompt2 = action.payload;
|
||||
},
|
||||
negativePrompt2Changed: (state, action: PayloadAction<string>) => {
|
||||
state.prompts.negativePrompt2 = action.payload;
|
||||
},
|
||||
shouldConcatPromptsChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.prompts.shouldConcatPrompts = action.payload;
|
||||
},
|
||||
widthChanged: (state, action: PayloadAction<{ width: number; updateAspectRatio?: boolean; clamp?: boolean }>) => {
|
||||
const { width, updateAspectRatio, clamp } = action.payload;
|
||||
state.size.width = clamp ? Math.max(roundDownToMultiple(width, 8), 64) : width;
|
||||
state.document.width = clamp ? Math.max(roundDownToMultiple(width, 8), 64) : width;
|
||||
if (updateAspectRatio) {
|
||||
state.size.aspectRatio.value = state.size.width / state.size.height;
|
||||
state.size.aspectRatio.id = 'Free';
|
||||
state.size.aspectRatio.isLocked = false;
|
||||
state.document.aspectRatio.value = state.document.width / state.document.height;
|
||||
state.document.aspectRatio.id = 'Free';
|
||||
state.document.aspectRatio.isLocked = false;
|
||||
}
|
||||
},
|
||||
heightChanged: (state, action: PayloadAction<{ height: number; updateAspectRatio?: boolean; clamp?: boolean }>) => {
|
||||
const { height, updateAspectRatio, clamp } = action.payload;
|
||||
state.size.height = clamp ? Math.max(roundDownToMultiple(height, 8), 64) : height;
|
||||
state.document.height = clamp ? Math.max(roundDownToMultiple(height, 8), 64) : height;
|
||||
if (updateAspectRatio) {
|
||||
state.size.aspectRatio.value = state.size.width / state.size.height;
|
||||
state.size.aspectRatio.id = 'Free';
|
||||
state.size.aspectRatio.isLocked = false;
|
||||
state.document.aspectRatio.value = state.document.width / state.document.height;
|
||||
state.document.aspectRatio.id = 'Free';
|
||||
state.document.aspectRatio.isLocked = false;
|
||||
}
|
||||
},
|
||||
aspectRatioChanged: (state, action: PayloadAction<AspectRatioState>) => {
|
||||
state.size.aspectRatio = action.payload;
|
||||
state.document.aspectRatio = action.payload;
|
||||
},
|
||||
bboxChanged: (state, action: PayloadAction<IRect>) => {
|
||||
state.bbox = action.payload;
|
||||
@ -144,22 +122,17 @@ export const canvasV2Slice = createSlice({
|
||||
return;
|
||||
}
|
||||
const optimalDimension = getOptimalDimension(newModel);
|
||||
if (getIsSizeOptimal(state.size.width, state.size.height, optimalDimension)) {
|
||||
if (getIsSizeOptimal(state.document.width, state.document.height, optimalDimension)) {
|
||||
return;
|
||||
}
|
||||
const { width, height } = calculateNewSize(state.size.aspectRatio.value, optimalDimension * optimalDimension);
|
||||
state.size.width = width;
|
||||
state.size.height = height;
|
||||
const { width, height } = calculateNewSize(state.document.aspectRatio.value, optimalDimension * optimalDimension);
|
||||
state.document.width = width;
|
||||
state.document.height = height;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
positivePromptChanged,
|
||||
negativePromptChanged,
|
||||
positivePrompt2Changed,
|
||||
negativePrompt2Changed,
|
||||
shouldConcatPromptsChanged,
|
||||
widthChanged,
|
||||
heightChanged,
|
||||
aspectRatioChanged,
|
||||
|
@ -3,10 +3,6 @@ import { zModelIdentifierField } from 'features/nodes/types/common';
|
||||
import type { AspectRatioState } from 'features/parameters/components/ImageSize/types';
|
||||
import type {
|
||||
ParameterHeight,
|
||||
ParameterNegativePrompt,
|
||||
ParameterNegativeStylePromptSDXL,
|
||||
ParameterPositivePrompt,
|
||||
ParameterPositiveStylePromptSDXL,
|
||||
ParameterWidth,
|
||||
} from 'features/parameters/types/parameterSchemas';
|
||||
import {
|
||||
@ -758,13 +754,6 @@ export type CanvasEntityIdentifier = Pick<CanvasEntity, 'id' | 'type'>;
|
||||
export type CanvasV2State = {
|
||||
_version: 3;
|
||||
selectedEntityIdentifier: CanvasEntityIdentifier | null;
|
||||
prompts: {
|
||||
positivePrompt: ParameterPositivePrompt;
|
||||
negativePrompt: ParameterNegativePrompt;
|
||||
positivePrompt2: ParameterPositiveStylePromptSDXL;
|
||||
negativePrompt2: ParameterNegativeStylePromptSDXL;
|
||||
shouldConcatPrompts: boolean;
|
||||
};
|
||||
tool: {
|
||||
selected: Tool;
|
||||
selectedBuffer: Tool | null;
|
||||
@ -777,7 +766,7 @@ export type CanvasV2State = {
|
||||
};
|
||||
fill: RgbaColor;
|
||||
};
|
||||
size: {
|
||||
document: {
|
||||
width: ParameterWidth;
|
||||
height: ParameterHeight;
|
||||
aspectRatio: AspectRatioState;
|
||||
|
@ -421,7 +421,7 @@ const addInitialImageLayerToGraph = (
|
||||
) => {
|
||||
const { vaePrecision } = state.generation;
|
||||
const { refinerModel, refinerStart } = state.sdxl;
|
||||
const { width, height } = state.canvasV2.size;
|
||||
const { width, height } = state.canvasV2.document;
|
||||
assert(layer.isEnabled, 'Initial image layer is not enabled');
|
||||
assert(layer.image, 'Initial image layer has no image');
|
||||
|
||||
@ -568,7 +568,7 @@ const buildControlImage = (
|
||||
const getRGLayerBlobs = async (layerIds?: string[], preview: boolean = false): Promise<Record<string, Blob>> => {
|
||||
const state = getStore().getState();
|
||||
const { layers } = state.canvasV2;
|
||||
const { width, height } = state.canvasV2.size;
|
||||
const { width, height } = state.canvasV2.document;
|
||||
const reduxLayers = layers.filter(isRegionalGuidanceLayer);
|
||||
const container = document.createElement('div');
|
||||
const stage = new Konva.Stage({ container, width, height });
|
||||
|
@ -74,7 +74,7 @@ export const addHRF = (
|
||||
vaeSource: Invocation<'vae_loader'> | Invocation<'main_model_loader'> | Invocation<'seamless'>
|
||||
): Invocation<'l2i'> => {
|
||||
const { hrfStrength, hrfEnabled, hrfMethod } = state.hrf;
|
||||
const { width, height } = state.canvasV2.size;
|
||||
const { width, height } = state.canvasV2.document;
|
||||
const optimalDimension = selectOptimalDimension(state);
|
||||
const { newWidth: hrfWidth, newHeight: hrfHeight } = calculateHrfRes(optimalDimension, width, height);
|
||||
|
||||
|
@ -40,7 +40,7 @@ export const buildGenerationTabGraph = async (state: RootState): Promise<GraphTy
|
||||
seed,
|
||||
vae,
|
||||
} = state.generation;
|
||||
const { width, height } = state.controlLayers.present.size;
|
||||
const { width, height } = state.canvasV2.document;
|
||||
|
||||
assert(model, 'No model found in state');
|
||||
|
||||
|
@ -36,7 +36,7 @@ export const buildGenerationTabSDXLGraph = async (state: RootState): Promise<Non
|
||||
vaePrecision,
|
||||
vae,
|
||||
} = state.generation;
|
||||
const { width, height } = state.controlLayers.present.size;
|
||||
const { width, height } = state.canvasV2.document;
|
||||
|
||||
const { refinerModel, refinerStart } = state.sdxl;
|
||||
|
||||
|
@ -22,7 +22,7 @@ export const getPresetModifiedPrompts = (
|
||||
state: RootState
|
||||
): { positivePrompt: string; negativePrompt: string; positiveStylePrompt?: string; negativeStylePrompt?: string } => {
|
||||
const { positivePrompt, negativePrompt, positivePrompt2, negativePrompt2, shouldConcatPrompts } =
|
||||
state.canvasV2.prompts;
|
||||
state.generation;
|
||||
const { activeStylePresetId } = state.stylePreset;
|
||||
|
||||
if (activeStylePresetId) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Box, Textarea } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { negativePromptChanged } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { PromptLabel } from 'features/parameters/components/Prompts/PromptLabel';
|
||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||
import { ViewModePrompt } from 'features/parameters/components/Prompts/ViewModePrompt';
|
||||
import { negativePromptChanged } from 'features/parameters/store/generationSlice';
|
||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||
import { usePrompt } from 'features/prompt/usePrompt';
|
||||
@ -13,7 +13,7 @@ import { useListStylePresetsQuery } from 'services/api/endpoints/stylePresets';
|
||||
|
||||
export const ParamNegativePrompt = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const prompt = useAppSelector((s) => s.canvasV2.prompts.negativePrompt);
|
||||
const prompt = useAppSelector((s) => s.generation.negativePrompt);
|
||||
const viewMode = useAppSelector((s) => s.stylePreset.viewMode);
|
||||
const activeStylePresetId = useAppSelector((s) => s.stylePreset.activeStylePresetId);
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Box, Textarea } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { positivePromptChanged } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { ShowDynamicPromptsPreviewButton } from 'features/dynamicPrompts/components/ShowDynamicPromptsPreviewButton';
|
||||
import { PromptLabel } from 'features/parameters/components/Prompts/PromptLabel';
|
||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||
import { ViewModePrompt } from 'features/parameters/components/Prompts/ViewModePrompt';
|
||||
import { positivePromptChanged } from 'features/parameters/store/generationSlice';
|
||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||
import { usePrompt } from 'features/prompt/usePrompt';
|
||||
@ -17,7 +17,7 @@ import { useListStylePresetsQuery } from 'services/api/endpoints/stylePresets';
|
||||
|
||||
export const ParamPositivePrompt = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const prompt = useAppSelector((s) => s.canvasV2.positivePrompt);
|
||||
const prompt = useAppSelector((s) => s.generation.positivePrompt);
|
||||
const baseModel = useAppSelector((s) => s.generation.model)?.base;
|
||||
const viewMode = useAppSelector((s) => s.stylePreset.viewMode);
|
||||
const activeStylePresetId = useAppSelector((s) => s.stylePreset.activeStylePresetId);
|
||||
|
@ -24,14 +24,8 @@ const initialGenerationState: GenerationState = {
|
||||
cfgScale: 7.5,
|
||||
cfgRescaleMultiplier: 0,
|
||||
img2imgStrength: 0.75,
|
||||
infillMethod: 'patchmatch',
|
||||
iterations: 1,
|
||||
scheduler: 'euler',
|
||||
maskBlur: 16,
|
||||
maskBlurMethod: 'box',
|
||||
canvasCoherenceMode: 'Gaussian Blur',
|
||||
canvasCoherenceMinDenoise: 0,
|
||||
canvasCoherenceEdgeSize: 16,
|
||||
seed: 0,
|
||||
shouldRandomizeSeed: true,
|
||||
steps: 50,
|
||||
@ -43,6 +37,12 @@ const initialGenerationState: GenerationState = {
|
||||
clipSkip: 0,
|
||||
shouldUseCpuNoise: true,
|
||||
shouldShowAdvancedOptions: false,
|
||||
maskBlur: 16,
|
||||
maskBlurMethod: 'box',
|
||||
canvasCoherenceMode: 'Gaussian Blur',
|
||||
canvasCoherenceMinDenoise: 0,
|
||||
canvasCoherenceEdgeSize: 16,
|
||||
infillMethod: 'patchmatch',
|
||||
infillTileSize: 32,
|
||||
infillPatchmatchDownscaleSize: 1,
|
||||
infillMosaicTileWidth: 64,
|
||||
@ -50,6 +50,11 @@ const initialGenerationState: GenerationState = {
|
||||
infillMosaicMinColor: { r: 0, g: 0, b: 0, a: 1 },
|
||||
infillMosaicMaxColor: { r: 255, g: 255, b: 255, a: 1 },
|
||||
infillColorValue: { r: 0, g: 0, b: 0, a: 1 },
|
||||
positivePrompt: '',
|
||||
negativePrompt: '',
|
||||
positivePrompt2: '',
|
||||
negativePrompt2: '',
|
||||
shouldConcatPrompts: true,
|
||||
};
|
||||
|
||||
export const generationSlice = createSlice({
|
||||
@ -166,6 +171,21 @@ export const generationSlice = createSlice({
|
||||
setInfillColorValue: (state, action: PayloadAction<RgbaColor>) => {
|
||||
state.infillColorValue = action.payload;
|
||||
},
|
||||
positivePromptChanged: (state, action: PayloadAction<string>) => {
|
||||
state.positivePrompt = action.payload;
|
||||
},
|
||||
negativePromptChanged: (state, action: PayloadAction<string>) => {
|
||||
state.negativePrompt = action.payload;
|
||||
},
|
||||
positivePrompt2Changed: (state, action: PayloadAction<string>) => {
|
||||
state.positivePrompt2 = action.payload;
|
||||
},
|
||||
negativePrompt2Changed: (state, action: PayloadAction<string>) => {
|
||||
state.negativePrompt2 = action.payload;
|
||||
},
|
||||
shouldConcatPromptsChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldConcatPrompts = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(configChanged, (state, action) => {
|
||||
@ -210,6 +230,11 @@ export const {
|
||||
setInfillMosaicMinColor,
|
||||
setInfillMosaicMaxColor,
|
||||
setInfillColorValue,
|
||||
positivePromptChanged,
|
||||
negativePromptChanged,
|
||||
positivePrompt2Changed,
|
||||
negativePrompt2Changed,
|
||||
shouldConcatPromptsChanged,
|
||||
} = generationSlice.actions;
|
||||
|
||||
export const { selectOptimalDimension } = generationSlice.selectors;
|
||||
|
@ -5,6 +5,10 @@ import type {
|
||||
ParameterCFGScale,
|
||||
ParameterMaskBlurMethod,
|
||||
ParameterModel,
|
||||
ParameterNegativePrompt,
|
||||
ParameterNegativeStylePromptSDXL,
|
||||
ParameterPositivePrompt,
|
||||
ParameterPositiveStylePromptSDXL,
|
||||
ParameterPrecision,
|
||||
ParameterScheduler,
|
||||
ParameterSeed,
|
||||
@ -45,6 +49,11 @@ export interface GenerationState {
|
||||
infillMosaicMinColor: RgbaColor;
|
||||
infillMosaicMaxColor: RgbaColor;
|
||||
infillColorValue: RgbaColor;
|
||||
positivePrompt: ParameterPositivePrompt;
|
||||
negativePrompt: ParameterNegativePrompt;
|
||||
positivePrompt2: ParameterPositiveStylePromptSDXL;
|
||||
negativePrompt2: ParameterNegativeStylePromptSDXL;
|
||||
shouldConcatPrompts: boolean;
|
||||
}
|
||||
|
||||
export type PayloadActionWithOptimalDimension<T = void> = PayloadAction<T, string, { optimalDimension: number }>;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Box, Textarea } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { negativePrompt2Changed } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { PromptLabel } from 'features/parameters/components/Prompts/PromptLabel';
|
||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||
import { negativePrompt2Changed } from 'features/parameters/store/generationSlice';
|
||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||
import { usePrompt } from 'features/prompt/usePrompt';
|
||||
@ -12,7 +12,7 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ParamSDXLNegativeStylePrompt = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const prompt = useAppSelector((s) => s.canvasV2.negativePrompt2);
|
||||
const prompt = useAppSelector((s) => s.generation.negativePrompt2);
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const { t } = useTranslation();
|
||||
const handleChange = useCallback(
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Box, Textarea } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { positivePrompt2Changed } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { PromptLabel } from 'features/parameters/components/Prompts/PromptLabel';
|
||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||
import { positivePrompt2Changed } from 'features/parameters/store/generationSlice';
|
||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||
import { usePrompt } from 'features/prompt/usePrompt';
|
||||
@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ParamSDXLPositiveStylePrompt = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const prompt = useAppSelector((s) => s.canvasV2.positivePrompt2);
|
||||
const prompt = useAppSelector((s) => s.generation.positivePrompt2);
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
const { t } = useTranslation();
|
||||
const handleChange = useCallback(
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { shouldConcatPromptsChanged } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { shouldConcatPromptsChanged } from 'features/parameters/store/generationSlice';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiLinkSimpleBold, PiLinkSimpleBreakBold } from 'react-icons/pi';
|
||||
|
||||
export const SDXLConcatButton = memo(() => {
|
||||
const shouldConcatPrompts = useAppSelector((s) => s.canvasV2.shouldConcatPrompts);
|
||||
const shouldConcatPrompts = useAppSelector((s) => s.generation.shouldConcatPrompts);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
@ -29,7 +29,7 @@ const selector = createMemoizedSelector(
|
||||
const badges: string[] = [];
|
||||
const isSDXL = model?.base === 'sdxl';
|
||||
|
||||
const { aspectRatio, width, height } = canvasV2.size;
|
||||
const { aspectRatio, width, height } = canvasV2.document;
|
||||
badges.push(`${width}×${height}`);
|
||||
badges.push(aspectRatio.id);
|
||||
|
||||
|
@ -9,9 +9,9 @@ import { memo, useCallback } from 'react';
|
||||
|
||||
export const ImageSizeLinear = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const width = useAppSelector((s) => s.canvasV2.size.width);
|
||||
const height = useAppSelector((s) => s.canvasV2.size.height);
|
||||
const aspectRatioState = useAppSelector((s) => s.canvasV2.size.aspectRatio);
|
||||
const width = useAppSelector((s) => s.canvasV2.document.width);
|
||||
const height = useAppSelector((s) => s.canvasV2.document.height);
|
||||
const aspectRatioState = useAppSelector((s) => s.canvasV2.document.aspectRatio);
|
||||
|
||||
const onChangeWidth = useCallback(
|
||||
(width: number) => {
|
||||
|
Loading…
Reference in New Issue
Block a user