feat(ui): store all stage attrs in nanostores

This commit is contained in:
psychedelicious 2024-06-12 11:57:14 +10:00
parent 2c3ac972e5
commit 154e3e6f64
6 changed files with 55 additions and 24 deletions

View File

@ -1,18 +1,20 @@
import { Box, Flex, Text } from '@invoke-ai/ui-library'; import { Box, Flex, Text } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { useAppSelector } from 'app/store/storeHooks'; import { useAppSelector } from 'app/store/storeHooks';
import { $stageScale } from 'features/controlLayers/store/controlLayersSlice'; import { $stageAttrs } from 'features/controlLayers/store/controlLayersSlice';
import { round } from 'lodash-es'; import { round } from 'lodash-es';
import { memo } from 'react'; import { memo } from 'react';
export const HeadsUpDisplay = memo(() => { export const HeadsUpDisplay = memo(() => {
const stageScale = useStore($stageScale); const stageAttrs = useStore($stageAttrs);
const layerCount = useAppSelector((s) => s.controlLayers.present.layers.length); const layerCount = useAppSelector((s) => s.controlLayers.present.layers.length);
const bbox = useAppSelector((s) => s.controlLayers.present.bbox); const bbox = useAppSelector((s) => s.controlLayers.present.bbox);
return ( return (
<Flex flexDir="column" bg="blackAlpha.400" borderBottomEndRadius="base" p={2} minW={64} gap={2}> <Flex flexDir="column" bg="blackAlpha.400" borderBottomEndRadius="base" p={2} minW={64} gap={2}>
<HUDItem label="Scale" value={round(stageScale, 3)} /> <HUDItem label="Scale" value={round(stageAttrs.scale, 3)} />
<HUDItem label="Stage Pos" value={`${round(stageAttrs.x, 3)}, ${round(stageAttrs.y, 3)}`} />
<HUDItem label="Stage Size" value={`${round(stageAttrs.width, 3)}, ${round(stageAttrs.height, 3)}`} />
<HUDItem label="Layer Count" value={layerCount} /> <HUDItem label="Layer Count" value={layerCount} />
<HUDItem label="BBox Size" value={`${bbox.width}×${bbox.height}`} /> <HUDItem label="BBox Size" value={`${bbox.width}×${bbox.height}`} />
<HUDItem label="BBox Position" value={`${bbox.x}, ${bbox.y}`} /> <HUDItem label="BBox Position" value={`${bbox.x}, ${bbox.y}`} />

View File

@ -26,8 +26,7 @@ import {
$lastMouseDownPos, $lastMouseDownPos,
$selectedLayer, $selectedLayer,
$shouldInvertBrushSizeScrollDirection, $shouldInvertBrushSizeScrollDirection,
$stagePos, $stageAttrs,
$stageScale,
$tool, $tool,
$toolBuffer, $toolBuffer,
bboxChanged, bboxChanged,
@ -89,7 +88,6 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
const lastCursorPos = useStore($lastCursorPos); const lastCursorPos = useStore($lastCursorPos);
const lastMouseDownPos = useStore($lastMouseDownPos); const lastMouseDownPos = useStore($lastMouseDownPos);
const isMouseDown = useStore($isMouseDown); const isMouseDown = useStore($isMouseDown);
const stageScale = useStore($stageScale);
const isDrawing = useStore($isDrawing); const isDrawing = useStore($isDrawing);
const brushColor = useAppSelector(selectBrushColor); const brushColor = useAppSelector(selectBrushColor);
const selectedLayer = useAppSelector(selectSelectedLayer); const selectedLayer = useAppSelector(selectSelectedLayer);
@ -197,8 +195,7 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
$lastMouseDownPos, $lastMouseDownPos,
$lastCursorPos, $lastCursorPos,
$lastAddedPoint, $lastAddedPoint,
$stageScale, $stageAttrs,
$stagePos,
$brushSize, $brushSize,
$brushColor, $brushColor,
$brushSpacingPx, $brushSpacingPx,
@ -236,6 +233,13 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null,
const fitStageToContainer = () => { const fitStageToContainer = () => {
stage.width(container.offsetWidth); stage.width(container.offsetWidth);
stage.height(container.offsetHeight); stage.height(container.offsetHeight);
$stageAttrs.set({
x: stage.x(),
y: stage.y(),
width: stage.width(),
height: stage.height(),
scale: stage.scaleX(),
});
}; };
const resizeObserver = new ResizeObserver(fitStageToContainer); const resizeObserver = new ResizeObserver(fitStageToContainer);

View File

@ -1,15 +1,16 @@
import { calculateNewBrushSize } from 'features/canvas/hooks/useCanvasZoom'; import { calculateNewBrushSize } from 'features/canvas/hooks/useCanvasZoom';
import { CANVAS_SCALE_BY, MAX_CANVAS_SCALE, MIN_CANVAS_SCALE } from 'features/canvas/util/constants'; import { CANVAS_SCALE_BY, MAX_CANVAS_SCALE, MIN_CANVAS_SCALE } from 'features/canvas/util/constants';
import { getIsMouseDown, getScaledFlooredCursorPosition, snapPosToStage } from 'features/controlLayers/konva/util'; import { getIsMouseDown, getScaledFlooredCursorPosition, snapPosToStage } from 'features/controlLayers/konva/util';
import { import type {
type AddBrushLineArg, AddBrushLineArg,
type AddEraserLineArg, AddEraserLineArg,
type AddPointToLineArg, AddPointToLineArg,
type AddRectShapeArg, AddRectShapeArg,
DEFAULT_RGBA_COLOR, Layer,
type Layer, StageAttrs,
type Tool, Tool,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { DEFAULT_RGBA_COLOR } from 'features/controlLayers/store/types';
import type Konva from 'konva'; import type Konva from 'konva';
import type { Vector2d } from 'konva/lib/types'; import type { Vector2d } from 'konva/lib/types';
import { clamp } from 'lodash-es'; import { clamp } from 'lodash-es';
@ -27,8 +28,7 @@ type SetStageEventHandlersArg = {
$lastMouseDownPos: WritableAtom<Vector2d | null>; $lastMouseDownPos: WritableAtom<Vector2d | null>;
$lastCursorPos: WritableAtom<Vector2d | null>; $lastCursorPos: WritableAtom<Vector2d | null>;
$lastAddedPoint: WritableAtom<Vector2d | null>; $lastAddedPoint: WritableAtom<Vector2d | null>;
$stageScale: WritableAtom<number>; $stageAttrs: WritableAtom<StageAttrs>;
$stagePos: WritableAtom<Vector2d>;
$brushColor: WritableAtom<RgbaColor>; $brushColor: WritableAtom<RgbaColor>;
$brushSize: WritableAtom<number>; $brushSize: WritableAtom<number>;
$brushSpacingPx: WritableAtom<number>; $brushSpacingPx: WritableAtom<number>;
@ -93,8 +93,7 @@ export const setStageEventHandlers = ({
$lastMouseDownPos, $lastMouseDownPos,
$lastCursorPos, $lastCursorPos,
$lastAddedPoint, $lastAddedPoint,
$stagePos, $stageAttrs,
$stageScale,
$brushColor, $brushColor,
$brushSize, $brushSize,
$brushSpacingPx, $brushSpacingPx,
@ -333,15 +332,31 @@ export const setStageEventHandlers = ({
stage.scaleX(newScale); stage.scaleX(newScale);
stage.scaleY(newScale); stage.scaleY(newScale);
stage.position(newPos); stage.position(newPos);
$stageScale.set(newScale); $stageAttrs.set({ ...newPos, width: stage.width(), height: stage.height(), scale: newScale });
$stagePos.set(newPos);
} }
}); });
stage.on('dragmove', () => {
$stageAttrs.set({
x: stage.x(),
y: stage.y(),
width: stage.width(),
height: stage.height(),
scale: stage.scaleX(),
});
});
stage.on('dragend', () => { stage.on('dragend', () => {
// Stage position should always be an integer, else we get fractional pixels which are blurry // Stage position should always be an integer, else we get fractional pixels which are blurry
stage.x(Math.floor(stage.x())); stage.x(Math.floor(stage.x()));
stage.y(Math.floor(stage.y())); stage.y(Math.floor(stage.y()));
$stageAttrs.set({
x: stage.x(),
y: stage.y(),
width: stage.width(),
height: stage.height(),
scale: stage.scaleX(),
});
}); });
const onKeyDown = (e: KeyboardEvent) => { const onKeyDown = (e: KeyboardEvent) => {

View File

@ -13,6 +13,9 @@ export const PREVIEW_RECT_ID = 'preview_layer.rect';
export const PREVIEW_GENERATION_BBOX_GROUP = 'preview_layer.gen_bbox_group'; export const PREVIEW_GENERATION_BBOX_GROUP = 'preview_layer.gen_bbox_group';
export const PREVIEW_GENERATION_BBOX_TRANSFORMER = 'preview_layer.gen_bbox_transformer'; export const PREVIEW_GENERATION_BBOX_TRANSFORMER = 'preview_layer.gen_bbox_transformer';
export const PREVIEW_GENERATION_BBOX_DUMMY_RECT = 'preview_layer.gen_bbox_dummy_rect'; export const PREVIEW_GENERATION_BBOX_DUMMY_RECT = 'preview_layer.gen_bbox_dummy_rect';
export const PREVIEW_DOCUMENT_SIZE_GROUP = 'preview_layer.doc_size_group';
export const PREVIEW_DOCUMENT_SIZE_STAGE_RECT = 'preview_layer.doc_size_stage_rect';
export const PREVIEW_DOCUMENT_SIZE_DOCUMENT_RECT = 'preview_layer.doc_size_doc_rect';
// Names for Konva layers and objects (comparable to CSS classes) // Names for Konva layers and objects (comparable to CSS classes)
export const LAYER_BBOX_NAME = 'layer.bbox'; export const LAYER_BBOX_NAME = 'layer.bbox';

View File

@ -60,6 +60,7 @@ import type {
RasterLayer, RasterLayer,
RegionalGuidanceLayer, RegionalGuidanceLayer,
RgbaColor, RgbaColor,
StageAttrs,
Tool, Tool,
} from './types'; } from './types';
import { import {
@ -997,8 +998,13 @@ export const $lastCursorPos = atom<Vector2d | null>(null);
export const $isPreviewVisible = atom(true); export const $isPreviewVisible = atom(true);
export const $lastAddedPoint = atom<Vector2d | null>(null); export const $lastAddedPoint = atom<Vector2d | null>(null);
export const $isSpaceDown = atom(false); export const $isSpaceDown = atom(false);
export const $stageScale = atom<number>(1); export const $stageAttrs = atom<StageAttrs>({
export const $stagePos = atom<Vector2d>({ x: 0, y: 0 }); x: 0,
y: 0,
width: 0,
height: 0,
scale: 0,
});
// Some nanostores that are manually synced to redux state to provide imperative access // Some nanostores that are manually synced to redux state to provide imperative access
// TODO(psyche): This is a hack, figure out another way to handle this... // TODO(psyche): This is a hack, figure out another way to handle this...

View File

@ -272,6 +272,7 @@ export type ControlLayersState = {
bbox: IRect; bbox: IRect;
}; };
export type StageAttrs = { x: number; y: number; width: number; height: number; scale: number };
export type AddEraserLineArg = { layerId: string; points: [number, number, number, number] }; export type AddEraserLineArg = { layerId: string; points: [number, number, number, number] };
export type AddBrushLineArg = AddEraserLineArg & { color: RgbaColor }; export type AddBrushLineArg = AddEraserLineArg & { color: RgbaColor };
export type AddPointToLineArg = { layerId: string; point: [number, number] }; export type AddPointToLineArg = { layerId: string; point: [number, number] };