mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): generalize mask fill, add to action bar
This commit is contained in:
parent
ac16fa65a3
commit
3001718f9f
@ -1676,7 +1676,7 @@
|
|||||||
"resetRegion": "Reset Region",
|
"resetRegion": "Reset Region",
|
||||||
"debugLayers": "Debug Layers",
|
"debugLayers": "Debug Layers",
|
||||||
"rectangle": "Rectangle",
|
"rectangle": "Rectangle",
|
||||||
"maskPreviewColor": "Mask Preview Color",
|
"maskFill": "Mask Fill",
|
||||||
"addPositivePrompt": "Add $t(common.positivePrompt)",
|
"addPositivePrompt": "Add $t(common.positivePrompt)",
|
||||||
"addNegativePrompt": "Add $t(common.negativePrompt)",
|
"addNegativePrompt": "Add $t(common.negativePrompt)",
|
||||||
"addIPAdapter": "Add $t(common.ipAdapter)",
|
"addIPAdapter": "Add $t(common.ipAdapter)",
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
import { Flex, Spacer } from '@invoke-ai/ui-library';
|
import { Flex, Spacer } from '@invoke-ai/ui-library';
|
||||||
import { EntityListActionBarAddLayerButton } from 'features/controlLayers/components/CanvasEntityList/EntityListActionBarAddLayerMenuButton';
|
import { EntityListActionBarAddLayerButton } from 'features/controlLayers/components/CanvasEntityList/EntityListActionBarAddLayerMenuButton';
|
||||||
import { EntityListActionBarDeleteButton } from 'features/controlLayers/components/CanvasEntityList/EntityListActionBarDeleteButton';
|
import { EntityListActionBarDeleteButton } from 'features/controlLayers/components/CanvasEntityList/EntityListActionBarDeleteButton';
|
||||||
|
import { EntityListActionBarSelectedEntityFill } from 'features/controlLayers/components/CanvasEntityList/EntityListActionBarSelectedEntityFill';
|
||||||
import { SelectedEntityOpacity } from 'features/controlLayers/components/CanvasEntityList/EntityListActionBarSelectedEntityOpacity';
|
import { SelectedEntityOpacity } from 'features/controlLayers/components/CanvasEntityList/EntityListActionBarSelectedEntityOpacity';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
|
|
||||||
export const EntityListActionBar = memo(() => {
|
export const EntityListActionBar = memo(() => {
|
||||||
return (
|
return (
|
||||||
<Flex w="full" py={1} px={1} gap={2}>
|
<Flex w="full" py={1} px={1} gap={2} alignItems="center">
|
||||||
<SelectedEntityOpacity />
|
<SelectedEntityOpacity />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
|
<EntityListActionBarSelectedEntityFill />
|
||||||
<EntityListActionBarAddLayerButton />
|
<EntityListActionBarAddLayerButton />
|
||||||
<EntityListActionBarDeleteButton />
|
<EntityListActionBarDeleteButton />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
import { Box, Flex, Popover, PopoverBody, PopoverContent, PopoverTrigger, Tooltip } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import RgbColorPicker from 'common/components/RgbColorPicker';
|
||||||
|
import { rgbColorToString } from 'common/util/colorCodeTransformers';
|
||||||
|
import { MaskFillStyle } from 'features/controlLayers/components/common/MaskFillStyle';
|
||||||
|
import { entityFillColorChanged, entityFillStyleChanged } from 'features/controlLayers/store/canvasSlice';
|
||||||
|
import { selectSelectedEntityFill, selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
|
||||||
|
import { type FillStyle, isMaskEntityIdentifier, type RgbColor } from 'features/controlLayers/store/types';
|
||||||
|
import { memo, useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
export const EntityListActionBarSelectedEntityFill = memo(() => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const selectedEntityIdentifier = useAppSelector(selectSelectedEntityIdentifier);
|
||||||
|
const fill = useAppSelector(selectSelectedEntityFill);
|
||||||
|
|
||||||
|
const onChangeFillColor = useCallback(
|
||||||
|
(color: RgbColor) => {
|
||||||
|
if (!selectedEntityIdentifier) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isMaskEntityIdentifier(selectedEntityIdentifier)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch(entityFillColorChanged({ entityIdentifier: selectedEntityIdentifier, color }));
|
||||||
|
},
|
||||||
|
[dispatch, selectedEntityIdentifier]
|
||||||
|
);
|
||||||
|
const onChangeFillStyle = useCallback(
|
||||||
|
(style: FillStyle) => {
|
||||||
|
if (!selectedEntityIdentifier) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isMaskEntityIdentifier(selectedEntityIdentifier)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch(entityFillStyleChanged({ entityIdentifier: selectedEntityIdentifier, style }));
|
||||||
|
},
|
||||||
|
[dispatch, selectedEntityIdentifier]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!selectedEntityIdentifier || !fill) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover isLazy>
|
||||||
|
<PopoverTrigger>
|
||||||
|
<Flex role="button" aria-label={t('controlLayers.maskFill')} tabIndex={-1} w={8} h={8}>
|
||||||
|
<Tooltip label={t('controlLayers.maskFill')}>
|
||||||
|
<Flex w="full" h="full" alignItems="center" justifyContent="center">
|
||||||
|
<Box borderRadius="full" w={6} h={6} borderWidth={1} bg={rgbColorToString(fill.color)} />
|
||||||
|
</Flex>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent>
|
||||||
|
<PopoverBody minH={64}>
|
||||||
|
<Flex flexDir="column" gap={4}>
|
||||||
|
<RgbColorPicker color={fill.color} onChange={onChangeFillColor} withNumberInput />
|
||||||
|
<MaskFillStyle style={fill.style} onChange={onChangeFillStyle} />
|
||||||
|
</Flex>
|
||||||
|
</PopoverBody>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
EntityListActionBarSelectedEntityFill.displayName = 'EntityListActionBarSelectedEntityFill';
|
@ -10,8 +10,6 @@ import { EntityIdentifierContext } from 'features/controlLayers/contexts/EntityI
|
|||||||
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
|
|
||||||
import { InpaintMaskMaskFillColorPicker } from './InpaintMaskMaskFillColorPicker';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
@ -28,7 +26,6 @@ export const InpaintMask = memo(({ id }: Props) => {
|
|||||||
<CanvasEntityEditableTitle />
|
<CanvasEntityEditableTitle />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<CanvasEntityIsLockedToggle />
|
<CanvasEntityIsLockedToggle />
|
||||||
<InpaintMaskMaskFillColorPicker />
|
|
||||||
<CanvasEntityEnabledToggle />
|
<CanvasEntityEnabledToggle />
|
||||||
</CanvasEntityHeader>
|
</CanvasEntityHeader>
|
||||||
</CanvasEntityContainer>
|
</CanvasEntityContainer>
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
import { Flex, Popover, PopoverBody, PopoverContent, PopoverTrigger } from '@invoke-ai/ui-library';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import RgbColorPicker from 'common/components/RgbColorPicker';
|
|
||||||
import { rgbColorToString } from 'common/util/colorCodeTransformers';
|
|
||||||
import { MaskFillStyle } from 'features/controlLayers/components/common/MaskFillStyle';
|
|
||||||
import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext';
|
|
||||||
import { inpaintMaskFillColorChanged, inpaintMaskFillStyleChanged } from 'features/controlLayers/store/canvasSlice';
|
|
||||||
import { selectCanvasSlice, selectEntityOrThrow } from 'features/controlLayers/store/selectors';
|
|
||||||
import type { FillStyle, RgbColor } from 'features/controlLayers/store/types';
|
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export const InpaintMaskMaskFillColorPicker = memo(() => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const entityIdentifier = useEntityIdentifierContext('inpaint_mask');
|
|
||||||
const selectFill = useMemo(
|
|
||||||
() => createSelector(selectCanvasSlice, (canvas) => selectEntityOrThrow(canvas, entityIdentifier).fill),
|
|
||||||
[entityIdentifier]
|
|
||||||
);
|
|
||||||
const fill = useAppSelector(selectFill);
|
|
||||||
|
|
||||||
const onChangeFillColor = useCallback(
|
|
||||||
(color: RgbColor) => {
|
|
||||||
dispatch(inpaintMaskFillColorChanged({ entityIdentifier, color }));
|
|
||||||
},
|
|
||||||
[dispatch, entityIdentifier]
|
|
||||||
);
|
|
||||||
const onChangeFillStyle = useCallback(
|
|
||||||
(style: FillStyle) => {
|
|
||||||
dispatch(inpaintMaskFillStyleChanged({ entityIdentifier, style }));
|
|
||||||
},
|
|
||||||
[dispatch, entityIdentifier]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<Popover isLazy>
|
|
||||||
<PopoverTrigger>
|
|
||||||
<Flex
|
|
||||||
role="button"
|
|
||||||
aria-label={t('controlLayers.maskPreviewColor')}
|
|
||||||
borderRadius="full"
|
|
||||||
borderWidth={1}
|
|
||||||
bg={rgbColorToString(fill.color)}
|
|
||||||
w="22px"
|
|
||||||
h="22px"
|
|
||||||
tabIndex={-1}
|
|
||||||
/>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent>
|
|
||||||
<PopoverBody minH={64}>
|
|
||||||
<Flex flexDir="column" gap={4}>
|
|
||||||
<RgbColorPicker color={fill.color} onChange={onChangeFillColor} withNumberInput />
|
|
||||||
<MaskFillStyle style={fill.style} onChange={onChangeFillStyle} />
|
|
||||||
</Flex>
|
|
||||||
</PopoverBody>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
InpaintMaskMaskFillColorPicker.displayName = 'InpaintMaskMaskFillColorPicker';
|
|
@ -12,8 +12,6 @@ import { EntityIdentifierContext } from 'features/controlLayers/contexts/EntityI
|
|||||||
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
|
|
||||||
import { RegionalGuidanceMaskFillColorPicker } from './RegionalGuidanceMaskFillColorPicker';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
@ -30,7 +28,6 @@ export const RegionalGuidance = memo(({ id }: Props) => {
|
|||||||
<CanvasEntityEditableTitle />
|
<CanvasEntityEditableTitle />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<RegionalGuidanceBadges />
|
<RegionalGuidanceBadges />
|
||||||
<RegionalGuidanceMaskFillColorPicker />
|
|
||||||
<CanvasEntityIsLockedToggle />
|
<CanvasEntityIsLockedToggle />
|
||||||
<CanvasEntityEnabledToggle />
|
<CanvasEntityEnabledToggle />
|
||||||
</CanvasEntityHeader>
|
</CanvasEntityHeader>
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
import { Flex, Popover, PopoverBody, PopoverContent, PopoverTrigger } from '@invoke-ai/ui-library';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import RgbColorPicker from 'common/components/RgbColorPicker';
|
|
||||||
import { rgbColorToString } from 'common/util/colorCodeTransformers';
|
|
||||||
import { MaskFillStyle } from 'features/controlLayers/components/common/MaskFillStyle';
|
|
||||||
import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext';
|
|
||||||
import { rgFillColorChanged, rgFillStyleChanged } from 'features/controlLayers/store/canvasSlice';
|
|
||||||
import { selectCanvasSlice, selectEntityOrThrow } from 'features/controlLayers/store/selectors';
|
|
||||||
import type { FillStyle, RgbColor } from 'features/controlLayers/store/types';
|
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
export const RegionalGuidanceMaskFillColorPicker = memo(() => {
|
|
||||||
const entityIdentifier = useEntityIdentifierContext('regional_guidance');
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const selectFill = useMemo(
|
|
||||||
() => createSelector(selectCanvasSlice, (canvas) => selectEntityOrThrow(canvas, entityIdentifier).fill),
|
|
||||||
[entityIdentifier]
|
|
||||||
);
|
|
||||||
const fill = useAppSelector(selectFill);
|
|
||||||
const onChangeFillColor = useCallback(
|
|
||||||
(color: RgbColor) => {
|
|
||||||
dispatch(rgFillColorChanged({ entityIdentifier, color }));
|
|
||||||
},
|
|
||||||
[dispatch, entityIdentifier]
|
|
||||||
);
|
|
||||||
const onChangeFillStyle = useCallback(
|
|
||||||
(style: FillStyle) => {
|
|
||||||
dispatch(rgFillStyleChanged({ entityIdentifier, style }));
|
|
||||||
},
|
|
||||||
[dispatch, entityIdentifier]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<Popover isLazy>
|
|
||||||
<PopoverTrigger>
|
|
||||||
<Flex
|
|
||||||
role="button"
|
|
||||||
aria-label={t('controlLayers.maskPreviewColor')}
|
|
||||||
borderRadius="full"
|
|
||||||
borderWidth={1}
|
|
||||||
bg={rgbColorToString(fill.color)}
|
|
||||||
w="22px"
|
|
||||||
h="22px"
|
|
||||||
tabIndex={-1}
|
|
||||||
/>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent>
|
|
||||||
<PopoverBody minH={64}>
|
|
||||||
<Flex flexDir="column" gap={4}>
|
|
||||||
<RgbColorPicker color={fill.color} onChange={onChangeFillColor} withNumberInput />
|
|
||||||
<MaskFillStyle style={fill.style} onChange={onChangeFillStyle} />
|
|
||||||
</Flex>
|
|
||||||
</PopoverBody>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
RegionalGuidanceMaskFillColorPicker.displayName = 'RegionalGuidanceMaskFillColorPicker';
|
|
@ -475,29 +475,6 @@ export const canvasSlice = createSlice({
|
|||||||
}
|
}
|
||||||
entity.negativePrompt = prompt;
|
entity.negativePrompt = prompt;
|
||||||
},
|
},
|
||||||
rgFillColorChanged: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<EntityIdentifierPayload<{ color: RgbColor }, 'regional_guidance'>>
|
|
||||||
) => {
|
|
||||||
const { entityIdentifier, color } = action.payload;
|
|
||||||
const entity = selectEntity(state, entityIdentifier);
|
|
||||||
if (!entity) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
entity.fill.color = color;
|
|
||||||
},
|
|
||||||
rgFillStyleChanged: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<EntityIdentifierPayload<{ style: FillStyle }, 'regional_guidance'>>
|
|
||||||
) => {
|
|
||||||
const { entityIdentifier, style } = action.payload;
|
|
||||||
const entity = selectEntity(state, entityIdentifier);
|
|
||||||
if (!entity) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
entity.fill.style = style;
|
|
||||||
},
|
|
||||||
|
|
||||||
rgAutoNegativeToggled: (state, action: PayloadAction<EntityIdentifierPayload<void, 'regional_guidance'>>) => {
|
rgAutoNegativeToggled: (state, action: PayloadAction<EntityIdentifierPayload<void, 'regional_guidance'>>) => {
|
||||||
const { entityIdentifier } = action.payload;
|
const { entityIdentifier } = action.payload;
|
||||||
const rg = selectEntity(state, entityIdentifier);
|
const rg = selectEntity(state, entityIdentifier);
|
||||||
@ -658,28 +635,6 @@ export const canvasSlice = createSlice({
|
|||||||
state.inpaintMasks.entities = [data];
|
state.inpaintMasks.entities = [data];
|
||||||
state.selectedEntityIdentifier = { type: 'inpaint_mask', id: data.id };
|
state.selectedEntityIdentifier = { type: 'inpaint_mask', id: data.id };
|
||||||
},
|
},
|
||||||
inpaintMaskFillColorChanged: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<EntityIdentifierPayload<{ color: RgbColor }, 'inpaint_mask'>>
|
|
||||||
) => {
|
|
||||||
const { color, entityIdentifier } = action.payload;
|
|
||||||
const entity = selectEntity(state, entityIdentifier);
|
|
||||||
if (!entity) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
entity.fill.color = color;
|
|
||||||
},
|
|
||||||
inpaintMaskFillStyleChanged: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<EntityIdentifierPayload<{ style: FillStyle }, 'inpaint_mask'>>
|
|
||||||
) => {
|
|
||||||
const { style, entityIdentifier } = action.payload;
|
|
||||||
const entity = selectEntity(state, entityIdentifier);
|
|
||||||
if (!entity) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
entity.fill.style = style;
|
|
||||||
},
|
|
||||||
//#region BBox
|
//#region BBox
|
||||||
bboxScaledSizeChanged: (state, action: PayloadAction<Partial<Dimensions>>) => {
|
bboxScaledSizeChanged: (state, action: PayloadAction<Partial<Dimensions>>) => {
|
||||||
state.bbox.scaledSize = { ...state.bbox.scaledSize, ...action.payload };
|
state.bbox.scaledSize = { ...state.bbox.scaledSize, ...action.payload };
|
||||||
@ -862,6 +817,28 @@ export const canvasSlice = createSlice({
|
|||||||
}
|
}
|
||||||
entity.isLocked = !entity.isLocked;
|
entity.isLocked = !entity.isLocked;
|
||||||
},
|
},
|
||||||
|
entityFillColorChanged: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<EntityIdentifierPayload<{ color: RgbColor }, 'inpaint_mask' | 'regional_guidance'>>
|
||||||
|
) => {
|
||||||
|
const { color, entityIdentifier } = action.payload;
|
||||||
|
const entity = selectEntity(state, entityIdentifier);
|
||||||
|
if (!entity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entity.fill.color = color;
|
||||||
|
},
|
||||||
|
entityFillStyleChanged: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<EntityIdentifierPayload<{ style: FillStyle }, 'inpaint_mask' | 'regional_guidance'>>
|
||||||
|
) => {
|
||||||
|
const { style, entityIdentifier } = action.payload;
|
||||||
|
const entity = selectEntity(state, entityIdentifier);
|
||||||
|
if (!entity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entity.fill.style = style;
|
||||||
|
},
|
||||||
entityMoved: (state, action: PayloadAction<EntityMovedPayload>) => {
|
entityMoved: (state, action: PayloadAction<EntityMovedPayload>) => {
|
||||||
const { entityIdentifier, position } = action.payload;
|
const { entityIdentifier, position } = action.payload;
|
||||||
const entity = selectEntity(state, entityIdentifier);
|
const entity = selectEntity(state, entityIdentifier);
|
||||||
@ -1088,6 +1065,8 @@ export const {
|
|||||||
entityReset,
|
entityReset,
|
||||||
entityIsEnabledToggled,
|
entityIsEnabledToggled,
|
||||||
entityIsLockedToggled,
|
entityIsLockedToggled,
|
||||||
|
entityFillColorChanged,
|
||||||
|
entityFillStyleChanged,
|
||||||
entityMoved,
|
entityMoved,
|
||||||
entityDuplicated,
|
entityDuplicated,
|
||||||
entityRasterized,
|
entityRasterized,
|
||||||
@ -1139,8 +1118,6 @@ export const {
|
|||||||
// rgRecalled,
|
// rgRecalled,
|
||||||
rgPositivePromptChanged,
|
rgPositivePromptChanged,
|
||||||
rgNegativePromptChanged,
|
rgNegativePromptChanged,
|
||||||
rgFillColorChanged,
|
|
||||||
rgFillStyleChanged,
|
|
||||||
rgAutoNegativeToggled,
|
rgAutoNegativeToggled,
|
||||||
rgIPAdapterAdded,
|
rgIPAdapterAdded,
|
||||||
rgIPAdapterDeleted,
|
rgIPAdapterDeleted,
|
||||||
@ -1153,8 +1130,6 @@ export const {
|
|||||||
// Inpaint mask
|
// Inpaint mask
|
||||||
inpaintMaskAdded,
|
inpaintMaskAdded,
|
||||||
// inpaintMaskRecalled,
|
// inpaintMaskRecalled,
|
||||||
inpaintMaskFillColorChanged,
|
|
||||||
inpaintMaskFillStyleChanged,
|
|
||||||
} = canvasSlice.actions;
|
} = canvasSlice.actions;
|
||||||
|
|
||||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||||
|
@ -193,3 +193,20 @@ export const selectIsSelectedEntityDrawable = createSelector(
|
|||||||
|
|
||||||
export const selectCanvasMayUndo = (state: RootState) => state.canvas.past.length > 0;
|
export const selectCanvasMayUndo = (state: RootState) => state.canvas.past.length > 0;
|
||||||
export const selectCanvasMayRedo = (state: RootState) => state.canvas.future.length > 0;
|
export const selectCanvasMayRedo = (state: RootState) => state.canvas.future.length > 0;
|
||||||
|
export const selectSelectedEntityFill = createSelector(
|
||||||
|
selectCanvasSlice,
|
||||||
|
selectSelectedEntityIdentifier,
|
||||||
|
(canvas, selectedEntityIdentifier) => {
|
||||||
|
if (!selectedEntityIdentifier) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const entity = selectEntity(canvas, selectedEntityIdentifier);
|
||||||
|
if (!entity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (entity.type !== 'inpaint_mask' && entity.type !== 'regional_guidance') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return entity.fill;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
@ -788,3 +788,9 @@ export const getEntityIdentifier = <T extends CanvasEntityType>(
|
|||||||
): CanvasEntityIdentifier<T> => {
|
): CanvasEntityIdentifier<T> => {
|
||||||
return { id: entity.id, type: entity.type };
|
return { id: entity.id, type: entity.type };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isMaskEntityIdentifier = (
|
||||||
|
entityIdentifier: CanvasEntityIdentifier
|
||||||
|
): entityIdentifier is CanvasEntityIdentifier<'inpaint_mask' | 'regional_guidance'> => {
|
||||||
|
return entityIdentifier.type === 'inpaint_mask' || entityIdentifier.type === 'regional_guidance';
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user