feat(ui): canvas antialiasing

This commit is contained in:
psychedelicious 2023-05-10 14:13:33 +10:00
parent fdc2232ea0
commit 31a78d571b
6 changed files with 36 additions and 10 deletions

View File

@ -650,7 +650,8 @@
"betaClear": "Clear", "betaClear": "Clear",
"betaDarkenOutside": "Darken Outside", "betaDarkenOutside": "Darken Outside",
"betaLimitToBox": "Limit To Box", "betaLimitToBox": "Limit To Box",
"betaPreserveMasked": "Preserve Masked" "betaPreserveMasked": "Preserve Masked",
"antialiasing": "Antialiasing"
}, },
"ui": { "ui": {
"showProgressImages": "Show Progress Images", "showProgressImages": "Show Progress Images",

View File

@ -34,6 +34,7 @@ import IAICanvasStagingAreaToolbar from './IAICanvasStagingAreaToolbar';
import IAICanvasStatusText from './IAICanvasStatusText'; import IAICanvasStatusText from './IAICanvasStatusText';
import IAICanvasBoundingBox from './IAICanvasToolbar/IAICanvasBoundingBox'; import IAICanvasBoundingBox from './IAICanvasToolbar/IAICanvasBoundingBox';
import IAICanvasToolPreview from './IAICanvasToolPreview'; import IAICanvasToolPreview from './IAICanvasToolPreview';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
const selector = createSelector( const selector = createSelector(
[canvasSelector, isStagingSelector], [canvasSelector, isStagingSelector],
@ -52,6 +53,7 @@ const selector = createSelector(
shouldShowIntermediates, shouldShowIntermediates,
shouldShowGrid, shouldShowGrid,
shouldRestrictStrokesToBox, shouldRestrictStrokesToBox,
shouldAntialias,
} = canvas; } = canvas;
let stageCursor: string | undefined = 'none'; let stageCursor: string | undefined = 'none';
@ -80,13 +82,10 @@ const selector = createSelector(
tool, tool,
isStaging, isStaging,
shouldShowIntermediates, shouldShowIntermediates,
shouldAntialias,
}; };
}, },
{ defaultSelectorOptions
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
); );
const ChakraStage = chakra(Stage, { const ChakraStage = chakra(Stage, {
@ -106,6 +105,7 @@ const IAICanvas = () => {
tool, tool,
isStaging, isStaging,
shouldShowIntermediates, shouldShowIntermediates,
shouldAntialias,
} = useAppSelector(selector); } = useAppSelector(selector);
useCanvasHotkeys(); useCanvasHotkeys();
@ -190,7 +190,7 @@ const IAICanvas = () => {
id="base" id="base"
ref={canvasBaseLayerRefCallback} ref={canvasBaseLayerRefCallback}
listening={false} listening={false}
imageSmoothingEnabled={false} imageSmoothingEnabled={shouldAntialias}
> >
<IAICanvasObjectRenderer /> <IAICanvasObjectRenderer />
</Layer> </Layer>
@ -201,7 +201,7 @@ const IAICanvas = () => {
<Layer> <Layer>
<IAICanvasBoundingBoxOverlay /> <IAICanvasBoundingBoxOverlay />
</Layer> </Layer>
<Layer id="preview" imageSmoothingEnabled={false}> <Layer id="preview" imageSmoothingEnabled={shouldAntialias}>
{!isStaging && ( {!isStaging && (
<IAICanvasToolPreview <IAICanvasToolPreview
visible={tool !== 'move'} visible={tool !== 'move'}

View File

@ -6,6 +6,7 @@ import IAIIconButton from 'common/components/IAIIconButton';
import IAIPopover from 'common/components/IAIPopover'; import IAIPopover from 'common/components/IAIPopover';
import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { import {
setShouldAntialias,
setShouldAutoSave, setShouldAutoSave,
setShouldCropToBoundingBoxOnSave, setShouldCropToBoundingBoxOnSave,
setShouldDarkenOutsideBoundingBox, setShouldDarkenOutsideBoundingBox,
@ -36,6 +37,7 @@ export const canvasControlsSelector = createSelector(
shouldShowIntermediates, shouldShowIntermediates,
shouldSnapToGrid, shouldSnapToGrid,
shouldRestrictStrokesToBox, shouldRestrictStrokesToBox,
shouldAntialias,
} = canvas; } = canvas;
return { return {
@ -47,6 +49,7 @@ export const canvasControlsSelector = createSelector(
shouldShowIntermediates, shouldShowIntermediates,
shouldSnapToGrid, shouldSnapToGrid,
shouldRestrictStrokesToBox, shouldRestrictStrokesToBox,
shouldAntialias,
}; };
}, },
{ {
@ -69,6 +72,7 @@ const IAICanvasSettingsButtonPopover = () => {
shouldShowIntermediates, shouldShowIntermediates,
shouldSnapToGrid, shouldSnapToGrid,
shouldRestrictStrokesToBox, shouldRestrictStrokesToBox,
shouldAntialias,
} = useAppSelector(canvasControlsSelector); } = useAppSelector(canvasControlsSelector);
useHotkeys( useHotkeys(
@ -148,6 +152,12 @@ const IAICanvasSettingsButtonPopover = () => {
dispatch(setShouldShowCanvasDebugInfo(e.target.checked)) dispatch(setShouldShowCanvasDebugInfo(e.target.checked))
} }
/> />
<IAICheckbox
label={t('unifiedCanvas.antialiasing')}
isChecked={shouldAntialias}
onChange={(e) => dispatch(setShouldAntialias(e.target.checked))}
/>
<ClearCanvasHistoryButtonModal /> <ClearCanvasHistoryButtonModal />
<EmptyTempFolderButtonModal /> <EmptyTempFolderButtonModal />
</Flex> </Flex>

View File

@ -66,6 +66,7 @@ export const initialCanvasState: CanvasState = {
minimumStageScale: 1, minimumStageScale: 1,
pastLayerStates: [], pastLayerStates: [],
scaledBoundingBoxDimensions: { width: 512, height: 512 }, scaledBoundingBoxDimensions: { width: 512, height: 512 },
shouldAntialias: true,
shouldAutoSave: false, shouldAutoSave: false,
shouldCropToBoundingBoxOnSave: false, shouldCropToBoundingBoxOnSave: false,
shouldDarkenOutsideBoundingBox: false, shouldDarkenOutsideBoundingBox: false,
@ -796,6 +797,9 @@ export const canvasSlice = createSlice({
setShouldRestrictStrokesToBox: (state, action: PayloadAction<boolean>) => { setShouldRestrictStrokesToBox: (state, action: PayloadAction<boolean>) => {
state.shouldRestrictStrokesToBox = action.payload; state.shouldRestrictStrokesToBox = action.payload;
}, },
setShouldAntialias: (state, action: PayloadAction<boolean>) => {
state.shouldAntialias = action.payload;
},
setShouldCropToBoundingBoxOnSave: ( setShouldCropToBoundingBoxOnSave: (
state, state,
action: PayloadAction<boolean> action: PayloadAction<boolean>
@ -907,6 +911,7 @@ export const {
setShouldRestrictStrokesToBox, setShouldRestrictStrokesToBox,
stagingAreaInitialized, stagingAreaInitialized,
canvasSessionIdChanged, canvasSessionIdChanged,
setShouldAntialias,
} = canvasSlice.actions; } = canvasSlice.actions;
export default canvasSlice.reducer; export default canvasSlice.reducer;

View File

@ -37,7 +37,7 @@ export type CanvasImage = {
y: number; y: number;
width: number; width: number;
height: number; height: number;
image: InvokeAI._Image; image: InvokeAI.Image;
}; };
export type CanvasMaskLine = { export type CanvasMaskLine = {
@ -132,7 +132,7 @@ export interface CanvasState {
cursorPosition: Vector2d | null; cursorPosition: Vector2d | null;
doesCanvasNeedScaling: boolean; doesCanvasNeedScaling: boolean;
futureLayerStates: CanvasLayerState[]; futureLayerStates: CanvasLayerState[];
intermediateImage?: InvokeAI._Image; intermediateImage?: InvokeAI.Image;
isCanvasInitialized: boolean; isCanvasInitialized: boolean;
isDrawing: boolean; isDrawing: boolean;
isMaskEnabled: boolean; isMaskEnabled: boolean;
@ -149,6 +149,7 @@ export interface CanvasState {
minimumStageScale: number; minimumStageScale: number;
pastLayerStates: CanvasLayerState[]; pastLayerStates: CanvasLayerState[];
scaledBoundingBoxDimensions: Dimensions; scaledBoundingBoxDimensions: Dimensions;
shouldAntialias: boolean;
shouldAutoSave: boolean; shouldAutoSave: boolean;
shouldCropToBoundingBoxOnSave: boolean; shouldCropToBoundingBoxOnSave: boolean;
shouldDarkenOutsideBoundingBox: boolean; shouldDarkenOutsideBoundingBox: boolean;

View File

@ -6,6 +6,7 @@ import IAIIconButton from 'common/components/IAIIconButton';
import IAIPopover from 'common/components/IAIPopover'; import IAIPopover from 'common/components/IAIPopover';
import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { import {
setShouldAntialias,
setShouldAutoSave, setShouldAutoSave,
setShouldCropToBoundingBoxOnSave, setShouldCropToBoundingBoxOnSave,
setShouldShowCanvasDebugInfo, setShouldShowCanvasDebugInfo,
@ -27,6 +28,7 @@ export const canvasControlsSelector = createSelector(
shouldCropToBoundingBoxOnSave, shouldCropToBoundingBoxOnSave,
shouldShowCanvasDebugInfo, shouldShowCanvasDebugInfo,
shouldShowIntermediates, shouldShowIntermediates,
shouldAntialias,
} = canvas; } = canvas;
return { return {
@ -34,6 +36,7 @@ export const canvasControlsSelector = createSelector(
shouldCropToBoundingBoxOnSave, shouldCropToBoundingBoxOnSave,
shouldShowCanvasDebugInfo, shouldShowCanvasDebugInfo,
shouldShowIntermediates, shouldShowIntermediates,
shouldAntialias,
}; };
}, },
{ {
@ -52,6 +55,7 @@ const UnifiedCanvasSettings = () => {
shouldCropToBoundingBoxOnSave, shouldCropToBoundingBoxOnSave,
shouldShowCanvasDebugInfo, shouldShowCanvasDebugInfo,
shouldShowIntermediates, shouldShowIntermediates,
shouldAntialias,
} = useAppSelector(canvasControlsSelector); } = useAppSelector(canvasControlsSelector);
return ( return (
@ -95,6 +99,11 @@ const UnifiedCanvasSettings = () => {
dispatch(setShouldShowCanvasDebugInfo(e.target.checked)) dispatch(setShouldShowCanvasDebugInfo(e.target.checked))
} }
/> />
<IAICheckbox
label={t('unifiedCanvas.antialiasing')}
isChecked={shouldAntialias}
onChange={(e) => dispatch(setShouldAntialias(e.target.checked))}
/>
<ClearCanvasHistoryButtonModal /> <ClearCanvasHistoryButtonModal />
<EmptyTempFolderButtonModal /> <EmptyTempFolderButtonModal />
</Flex> </Flex>