mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
[Code Splitting] Bounding Box Options
Isolated all bounding box components to trigger unnecessary re-renders. Still need to fix bounding box triggering re-renders on the control panel inside the canvas itself. But the options panel should be a good to go with this change.
This commit is contained in:
parent
2e562742c1
commit
868e4b2db8
File diff suppressed because one or more lines are too long
2
frontend/dist/index.html
vendored
2
frontend/dist/index.html
vendored
@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>InvokeAI - A Stable Diffusion Toolkit</title>
|
||||
<link rel="shortcut icon" type="icon" href="./assets/favicon.0d253ced.ico" />
|
||||
<script type="module" crossorigin src="./assets/index.f51a2644.js"></script>
|
||||
<script type="module" crossorigin src="./assets/index.9ad2f384.js"></script>
|
||||
<link rel="stylesheet" href="./assets/index.14c578ee.css">
|
||||
</head>
|
||||
|
||||
|
@ -1,209 +0,0 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { BiHide, BiReset, BiShow } from 'react-icons/bi';
|
||||
|
||||
import {
|
||||
RootState,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from '../../../../app/store';
|
||||
import IAICheckbox from '../../../../common/components/IAICheckbox';
|
||||
import IAIIconButton from '../../../../common/components/IAIIconButton';
|
||||
|
||||
import IAINumberInput from '../../../../common/components/IAINumberInput';
|
||||
import IAISlider from '../../../../common/components/IAISlider';
|
||||
import { roundDownToMultiple } from '../../../../common/util/roundDownToMultiple';
|
||||
import {
|
||||
InpaintingState,
|
||||
setBoundingBoxDimensions,
|
||||
setShouldLockBoundingBox,
|
||||
setShouldShowBoundingBox,
|
||||
setShouldShowBoundingBoxFill,
|
||||
} from '../../../tabs/Inpainting/inpaintingSlice';
|
||||
|
||||
const boundingBoxDimensionsSelector = createSelector(
|
||||
(state: RootState) => state.inpainting,
|
||||
(inpainting: InpaintingState) => {
|
||||
const {
|
||||
canvasDimensions,
|
||||
boundingBoxDimensions,
|
||||
shouldShowBoundingBox,
|
||||
shouldShowBoundingBoxFill,
|
||||
shouldLockBoundingBox,
|
||||
} = inpainting;
|
||||
return {
|
||||
canvasDimensions,
|
||||
boundingBoxDimensions,
|
||||
shouldShowBoundingBox,
|
||||
shouldShowBoundingBoxFill,
|
||||
shouldLockBoundingBox,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: _.isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const BoundingBoxSettings = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const {
|
||||
canvasDimensions,
|
||||
boundingBoxDimensions,
|
||||
shouldShowBoundingBox,
|
||||
shouldShowBoundingBoxFill,
|
||||
shouldLockBoundingBox,
|
||||
} = useAppSelector(boundingBoxDimensionsSelector);
|
||||
|
||||
const handleChangeBoundingBoxWidth = (v: number) => {
|
||||
dispatch(
|
||||
setBoundingBoxDimensions({
|
||||
...boundingBoxDimensions,
|
||||
width: Math.floor(v),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleChangeBoundingBoxHeight = (v: number) => {
|
||||
dispatch(
|
||||
setBoundingBoxDimensions({
|
||||
...boundingBoxDimensions,
|
||||
height: Math.floor(v),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleChangeShouldShowBoundingBoxFill = () => {
|
||||
dispatch(setShouldShowBoundingBoxFill(!shouldShowBoundingBoxFill));
|
||||
};
|
||||
|
||||
const handleChangeShouldLockBoundingBox = () => {
|
||||
dispatch(setShouldLockBoundingBox(!shouldLockBoundingBox));
|
||||
};
|
||||
|
||||
const handleResetWidth = () => {
|
||||
dispatch(
|
||||
setBoundingBoxDimensions({
|
||||
...boundingBoxDimensions,
|
||||
width: Math.floor(canvasDimensions.width),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleResetHeight = () => {
|
||||
dispatch(
|
||||
setBoundingBoxDimensions({
|
||||
...boundingBoxDimensions,
|
||||
height: Math.floor(canvasDimensions.height),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleShowBoundingBox = () =>
|
||||
dispatch(setShouldShowBoundingBox(!shouldShowBoundingBox));
|
||||
|
||||
return (
|
||||
<div className="inpainting-bounding-box-settings">
|
||||
<div className="inpainting-bounding-box-header">
|
||||
<p>Inpaint Box</p>
|
||||
<IAIIconButton
|
||||
aria-label="Toggle Bounding Box Visibility"
|
||||
icon={
|
||||
shouldShowBoundingBox ? <BiShow size={22} /> : <BiHide size={22} />
|
||||
}
|
||||
onClick={handleShowBoundingBox}
|
||||
background={'none'}
|
||||
padding={0}
|
||||
/>
|
||||
</div>
|
||||
<div className="inpainting-bounding-box-settings-items">
|
||||
<div className="inpainting-bounding-box-dimensions-slider-numberinput">
|
||||
<IAISlider
|
||||
isDisabled={shouldLockBoundingBox}
|
||||
label="Box W"
|
||||
min={64}
|
||||
max={roundDownToMultiple(canvasDimensions.width, 64)}
|
||||
step={64}
|
||||
value={boundingBoxDimensions.width}
|
||||
onChange={handleChangeBoundingBoxWidth}
|
||||
width={'5rem'}
|
||||
/>
|
||||
<IAINumberInput
|
||||
isDisabled={shouldLockBoundingBox}
|
||||
value={boundingBoxDimensions.width}
|
||||
onChange={handleChangeBoundingBoxWidth}
|
||||
min={64}
|
||||
max={roundDownToMultiple(canvasDimensions.width, 64)}
|
||||
step={64}
|
||||
width={'5rem'}
|
||||
/>
|
||||
<IAIIconButton
|
||||
size={'sm'}
|
||||
aria-label={'Reset Width'}
|
||||
tooltip={'Reset Width'}
|
||||
onClick={handleResetWidth}
|
||||
icon={<BiReset />}
|
||||
styleClass="inpainting-bounding-box-reset-icon-btn"
|
||||
isDisabled={
|
||||
shouldLockBoundingBox ||
|
||||
canvasDimensions.width === boundingBoxDimensions.width
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="inpainting-bounding-box-dimensions-slider-numberinput">
|
||||
<IAISlider
|
||||
isDisabled={shouldLockBoundingBox}
|
||||
label="Box H"
|
||||
min={64}
|
||||
max={roundDownToMultiple(canvasDimensions.height, 64)}
|
||||
step={64}
|
||||
value={boundingBoxDimensions.height}
|
||||
onChange={handleChangeBoundingBoxHeight}
|
||||
width={'5rem'}
|
||||
/>
|
||||
<IAINumberInput
|
||||
isDisabled={shouldLockBoundingBox}
|
||||
value={boundingBoxDimensions.height}
|
||||
onChange={handleChangeBoundingBoxHeight}
|
||||
min={64}
|
||||
max={roundDownToMultiple(canvasDimensions.height, 64)}
|
||||
step={64}
|
||||
padding="0"
|
||||
width={'5rem'}
|
||||
/>
|
||||
<IAIIconButton
|
||||
size={'sm'}
|
||||
aria-label={'Reset Height'}
|
||||
tooltip={'Reset Height'}
|
||||
onClick={handleResetHeight}
|
||||
icon={<BiReset />}
|
||||
styleClass="inpainting-bounding-box-reset-icon-btn"
|
||||
isDisabled={
|
||||
shouldLockBoundingBox ||
|
||||
canvasDimensions.height === boundingBoxDimensions.height
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Flex alignItems={'center'} justifyContent={'space-between'}>
|
||||
<IAICheckbox
|
||||
label="Darken Outside Box"
|
||||
isChecked={shouldShowBoundingBoxFill}
|
||||
onChange={handleChangeShouldShowBoundingBoxFill}
|
||||
styleClass="inpainting-bounding-box-darken"
|
||||
/>
|
||||
<IAICheckbox
|
||||
label="Lock Bounding Box"
|
||||
isChecked={shouldLockBoundingBox}
|
||||
onChange={handleChangeShouldLockBoundingBox}
|
||||
styleClass="inpainting-bounding-box-darken"
|
||||
/>
|
||||
</Flex>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BoundingBoxSettings;
|
@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
RootState,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from '../../../../../app/store';
|
||||
import IAICheckbox from '../../../../../common/components/IAICheckbox';
|
||||
import { setShouldShowBoundingBoxFill } from '../../../../tabs/Inpainting/inpaintingSlice';
|
||||
|
||||
export default function BoundingBoxDarkenOutside() {
|
||||
const dispatch = useAppDispatch();
|
||||
const shouldShowBoundingBoxFill = useAppSelector(
|
||||
(state: RootState) => state.inpainting.shouldShowBoundingBoxFill
|
||||
);
|
||||
|
||||
const handleChangeShouldShowBoundingBoxFill = () => {
|
||||
dispatch(setShouldShowBoundingBoxFill(!shouldShowBoundingBoxFill));
|
||||
};
|
||||
|
||||
return (
|
||||
<IAICheckbox
|
||||
label="Darken Outside Box"
|
||||
isChecked={shouldShowBoundingBoxFill}
|
||||
onChange={handleChangeShouldShowBoundingBoxFill}
|
||||
styleClass="inpainting-bounding-box-darken"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
import React from 'react';
|
||||
import IAISlider from '../../../../../common/components/IAISlider';
|
||||
import IAINumberInput from '../../../../../common/components/IAINumberInput';
|
||||
import IAIIconButton from '../../../../../common/components/IAIIconButton';
|
||||
import { BiReset } from 'react-icons/bi';
|
||||
|
||||
import {
|
||||
RootState,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from '../../../../../app/store';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
InpaintingState,
|
||||
setBoundingBoxDimensions,
|
||||
} from '../../../../tabs/Inpainting/inpaintingSlice';
|
||||
|
||||
import { roundDownToMultiple } from '../../../../../common/util/roundDownToMultiple';
|
||||
import _ from 'lodash';
|
||||
|
||||
const boundingBoxDimensionsSelector = createSelector(
|
||||
(state: RootState) => state.inpainting,
|
||||
(inpainting: InpaintingState) => {
|
||||
const { canvasDimensions, boundingBoxDimensions, shouldLockBoundingBox } =
|
||||
inpainting;
|
||||
return {
|
||||
canvasDimensions,
|
||||
boundingBoxDimensions,
|
||||
shouldLockBoundingBox,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: _.isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
type BoundingBoxDimensionSlidersType = {
|
||||
dimension: 'width' | 'height';
|
||||
};
|
||||
|
||||
export default function BoundingBoxDimensionSlider(
|
||||
props: BoundingBoxDimensionSlidersType
|
||||
) {
|
||||
const { dimension } = props;
|
||||
const dispatch = useAppDispatch();
|
||||
const { shouldLockBoundingBox, canvasDimensions, boundingBoxDimensions } =
|
||||
useAppSelector(boundingBoxDimensionsSelector);
|
||||
|
||||
const canvasDimension = canvasDimensions[dimension];
|
||||
const boundingBoxDimension = boundingBoxDimensions[dimension];
|
||||
|
||||
const handleBoundingBoxDimension = (v: number) => {
|
||||
if (dimension == 'width') {
|
||||
dispatch(
|
||||
setBoundingBoxDimensions({
|
||||
...boundingBoxDimensions,
|
||||
width: Math.floor(v),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (dimension == 'height') {
|
||||
dispatch(
|
||||
setBoundingBoxDimensions({
|
||||
...boundingBoxDimensions,
|
||||
height: Math.floor(v),
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const handleResetDimension = () => {
|
||||
if (dimension == 'width') {
|
||||
dispatch(
|
||||
setBoundingBoxDimensions({
|
||||
...boundingBoxDimensions,
|
||||
width: Math.floor(canvasDimension),
|
||||
})
|
||||
);
|
||||
}
|
||||
if (dimension == 'height') {
|
||||
dispatch(
|
||||
setBoundingBoxDimensions({
|
||||
...boundingBoxDimensions,
|
||||
height: Math.floor(canvasDimension),
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="inpainting-bounding-box-dimensions-slider-numberinput">
|
||||
<IAISlider
|
||||
isDisabled={shouldLockBoundingBox}
|
||||
label="Box H"
|
||||
min={64}
|
||||
max={roundDownToMultiple(canvasDimension, 64)}
|
||||
step={64}
|
||||
value={boundingBoxDimension}
|
||||
onChange={handleBoundingBoxDimension}
|
||||
width={'5rem'}
|
||||
/>
|
||||
<IAINumberInput
|
||||
isDisabled={shouldLockBoundingBox}
|
||||
value={boundingBoxDimension}
|
||||
onChange={handleBoundingBoxDimension}
|
||||
min={64}
|
||||
max={roundDownToMultiple(canvasDimension, 64)}
|
||||
step={64}
|
||||
padding="0"
|
||||
width={'5rem'}
|
||||
/>
|
||||
<IAIIconButton
|
||||
size={'sm'}
|
||||
aria-label={'Reset Height'}
|
||||
tooltip={'Reset Height'}
|
||||
onClick={handleResetDimension}
|
||||
icon={<BiReset />}
|
||||
styleClass="inpainting-bounding-box-reset-icon-btn"
|
||||
isDisabled={
|
||||
shouldLockBoundingBox || canvasDimension === boundingBoxDimension
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
RootState,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from '../../../../../app/store';
|
||||
import IAICheckbox from '../../../../../common/components/IAICheckbox';
|
||||
import { setShouldLockBoundingBox } from '../../../../tabs/Inpainting/inpaintingSlice';
|
||||
|
||||
export default function BoundingBoxLock() {
|
||||
const shouldLockBoundingBox = useAppSelector(
|
||||
(state: RootState) => state.inpainting.shouldLockBoundingBox
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleChangeShouldLockBoundingBox = () => {
|
||||
dispatch(setShouldLockBoundingBox(!shouldLockBoundingBox));
|
||||
};
|
||||
return (
|
||||
<IAICheckbox
|
||||
label="Lock Bounding Box"
|
||||
isChecked={shouldLockBoundingBox}
|
||||
onChange={handleChangeShouldLockBoundingBox}
|
||||
styleClass="inpainting-bounding-box-darken"
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import BoundingBoxDarkenOutside from './BoundingBoxDarkenOutside';
|
||||
import BoundingBoxDimensionSlider from './BoundingBoxDimensionSlider';
|
||||
import BoundingBoxLock from './BoundingBoxLock';
|
||||
import BoundingBoxVisibility from './BoundingBoxVisibility';
|
||||
|
||||
const BoundingBoxSettings = () => {
|
||||
return (
|
||||
<div className="inpainting-bounding-box-settings">
|
||||
<div className="inpainting-bounding-box-header">
|
||||
<p>Inpaint Box</p>
|
||||
<BoundingBoxVisibility />
|
||||
</div>
|
||||
<div className="inpainting-bounding-box-settings-items">
|
||||
<BoundingBoxDimensionSlider dimension="width" />
|
||||
<BoundingBoxDimensionSlider dimension="height" />
|
||||
<Flex alignItems={'center'} justifyContent={'space-between'}>
|
||||
<BoundingBoxDarkenOutside />
|
||||
<BoundingBoxLock />
|
||||
</Flex>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BoundingBoxSettings;
|
@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { BiHide, BiShow } from 'react-icons/bi';
|
||||
import {
|
||||
RootState,
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
} from '../../../../../app/store';
|
||||
import IAIIconButton from '../../../../../common/components/IAIIconButton';
|
||||
import { setShouldShowBoundingBox } from '../../../../tabs/Inpainting/inpaintingSlice';
|
||||
|
||||
export default function BoundingBoxVisibility() {
|
||||
const shouldShowBoundingBox = useAppSelector(
|
||||
(state: RootState) => state.inpainting.shouldShowBoundingBox
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleShowBoundingBox = () =>
|
||||
dispatch(setShouldShowBoundingBox(!shouldShowBoundingBox));
|
||||
return (
|
||||
<IAIIconButton
|
||||
aria-label="Toggle Bounding Box Visibility"
|
||||
icon={shouldShowBoundingBox ? <BiShow size={22} /> : <BiHide size={22} />}
|
||||
onClick={handleShowBoundingBox}
|
||||
background={'none'}
|
||||
padding={0}
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import BoundingBoxSettings from './BoundingBoxSettings';
|
||||
import BoundingBoxSettings from './BoundingBoxSettings/BoundingBoxSettings';
|
||||
import InpaintReplace from './InpaintReplace';
|
||||
import ClearBrushHistory from './ClearBrushHistory';
|
||||
|
||||
|
@ -170,7 +170,6 @@ const InvokeOptionsPanel = (props: Props) => {
|
||||
</h1>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,7 +23,7 @@
|
||||
@use '../features/options/MainOptions/MainOptions.scss';
|
||||
@use '../features/options/AccordionItems/AdvancedSettings.scss';
|
||||
@use '../features/options/AdvancedOptions/Upscale/UpscaleOptions.scss';
|
||||
@use '../features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.scss';
|
||||
@use '../features/options/AdvancedOptions/Inpainting/BoundingBoxSettings/BoundingBoxSettings.scss';
|
||||
@use '../features/system/ProgressBar.scss';
|
||||
|
||||
// gallery
|
||||
|
Loading…
Reference in New Issue
Block a user