diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts index ca26a0567f..fb908fa601 100644 --- a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts +++ b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts @@ -235,10 +235,18 @@ export const canvasSlice = createSlice({ state.boundingBoxDimensions.width, state.boundingBoxDimensions.height, ]; + const [currScaledWidth, currScaledHeight] = [ + state.scaledBoundingBoxDimensions.width, + state.scaledBoundingBoxDimensions.height, + ]; state.boundingBoxDimensions = { width: currHeight, height: currWidth, }; + state.scaledBoundingBoxDimensions = { + width: currScaledHeight, + height: currScaledWidth, + }; }, setBoundingBoxCoordinates: (state, action: PayloadAction) => { state.boundingBoxCoordinates = floorCoordinates(action.payload); @@ -788,6 +796,10 @@ export const canvasSlice = createSlice({ state.boundingBoxDimensions.width / ratio, 64 ); + state.scaledBoundingBoxDimensions.height = roundToMultiple( + state.scaledBoundingBoxDimensions.width / ratio, + 64 + ); } }); }, diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledHeight.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledHeight.tsx index 7dae01bb91..6d0ac52b2f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledHeight.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledHeight.tsx @@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider from 'common/components/IAISlider'; +import { roundToMultiple } from 'common/util/roundDownToMultiple'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { setScaledBoundingBoxDimensions } from 'features/canvas/store/canvasSlice'; import { generationSelector } from 'features/parameters/store/generationSelectors'; @@ -12,12 +13,13 @@ const selector = createSelector( [generationSelector, canvasSelector], (generation, canvas) => { const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = canvas; - const { model } = generation; + const { model, aspectRatio } = generation; return { model, scaledBoundingBoxDimensions, isManual: boundingBoxScaleMethod === 'manual', + aspectRatio, }; }, defaultSelectorOptions @@ -25,7 +27,7 @@ const selector = createSelector( const ParamScaledHeight = () => { const dispatch = useAppDispatch(); - const { model, isManual, scaledBoundingBoxDimensions } = + const { model, isManual, scaledBoundingBoxDimensions, aspectRatio } = useAppSelector(selector); const initial = ['sdxl', 'sdxl-refiner'].includes(model?.base_model as string) @@ -35,19 +37,33 @@ const ParamScaledHeight = () => { const { t } = useTranslation(); const handleChangeScaledHeight = (v: number) => { + let newWidth = scaledBoundingBoxDimensions.width; + const newHeight = Math.floor(v); + + if (aspectRatio) { + newWidth = roundToMultiple(newHeight * aspectRatio, 64); + } + dispatch( setScaledBoundingBoxDimensions({ - ...scaledBoundingBoxDimensions, - height: Math.floor(v), + width: newWidth, + height: newHeight, }) ); }; const handleResetScaledHeight = () => { + let resetWidth = scaledBoundingBoxDimensions.width; + const resetHeight = Math.floor(initial); + + if (aspectRatio) { + resetWidth = roundToMultiple(resetHeight * aspectRatio, 64); + } + dispatch( setScaledBoundingBoxDimensions({ - ...scaledBoundingBoxDimensions, - height: Math.floor(initial), + width: resetWidth, + height: resetHeight, }) ); }; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledWidth.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledWidth.tsx index 0eda5a122c..71a8615d74 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledWidth.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledWidth.tsx @@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider from 'common/components/IAISlider'; +import { roundToMultiple } from 'common/util/roundDownToMultiple'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { setScaledBoundingBoxDimensions } from 'features/canvas/store/canvasSlice'; import { generationSelector } from 'features/parameters/store/generationSelectors'; @@ -12,11 +13,12 @@ const selector = createSelector( [canvasSelector, generationSelector], (canvas, generation) => { const { boundingBoxScaleMethod, scaledBoundingBoxDimensions } = canvas; - const { model } = generation; + const { model, aspectRatio } = generation; return { model, scaledBoundingBoxDimensions, + aspectRatio, isManual: boundingBoxScaleMethod === 'manual', }; }, @@ -25,7 +27,7 @@ const selector = createSelector( const ParamScaledWidth = () => { const dispatch = useAppDispatch(); - const { model, isManual, scaledBoundingBoxDimensions } = + const { model, isManual, scaledBoundingBoxDimensions, aspectRatio } = useAppSelector(selector); const initial = ['sdxl', 'sdxl-refiner'].includes(model?.base_model as string) @@ -35,19 +37,33 @@ const ParamScaledWidth = () => { const { t } = useTranslation(); const handleChangeScaledWidth = (v: number) => { + const newWidth = Math.floor(v); + let newHeight = scaledBoundingBoxDimensions.height; + + if (aspectRatio) { + newHeight = roundToMultiple(newWidth / aspectRatio, 64); + } + dispatch( setScaledBoundingBoxDimensions({ - ...scaledBoundingBoxDimensions, - width: Math.floor(v), + width: newWidth, + height: newHeight, }) ); }; const handleResetScaledWidth = () => { + const resetWidth = Math.floor(initial); + let resetHeight = scaledBoundingBoxDimensions.height; + + if (aspectRatio) { + resetHeight = roundToMultiple(resetWidth / aspectRatio, 64); + } + dispatch( setScaledBoundingBoxDimensions({ - ...scaledBoundingBoxDimensions, - width: Math.floor(initial), + width: resetWidth, + height: resetHeight, }) ); };