From d81cd050ef421d4acd83c59cd95c01dbd6f18770 Mon Sep 17 00:00:00 2001
From: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Date: Mon, 2 Sep 2024 17:10:24 +1000
Subject: [PATCH] feat(ui): streamline manager -> react transform interface
---
.../components/Transform/Transform.tsx | 21 ++++++-------------
.../common/CanvasEntityMenuItemsTransform.tsx | 4 ++--
.../controlLayers/hooks/useIsTransforming.ts | 2 +-
.../konva/CanvasEntityTransformer.ts | 4 ++--
.../controlLayers/konva/CanvasManager.ts | 2 +-
.../konva/CanvasStateApiModule.ts | 5 +++--
.../controlLayers/konva/CanvasToolModule.ts | 2 +-
7 files changed, 16 insertions(+), 24 deletions(-)
diff --git a/invokeai/frontend/web/src/features/controlLayers/components/Transform/Transform.tsx b/invokeai/frontend/web/src/features/controlLayers/components/Transform/Transform.tsx
index 715ba40ee2..ffcfacebef 100644
--- a/invokeai/frontend/web/src/features/controlLayers/components/Transform/Transform.tsx
+++ b/invokeai/frontend/web/src/features/controlLayers/components/Transform/Transform.tsx
@@ -1,19 +1,14 @@
import { Button, ButtonGroup, Flex, Heading, Spacer } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
-import {
- EntityIdentifierContext,
- useEntityIdentifierContext,
-} from 'features/controlLayers/contexts/EntityIdentifierContext';
-import { useEntityAdapter } from 'features/controlLayers/hooks/useEntityAdapter';
+import type { CanvasEntityLayerAdapter } from 'features/controlLayers/konva/CanvasEntityLayerAdapter';
+import type { CanvasEntityMaskAdapter } from 'features/controlLayers/konva/CanvasEntityMaskAdapter';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiArrowsCounterClockwiseBold, PiArrowsOutBold, PiCheckBold, PiXBold } from 'react-icons/pi';
-const TransformBox = memo(() => {
+const TransformBox = memo(({ adapter }: { adapter: CanvasEntityLayerAdapter | CanvasEntityMaskAdapter }) => {
const { t } = useTranslation();
- const entityIdentifier = useEntityIdentifierContext();
- const adapter = useEntityAdapter(entityIdentifier);
const isProcessing = useStore(adapter.transformer.$isProcessing);
return (
@@ -79,15 +74,11 @@ TransformBox.displayName = 'Transform';
export const Transform = () => {
const canvasManager = useCanvasManager();
- const transformingEntity = useStore(canvasManager.stateApi.$transformingEntity);
+ const adapter = useStore(canvasManager.stateApi.$transformingAdapter);
- if (!transformingEntity) {
+ if (!adapter) {
return null;
}
- return (
-
-
-
- );
+ return ;
};
diff --git a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsTransform.tsx b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsTransform.tsx
index 3d5fe022c3..e3fdac1f72 100644
--- a/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsTransform.tsx
+++ b/invokeai/frontend/web/src/features/controlLayers/components/common/CanvasEntityMenuItemsTransform.tsx
@@ -12,14 +12,14 @@ export const CanvasEntityMenuItemsTransform = memo(() => {
const entityIdentifier = useEntityIdentifierContext();
const canvasManager = useCanvasManager();
const adapter = useEntityAdapter(entityIdentifier);
- const transformingEntity = useStore(canvasManager.stateApi.$transformingEntity);
+ const isTransforming = useStore(canvasManager.stateApi.$isTranforming);
const onClick = useCallback(() => {
adapter.transformer.startTransform();
}, [adapter.transformer]);
return (
- } isDisabled={Boolean(transformingEntity)}>
+ } isDisabled={isTransforming}>
{t('controlLayers.transform.transform')}
);
diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/useIsTransforming.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/useIsTransforming.ts
index dac961350e..bf2407af35 100644
--- a/invokeai/frontend/web/src/features/controlLayers/hooks/useIsTransforming.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/hooks/useIsTransforming.ts
@@ -4,7 +4,7 @@ import { useMemo } from 'react';
export const useIsTransforming = () => {
const canvasManager = useCanvasManager();
- const transformingEntity = useStore(canvasManager.stateApi.$transformingEntity);
+ const transformingEntity = useStore(canvasManager.stateApi.$transformingAdapter);
const isTransforming = useMemo(() => {
return Boolean(transformingEntity);
}, [transformingEntity]);
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEntityTransformer.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEntityTransformer.ts
index edefe15deb..ecc4128130 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEntityTransformer.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEntityTransformer.ts
@@ -573,7 +573,7 @@ export class CanvasEntityTransformer extends CanvasModuleBase {
const shouldListen = this.manager.stateApi.$tool.get() !== 'view';
this.parent.konva.layer.listening(shouldListen);
this.setInteractionMode('all');
- this.manager.stateApi.$transformingEntity.set(this.parent.getEntityIdentifier());
+ this.manager.stateApi.$transformingAdapter.set(this.parent);
};
/**
@@ -608,7 +608,7 @@ export class CanvasEntityTransformer extends CanvasModuleBase {
// canceled a transformation. In either case, the scale should be reset.
this.resetTransform();
this.syncInteractionState();
- this.manager.stateApi.$transformingEntity.set(null);
+ this.manager.stateApi.$transformingAdapter.set(null);
this.$isProcessing.set(false);
};
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts
index 6fb136daf7..343fa7fd65 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts
@@ -137,7 +137,7 @@ export class CanvasManager extends CanvasModuleBase {
this.log.debug('Initializing canvas manager module');
// These atoms require the canvas manager to be set up before we can provide their initial values
- this.stateApi.$transformingEntity.set(null);
+ this.stateApi.$transformingAdapter.set(null);
this.stateApi.$toolState.set(this.stateApi.getToolState());
this.stateApi.$selectedEntityIdentifier.set(this.stateApi.getCanvasState().selectedEntityIdentifier);
this.stateApi.$currentFill.set(this.stateApi.getCurrentFill());
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApiModule.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApiModule.ts
index 31b1ba09b9..9a7519c23e 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApiModule.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApiModule.ts
@@ -43,7 +43,7 @@ import type {
} from 'features/controlLayers/store/types';
import { RGBA_BLACK } from 'features/controlLayers/store/types';
import type { WritableAtom } from 'nanostores';
-import { atom } from 'nanostores';
+import { atom, computed } from 'nanostores';
import type { Logger } from 'roarr';
import { queueApi } from 'services/api/endpoints/queue';
import type { BatchConfig } from 'services/api/types';
@@ -245,7 +245,8 @@ export class CanvasStateApiModule extends CanvasModuleBase {
}
};
- $transformingEntity = atom(null);
+ $transformingAdapter = atom(null);
+ $isTranforming = computed(this.$transformingAdapter, (transformingAdapter) => Boolean(transformingAdapter));
$toolState: WritableAtom = atom();
$currentFill: WritableAtom = atom();
diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasToolModule.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasToolModule.ts
index 87c2503c8b..6f03b1580b 100644
--- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasToolModule.ts
+++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasToolModule.ts
@@ -119,7 +119,7 @@ export class CanvasToolModule extends CanvasModuleBase {
isDrawableEntity(selectedEntity.state);
// Update the stage's pointer style
- if (Boolean(this.manager.stateApi.$transformingEntity.get()) || renderedEntityCount === 0) {
+ if (this.manager.stateApi.$isTranforming.get() || renderedEntityCount === 0) {
// We are transforming and/or have no layers, so we should not render any tool
stage.container.style.cursor = 'default';
} else if (tool === 'view') {