mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): move ephemeral state into canvas classes
Things like `$lastCursorPos` are now created within the canvas drawing classes. Consumers in react access them via `useCanvasManager`. For example: ```tsx const canvasManager = useCanvasManager(); const lastCursorPos = useStore(canvasManager.stateApi.$lastCursorPos); ```
This commit is contained in:
parent
a3179e7a3f
commit
9c1732e2bb
@ -14,10 +14,9 @@ import {
|
||||
PopoverTrigger,
|
||||
} from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { $canvasManager } from 'features/controlLayers/konva/CanvasManager';
|
||||
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
||||
import { MAX_CANVAS_SCALE, MIN_CANVAS_SCALE } from 'features/controlLayers/konva/constants';
|
||||
import { snapToNearest } from 'features/controlLayers/konva/util';
|
||||
import { $stageAttrs } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { clamp, round } from 'lodash-es';
|
||||
import { computed } from 'nanostores';
|
||||
import type { KeyboardEvent } from 'react';
|
||||
@ -72,12 +71,10 @@ const sliderDefaultValue = mapScaleToSliderValue(100);
|
||||
|
||||
const snapCandidates = marks.slice(1, marks.length - 1);
|
||||
|
||||
const $scale = computed($stageAttrs, (attrs) => attrs.scale);
|
||||
|
||||
export const CanvasScale = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const canvasManager = useStore($canvasManager);
|
||||
const scale = useStore($scale);
|
||||
const canvasManager = useCanvasManager();
|
||||
const scale = useStore(computed(canvasManager.stateApi.$stageAttrs, (attrs) => attrs.scale));
|
||||
const [localScale, setLocalScale] = useState(scale * 100);
|
||||
|
||||
const onChangeSlider = useCallback(
|
||||
|
@ -1,24 +1,18 @@
|
||||
import { Box, Flex, Text } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
$isDrawing,
|
||||
$isMouseDown,
|
||||
$lastAddedPoint,
|
||||
$lastCursorPos,
|
||||
$lastMouseDownPos,
|
||||
$stageAttrs,
|
||||
} from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
||||
import { round } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
|
||||
export const HeadsUpDisplay = memo(() => {
|
||||
const stageAttrs = useStore($stageAttrs);
|
||||
const cursorPos = useStore($lastCursorPos);
|
||||
const isDrawing = useStore($isDrawing);
|
||||
const isMouseDown = useStore($isMouseDown);
|
||||
const lastMouseDownPos = useStore($lastMouseDownPos);
|
||||
const lastAddedPoint = useStore($lastAddedPoint);
|
||||
const canvasManager = useCanvasManager();
|
||||
const stageAttrs = useStore(canvasManager.stateApi.$stageAttrs);
|
||||
const cursorPos = useStore(canvasManager.stateApi.$lastCursorPos);
|
||||
const isDrawing = useStore(canvasManager.stateApi.$isDrawing);
|
||||
const isMouseDown = useStore(canvasManager.stateApi.$isMouseDown);
|
||||
const lastMouseDownPos = useStore(canvasManager.stateApi.$lastMouseDownPos);
|
||||
const lastAddedPoint = useStore(canvasManager.stateApi.$lastAddedPoint);
|
||||
const bbox = useAppSelector((s) => s.canvasV2.bbox);
|
||||
|
||||
return (
|
||||
|
@ -2,8 +2,8 @@ import { Button, ButtonGroup, IconButton } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { INTERACTION_SCOPES, useScopeOnMount } from 'common/hooks/interactionScopes';
|
||||
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
||||
import {
|
||||
$shouldShowStagedImage,
|
||||
sessionNextStagedImageSelected,
|
||||
sessionPrevStagedImageSelected,
|
||||
sessionStagedImageDiscarded,
|
||||
@ -28,7 +28,8 @@ import { useChangeImageIsIntermediateMutation } from 'services/api/endpoints/ima
|
||||
export const StagingAreaToolbar = memo(() => {
|
||||
const dispatch = useAppDispatch();
|
||||
const session = useAppSelector((s) => s.canvasV2.session);
|
||||
const shouldShowStagedImage = useStore($shouldShowStagedImage);
|
||||
const canvasManager = useCanvasManager();
|
||||
const shouldShowStagedImage = useStore(canvasManager.stateApi.$shouldShowStagedImage);
|
||||
const images = useMemo(() => session.stagedImages, [session]);
|
||||
const selectedImage = useMemo(() => {
|
||||
return images[session.selectedStagedImageIndex] ?? null;
|
||||
@ -70,8 +71,8 @@ export const StagingAreaToolbar = memo(() => {
|
||||
}, [dispatch]);
|
||||
|
||||
const onToggleShouldShowStagedImage = useCallback(() => {
|
||||
$shouldShowStagedImage.set(!shouldShowStagedImage);
|
||||
}, [shouldShowStagedImage]);
|
||||
canvasManager.stateApi.$shouldShowStagedImage.set(!shouldShowStagedImage);
|
||||
}, [canvasManager.stateApi.$shouldShowStagedImage, shouldShowStagedImage]);
|
||||
|
||||
const onSaveStagingImage = useCallback(() => {
|
||||
if (!selectedImage) {
|
||||
|
@ -4,16 +4,6 @@ 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 {
|
||||
$isDrawing,
|
||||
$isMouseDown,
|
||||
$isProcessingTransform,
|
||||
$lastAddedPoint,
|
||||
$lastCursorPos,
|
||||
$lastMouseDownPos,
|
||||
$shouldShowStagedImage,
|
||||
$spaceKey,
|
||||
$stageAttrs,
|
||||
$transformingEntity,
|
||||
bboxChanged,
|
||||
brushWidthChanged,
|
||||
entityBrushLineAdded,
|
||||
@ -36,6 +26,7 @@ import type {
|
||||
CanvasRasterLayerState,
|
||||
CanvasRegionalGuidanceState,
|
||||
CanvasV2State,
|
||||
Coordinate,
|
||||
EntityBrushLineAddedPayload,
|
||||
EntityEraserLineAddedPayload,
|
||||
EntityIdentifierPayload,
|
||||
@ -45,6 +36,7 @@ import type {
|
||||
Rect,
|
||||
RgbaColor,
|
||||
RgbColor,
|
||||
StageAttrs,
|
||||
Tool,
|
||||
} from 'features/controlLayers/store/types';
|
||||
import { RGBA_BLACK } from 'features/controlLayers/store/types';
|
||||
@ -243,8 +235,8 @@ export class CanvasStateApiModule {
|
||||
}
|
||||
};
|
||||
|
||||
$transformingEntity = $transformingEntity;
|
||||
$isProcessingTransform = $isProcessingTransform;
|
||||
$transformingEntity = atom<CanvasEntityIdentifier | null>(null);
|
||||
$isProcessingTransform = atom<boolean>(false);
|
||||
|
||||
$toolState: WritableAtom<CanvasV2State['tool']> = atom();
|
||||
$currentFill: WritableAtom<RgbaColor> = atom();
|
||||
@ -253,17 +245,23 @@ export class CanvasStateApiModule {
|
||||
$colorUnderCursor: WritableAtom<RgbColor> = atom(RGBA_BLACK);
|
||||
|
||||
// Read-write state, ephemeral interaction state
|
||||
$isDrawing = $isDrawing;
|
||||
$isMouseDown = $isMouseDown;
|
||||
$lastAddedPoint = $lastAddedPoint;
|
||||
$lastMouseDownPos = $lastMouseDownPos;
|
||||
$lastCursorPos = $lastCursorPos;
|
||||
$isDrawing = atom<boolean>(false);
|
||||
$isMouseDown = atom<boolean>(false);
|
||||
$lastAddedPoint = atom<Coordinate | null>(null);
|
||||
$lastMouseDownPos = atom<Coordinate | null>(null);
|
||||
$lastCursorPos = atom<Coordinate | null>(null);
|
||||
$lastCanvasProgressEvent = $lastCanvasProgressEvent;
|
||||
$spaceKey = $spaceKey;
|
||||
$spaceKey = atom<boolean>(false);
|
||||
$altKey = $alt;
|
||||
$ctrlKey = $ctrl;
|
||||
$metaKey = $meta;
|
||||
$shiftKey = $shift;
|
||||
$shouldShowStagedImage = $shouldShowStagedImage;
|
||||
$stageAttrs = $stageAttrs;
|
||||
$shouldShowStagedImage = atom(true);
|
||||
$stageAttrs = atom<StageAttrs>({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
scale: 0,
|
||||
});
|
||||
}
|
||||
|
@ -22,20 +22,17 @@ import { simplifyFlatNumbersArray } from 'features/controlLayers/util/simplify';
|
||||
import { initialAspectRatioState } from 'features/parameters/components/DocumentSize/constants';
|
||||
import { getOptimalDimension } from 'features/parameters/util/optimalDimension';
|
||||
import { pick } from 'lodash-es';
|
||||
import { atom } from 'nanostores';
|
||||
import { assert } from 'tsafe';
|
||||
|
||||
import type {
|
||||
CanvasEntityIdentifier,
|
||||
CanvasV2State,
|
||||
Coordinate,
|
||||
EntityBrushLineAddedPayload,
|
||||
EntityEraserLineAddedPayload,
|
||||
EntityIdentifierPayload,
|
||||
EntityMovedPayload,
|
||||
EntityRasterizedPayload,
|
||||
EntityRectAddedPayload,
|
||||
StageAttrs,
|
||||
} from './types';
|
||||
import { getEntityIdentifier, isDrawableEntity } from './types';
|
||||
|
||||
@ -564,25 +561,6 @@ const migrate = (state: any): any => {
|
||||
return state;
|
||||
};
|
||||
|
||||
// Ephemeral state that does not need to be in redux
|
||||
export const $isPreviewVisible = atom(true);
|
||||
export const $stageAttrs = atom<StageAttrs>({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
scale: 0,
|
||||
});
|
||||
export const $shouldShowStagedImage = atom(true);
|
||||
export const $isDrawing = atom<boolean>(false);
|
||||
export const $isMouseDown = atom<boolean>(false);
|
||||
export const $lastAddedPoint = atom<Coordinate | null>(null);
|
||||
export const $lastMouseDownPos = atom<Coordinate | null>(null);
|
||||
export const $lastCursorPos = atom<Coordinate | null>(null);
|
||||
export const $spaceKey = atom<boolean>(false);
|
||||
export const $transformingEntity = atom<CanvasEntityIdentifier | null>(null);
|
||||
export const $isProcessingTransform = atom<boolean>(false);
|
||||
|
||||
export const canvasV2PersistConfig: PersistConfig<CanvasV2State> = {
|
||||
name: canvasV2Slice.name,
|
||||
initialState,
|
||||
|
@ -5,7 +5,6 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { CanvasEntityListMenuButton } from 'features/controlLayers/components/CanvasEntityList/CanvasEntityListMenuButton';
|
||||
import { CanvasPanelContent } from 'features/controlLayers/components/CanvasPanelContent';
|
||||
import { $isPreviewVisible } from 'features/controlLayers/store/canvasV2Slice';
|
||||
import { selectEntityCount } from 'features/controlLayers/store/selectors';
|
||||
import { isImageViewerOpenChanged } from 'features/gallery/store/gallerySlice';
|
||||
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
|
||||
@ -56,7 +55,6 @@ const ParametersPanelTextToImage = () => {
|
||||
if (i === 1) {
|
||||
dispatch(isImageViewerOpenChanged(false));
|
||||
}
|
||||
$isPreviewVisible.set(i === 0);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user