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