mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat: ✨ invert scroll direction for brush size
This commit is contained in:
parent
99c0662e3f
commit
4301a3d6fd
@ -1818,6 +1818,7 @@
|
|||||||
"eraseBoundingBox": "Erase Bounding Box",
|
"eraseBoundingBox": "Erase Bounding Box",
|
||||||
"eraser": "Eraser",
|
"eraser": "Eraser",
|
||||||
"fillBoundingBox": "Fill Bounding Box",
|
"fillBoundingBox": "Fill Bounding Box",
|
||||||
|
"invertBrushSizeScrollDirection": "Invert Scroll for Brush Size",
|
||||||
"layer": "Layer",
|
"layer": "Layer",
|
||||||
"limitStrokesToBox": "Limit Strokes to Box",
|
"limitStrokesToBox": "Limit Strokes to Box",
|
||||||
"mask": "Mask",
|
"mask": "Mask",
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
setShouldAutoSave,
|
setShouldAutoSave,
|
||||||
setShouldCropToBoundingBoxOnSave,
|
setShouldCropToBoundingBoxOnSave,
|
||||||
setShouldDarkenOutsideBoundingBox,
|
setShouldDarkenOutsideBoundingBox,
|
||||||
|
setShouldInvertBrushSizeScrollDirection,
|
||||||
setShouldRestrictStrokesToBox,
|
setShouldRestrictStrokesToBox,
|
||||||
setShouldShowCanvasDebugInfo,
|
setShouldShowCanvasDebugInfo,
|
||||||
setShouldShowGrid,
|
setShouldShowGrid,
|
||||||
@ -40,6 +41,7 @@ const IAICanvasSettingsButtonPopover = () => {
|
|||||||
const shouldAutoSave = useAppSelector((s) => s.canvas.shouldAutoSave);
|
const shouldAutoSave = useAppSelector((s) => s.canvas.shouldAutoSave);
|
||||||
const shouldCropToBoundingBoxOnSave = useAppSelector((s) => s.canvas.shouldCropToBoundingBoxOnSave);
|
const shouldCropToBoundingBoxOnSave = useAppSelector((s) => s.canvas.shouldCropToBoundingBoxOnSave);
|
||||||
const shouldDarkenOutsideBoundingBox = useAppSelector((s) => s.canvas.shouldDarkenOutsideBoundingBox);
|
const shouldDarkenOutsideBoundingBox = useAppSelector((s) => s.canvas.shouldDarkenOutsideBoundingBox);
|
||||||
|
const shouldInvertBrushSizeScrollDirection = useAppSelector((s) => s.canvas.shouldInvertBrushSizeScrollDirection);
|
||||||
const shouldShowCanvasDebugInfo = useAppSelector((s) => s.canvas.shouldShowCanvasDebugInfo);
|
const shouldShowCanvasDebugInfo = useAppSelector((s) => s.canvas.shouldShowCanvasDebugInfo);
|
||||||
const shouldShowGrid = useAppSelector((s) => s.canvas.shouldShowGrid);
|
const shouldShowGrid = useAppSelector((s) => s.canvas.shouldShowGrid);
|
||||||
const shouldShowIntermediates = useAppSelector((s) => s.canvas.shouldShowIntermediates);
|
const shouldShowIntermediates = useAppSelector((s) => s.canvas.shouldShowIntermediates);
|
||||||
@ -76,6 +78,10 @@ const IAICanvasSettingsButtonPopover = () => {
|
|||||||
(e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldDarkenOutsideBoundingBox(e.target.checked)),
|
(e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldDarkenOutsideBoundingBox(e.target.checked)),
|
||||||
[dispatch]
|
[dispatch]
|
||||||
);
|
);
|
||||||
|
const handleChangeShouldInvertBrushSizeScrollDirection = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldInvertBrushSizeScrollDirection(e.target.checked)),
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
const handleChangeShouldAutoSave = useCallback(
|
const handleChangeShouldAutoSave = useCallback(
|
||||||
(e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldAutoSave(e.target.checked)),
|
(e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldAutoSave(e.target.checked)),
|
||||||
[dispatch]
|
[dispatch]
|
||||||
@ -144,6 +150,13 @@ const IAICanvasSettingsButtonPopover = () => {
|
|||||||
<FormLabel>{t('unifiedCanvas.limitStrokesToBox')}</FormLabel>
|
<FormLabel>{t('unifiedCanvas.limitStrokesToBox')}</FormLabel>
|
||||||
<Checkbox isChecked={shouldRestrictStrokesToBox} onChange={handleChangeShouldRestrictStrokesToBox} />
|
<Checkbox isChecked={shouldRestrictStrokesToBox} onChange={handleChangeShouldRestrictStrokesToBox} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{t('unifiedCanvas.invertBrushSizeScrollDirection')}</FormLabel>
|
||||||
|
<Checkbox
|
||||||
|
isChecked={shouldInvertBrushSizeScrollDirection}
|
||||||
|
onChange={handleChangeShouldInvertBrushSizeScrollDirection}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormLabel>{t('unifiedCanvas.showCanvasDebugInfo')}</FormLabel>
|
<FormLabel>{t('unifiedCanvas.showCanvasDebugInfo')}</FormLabel>
|
||||||
<Checkbox isChecked={shouldShowCanvasDebugInfo} onChange={handleChangeShouldShowCanvasDebugInfo} />
|
<Checkbox isChecked={shouldShowCanvasDebugInfo} onChange={handleChangeShouldShowCanvasDebugInfo} />
|
||||||
|
@ -15,6 +15,7 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
|||||||
const stageScale = useAppSelector((s) => s.canvas.stageScale);
|
const stageScale = useAppSelector((s) => s.canvas.stageScale);
|
||||||
const isMoveStageKeyHeld = useStore($isMoveStageKeyHeld);
|
const isMoveStageKeyHeld = useStore($isMoveStageKeyHeld);
|
||||||
const brushSize = useAppSelector((s) => s.canvas.brushSize);
|
const brushSize = useAppSelector((s) => s.canvas.brushSize);
|
||||||
|
const shouldInvertBrushSizeScrollDirection = useAppSelector((s) => s.canvas.shouldInvertBrushSizeScrollDirection);
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
(e: KonvaEventObject<WheelEvent>) => {
|
(e: KonvaEventObject<WheelEvent>) => {
|
||||||
@ -28,10 +29,16 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
|||||||
// checking for ctrl key is pressed or not,
|
// checking for ctrl key is pressed or not,
|
||||||
// so that brush size can be controlled using ctrl + scroll up/down
|
// so that brush size can be controlled using ctrl + scroll up/down
|
||||||
|
|
||||||
|
// Invert the delta if the property is set to true
|
||||||
|
let delta = e.evt.deltaY;
|
||||||
|
if (shouldInvertBrushSizeScrollDirection) {
|
||||||
|
delta = -delta
|
||||||
|
}
|
||||||
|
|
||||||
if ($ctrl.get() || $meta.get()) {
|
if ($ctrl.get() || $meta.get()) {
|
||||||
// This equation was derived by fitting a curve to the desired brush sizes and deltas
|
// This equation was derived by fitting a curve to the desired brush sizes and deltas
|
||||||
// see https://github.com/invoke-ai/InvokeAI/pull/5542#issuecomment-1915847565
|
// see https://github.com/invoke-ai/InvokeAI/pull/5542#issuecomment-1915847565
|
||||||
const targetDelta = Math.sign(e.evt.deltaY) * 0.7363 * Math.pow(1.0394, brushSize);
|
const targetDelta = Math.sign(delta) * 0.7363 * Math.pow(1.0394, brushSize);
|
||||||
// This needs to be clamped to prevent the delta from getting too large
|
// This needs to be clamped to prevent the delta from getting too large
|
||||||
const finalDelta = clamp(targetDelta, -20, 20);
|
const finalDelta = clamp(targetDelta, -20, 20);
|
||||||
// The new brush size is also clamped to prevent it from getting too large or small
|
// The new brush size is also clamped to prevent it from getting too large or small
|
||||||
@ -67,7 +74,7 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
|||||||
dispatch(setStageCoordinates(newCoordinates));
|
dispatch(setStageCoordinates(newCoordinates));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[stageRef, isMoveStageKeyHeld, stageScale, dispatch, brushSize]
|
[stageRef, isMoveStageKeyHeld, brushSize, dispatch, stageScale, shouldInvertBrushSizeScrollDirection]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ const initialCanvasState: CanvasState = {
|
|||||||
shouldAutoSave: false,
|
shouldAutoSave: false,
|
||||||
shouldCropToBoundingBoxOnSave: false,
|
shouldCropToBoundingBoxOnSave: false,
|
||||||
shouldDarkenOutsideBoundingBox: false,
|
shouldDarkenOutsideBoundingBox: false,
|
||||||
|
shouldInvertBrushSizeScrollDirection: false,
|
||||||
shouldLockBoundingBox: false,
|
shouldLockBoundingBox: false,
|
||||||
shouldPreserveMaskedArea: false,
|
shouldPreserveMaskedArea: false,
|
||||||
shouldRestrictStrokesToBox: true,
|
shouldRestrictStrokesToBox: true,
|
||||||
@ -220,6 +221,9 @@ export const canvasSlice = createSlice({
|
|||||||
setShouldDarkenOutsideBoundingBox: (state, action: PayloadAction<boolean>) => {
|
setShouldDarkenOutsideBoundingBox: (state, action: PayloadAction<boolean>) => {
|
||||||
state.shouldDarkenOutsideBoundingBox = action.payload;
|
state.shouldDarkenOutsideBoundingBox = action.payload;
|
||||||
},
|
},
|
||||||
|
setShouldInvertBrushSizeScrollDirection: (state, action: PayloadAction<boolean>) => {
|
||||||
|
state.shouldInvertBrushSizeScrollDirection = action.payload;
|
||||||
|
},
|
||||||
clearCanvasHistory: (state) => {
|
clearCanvasHistory: (state) => {
|
||||||
state.pastLayerStates = [];
|
state.pastLayerStates = [];
|
||||||
state.futureLayerStates = [];
|
state.futureLayerStates = [];
|
||||||
@ -674,6 +678,7 @@ export const {
|
|||||||
setShouldAutoSave,
|
setShouldAutoSave,
|
||||||
setShouldCropToBoundingBoxOnSave,
|
setShouldCropToBoundingBoxOnSave,
|
||||||
setShouldDarkenOutsideBoundingBox,
|
setShouldDarkenOutsideBoundingBox,
|
||||||
|
setShouldInvertBrushSizeScrollDirection,
|
||||||
setShouldPreserveMaskedArea,
|
setShouldPreserveMaskedArea,
|
||||||
setShouldShowBoundingBox,
|
setShouldShowBoundingBox,
|
||||||
setShouldShowCanvasDebugInfo,
|
setShouldShowCanvasDebugInfo,
|
||||||
|
@ -120,6 +120,7 @@ export interface CanvasState {
|
|||||||
shouldAutoSave: boolean;
|
shouldAutoSave: boolean;
|
||||||
shouldCropToBoundingBoxOnSave: boolean;
|
shouldCropToBoundingBoxOnSave: boolean;
|
||||||
shouldDarkenOutsideBoundingBox: boolean;
|
shouldDarkenOutsideBoundingBox: boolean;
|
||||||
|
shouldInvertBrushSizeScrollDirection: boolean;
|
||||||
shouldLockBoundingBox: boolean;
|
shouldLockBoundingBox: boolean;
|
||||||
shouldPreserveMaskedArea: boolean;
|
shouldPreserveMaskedArea: boolean;
|
||||||
shouldRestrictStrokesToBox: boolean;
|
shouldRestrictStrokesToBox: boolean;
|
||||||
|
Loading…
Reference in New Issue
Block a user