mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): restore transparency effect for control layers
This commit is contained in:
parent
6c6b1aaff6
commit
fc75f7919f
@ -1698,6 +1698,8 @@
|
||||
"filter": "Filter",
|
||||
"convertToControlLayer": "Convert to Control Layer",
|
||||
"convertToRasterLayer": "Convert to Raster Layer",
|
||||
"enableTransparencyEffect": "Enable Transparency Effect",
|
||||
"disableTransparencyEffect": "Disable Transparency Effect",
|
||||
"fill": {
|
||||
"fillStyle": "Fill Style",
|
||||
"solid": "Solid",
|
||||
|
@ -4,6 +4,7 @@ import { CanvasEntityMenuItemsDelete } from 'features/controlLayers/components/c
|
||||
import { CanvasEntityMenuItemsFilter } from 'features/controlLayers/components/common/CanvasEntityMenuItemsFilter';
|
||||
import { CanvasEntityMenuItemsReset } from 'features/controlLayers/components/common/CanvasEntityMenuItemsReset';
|
||||
import { ControlLayerMenuItemsControlToRaster } from 'features/controlLayers/components/ControlLayer/ControlLayerMenuItemsControlToRaster';
|
||||
import { ControlLayerMenuItemsTransparencyEffect } from 'features/controlLayers/components/ControlLayer/ControlLayerMenuItemsTransparencyEffect';
|
||||
import { memo } from 'react';
|
||||
|
||||
export const ControlLayerMenuItems = memo(() => {
|
||||
@ -11,6 +12,7 @@ export const ControlLayerMenuItems = memo(() => {
|
||||
<>
|
||||
<CanvasEntityMenuItemsFilter />
|
||||
<ControlLayerMenuItemsControlToRaster />
|
||||
<ControlLayerMenuItemsTransparencyEffect />
|
||||
<MenuDivider />
|
||||
<CanvasEntityMenuItemsArrange />
|
||||
<MenuDivider />
|
||||
|
@ -0,0 +1,40 @@
|
||||
import { MenuItem } from '@invoke-ai/ui-library';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useEntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext';
|
||||
import {
|
||||
controlLayerWithTransparencyEffectToggled,
|
||||
selectCanvasV2Slice,
|
||||
} from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { selectControlLayerOrThrow } from 'features/controlLayers/store/controlLayersReducers';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiDropHalfBold } from 'react-icons/pi';
|
||||
|
||||
export const ControlLayerMenuItemsTransparencyEffect = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const entityIdentifier = useEntityIdentifierContext();
|
||||
const selectWithTransparencyEffect = useMemo(
|
||||
() =>
|
||||
createSelector(selectCanvasV2Slice, (canvasV2) => {
|
||||
const entity = selectControlLayerOrThrow(canvasV2, entityIdentifier.id);
|
||||
return entity.withTransparencyEffect;
|
||||
}),
|
||||
[entityIdentifier.id]
|
||||
);
|
||||
const withTransparencyEffect = useAppSelector(selectWithTransparencyEffect);
|
||||
const onToggle = useCallback(() => {
|
||||
dispatch(controlLayerWithTransparencyEffectToggled({ id: entityIdentifier.id }));
|
||||
}, [dispatch, entityIdentifier]);
|
||||
|
||||
return (
|
||||
<MenuItem onClick={onToggle} icon={<PiDropHalfBold />}>
|
||||
{withTransparencyEffect
|
||||
? t('controlLayers.disableTransparencyEffect')
|
||||
: t('controlLayers.enableTransparencyEffect')}
|
||||
</MenuItem>
|
||||
);
|
||||
});
|
||||
|
||||
ControlLayerMenuItemsTransparencyEffect.displayName = 'ControlLayerMenuItemsTransparencyEffect';
|
@ -100,6 +100,12 @@ export class CanvasLayerAdapter {
|
||||
if (this.isFirstRender || opacity !== this.state.opacity) {
|
||||
this.renderer.updateOpacity(opacity);
|
||||
}
|
||||
|
||||
if (state.type === 'control_layer' && this.state.type === 'control_layer') {
|
||||
if (this.isFirstRender || state.withTransparencyEffect !== this.state.withTransparencyEffect) {
|
||||
this.renderer.updateTransparencyEffect(state.withTransparencyEffect);
|
||||
}
|
||||
}
|
||||
// this.transformer.syncInteractionState();
|
||||
|
||||
if (this.isFirstRender) {
|
||||
@ -129,12 +135,6 @@ export class CanvasLayerAdapter {
|
||||
}
|
||||
};
|
||||
|
||||
updateOpacity = (arg?: { opacity: number }) => {
|
||||
this.log.trace('Updating opacity');
|
||||
const opacity = get(arg, 'opacity', this.state.opacity);
|
||||
this.renderer.konva.objectGroup.opacity(opacity);
|
||||
};
|
||||
|
||||
repr = () => {
|
||||
return {
|
||||
id: this.id,
|
||||
|
@ -7,6 +7,7 @@ import type { CanvasLayerAdapter } from 'features/controlLayers/konva/CanvasLaye
|
||||
import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
|
||||
import type { CanvasMaskAdapter } from 'features/controlLayers/konva/CanvasMaskAdapter';
|
||||
import { CanvasRectRenderer } from 'features/controlLayers/konva/CanvasRect';
|
||||
import { LightnessToAlphaFilter } from 'features/controlLayers/konva/filters';
|
||||
import { getPatternSVG } from 'features/controlLayers/konva/patterns/getPatternSVG';
|
||||
import { getPrefixedId, konvaNodeToBlob, konvaNodeToImageData, previewBlob } from 'features/controlLayers/konva/util';
|
||||
import type {
|
||||
@ -203,6 +204,11 @@ export class CanvasObjectRenderer {
|
||||
}
|
||||
};
|
||||
|
||||
updateTransparencyEffect = (withTransparencyEffect: boolean) => {
|
||||
const filters = withTransparencyEffect ? [LightnessToAlphaFilter] : [];
|
||||
this.konva.objectGroup.filters(filters);
|
||||
};
|
||||
|
||||
updateCompositingRectFill = (fill: Fill) => {
|
||||
this.log.trace('Updating compositing rect fill');
|
||||
assert(this.konva.compositing, 'Missing compositing rect');
|
||||
|
@ -584,6 +584,7 @@ export const {
|
||||
controlLayerControlModeChanged,
|
||||
controlLayerWeightChanged,
|
||||
controlLayerBeginEndStepPctChanged,
|
||||
controlLayerWithTransparencyEffectToggled,
|
||||
// IP Adapters
|
||||
ipaAdded,
|
||||
ipaRecalled,
|
||||
|
@ -36,6 +36,7 @@ export const controlLayersReducers = {
|
||||
name: null,
|
||||
type: 'control_layer',
|
||||
isEnabled: true,
|
||||
withTransparencyEffect: true,
|
||||
objects: [],
|
||||
opacity: 1,
|
||||
position: { x: 0, y: 0 },
|
||||
@ -70,7 +71,7 @@ export const controlLayersReducers = {
|
||||
|
||||
// Convert the raster layer to control layer
|
||||
const rasterLayerState: CanvasRasterLayerState = {
|
||||
...omit(deepClone(layer), ['type', 'controlAdapter']),
|
||||
...omit(deepClone(layer), ['type', 'controlAdapter', 'withTransparencyEffect']),
|
||||
id: newId,
|
||||
type: 'raster_layer',
|
||||
};
|
||||
@ -151,4 +152,12 @@ export const controlLayersReducers = {
|
||||
}
|
||||
layer.controlAdapter.beginEndStepPct = beginEndStepPct;
|
||||
},
|
||||
controlLayerWithTransparencyEffectToggled: (state, action: PayloadAction<{ id: string }>) => {
|
||||
const { id } = action.payload;
|
||||
const layer = selectControlLayer(state, id);
|
||||
if (!layer) {
|
||||
return;
|
||||
}
|
||||
layer.withTransparencyEffect = !layer.withTransparencyEffect;
|
||||
},
|
||||
} satisfies SliceCaseReducers<CanvasV2State>;
|
||||
|
@ -89,6 +89,7 @@ export const rasterLayersReducers = {
|
||||
id: newId,
|
||||
type: 'control_layer',
|
||||
controlAdapter,
|
||||
withTransparencyEffect: true,
|
||||
};
|
||||
|
||||
// Remove the raster layer
|
||||
|
@ -559,14 +559,14 @@ const zCanvasRectState = z.object({
|
||||
});
|
||||
export type CanvasRectState = z.infer<typeof zCanvasRectState>;
|
||||
|
||||
const zFilter = z.enum(['LightnessToAlphaFilter']);
|
||||
export type Filter = z.infer<typeof zFilter>;
|
||||
const zLayerEffect = z.enum(['LightnessToAlphaFilter']);
|
||||
export type LayerEffect = z.infer<typeof zLayerEffect>;
|
||||
|
||||
const zCanvasImageState = z.object({
|
||||
id: zId,
|
||||
type: z.literal('image'),
|
||||
image: zImageWithDims,
|
||||
filters: z.array(zFilter),
|
||||
filters: z.array(zLayerEffect),
|
||||
});
|
||||
export type CanvasImageState = z.infer<typeof zCanvasImageState>;
|
||||
|
||||
@ -699,7 +699,7 @@ const zCanvasControlAdapterStateBase = z.object({
|
||||
isEnabled: z.boolean(),
|
||||
position: zCoordinate,
|
||||
opacity: zOpacity,
|
||||
filters: z.array(zFilter),
|
||||
filters: z.array(zLayerEffect),
|
||||
weight: z.number().gte(-1).lte(2),
|
||||
imageObject: zCanvasImageState.nullable(),
|
||||
processedImageObject: zCanvasImageState.nullable(),
|
||||
@ -755,6 +755,7 @@ export type CanvasRasterLayerState = z.infer<typeof zCanvasRasterLayerState>;
|
||||
|
||||
export const zCanvasControlLayerState = zCanvasRasterLayerState.extend({
|
||||
type: z.literal('control_layer'),
|
||||
withTransparencyEffect: z.boolean(),
|
||||
controlAdapter: z.discriminatedUnion('type', [zControlNetConfig, zT2IAdapterConfig]),
|
||||
});
|
||||
export type CanvasControlLayerState = z.infer<typeof zCanvasControlLayerState>;
|
||||
|
Loading…
Reference in New Issue
Block a user