feat(ui): restore minimal HUD

This commit is contained in:
psychedelicious 2024-08-29 21:30:52 +10:00
parent e933d1ae2b
commit 284f768810
6 changed files with 64 additions and 49 deletions

View File

@ -1683,6 +1683,7 @@
"deletePrompt": "Delete Prompt", "deletePrompt": "Delete Prompt",
"resetRegion": "Reset Region", "resetRegion": "Reset Region",
"debugLayers": "Debug Layers", "debugLayers": "Debug Layers",
"showHUD": "Show HUD",
"rectangle": "Rectangle", "rectangle": "Rectangle",
"maskFill": "Mask Fill", "maskFill": "Mask Fill",
"addPositivePrompt": "Add $t(common.positivePrompt)", "addPositivePrompt": "Add $t(common.positivePrompt)",

View File

@ -1,53 +1,27 @@
import { Box, Flex, Text } from '@invoke-ai/ui-library'; import { Grid, GridItem, Text } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks'; import { useAppSelector } from 'app/store/storeHooks';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { selectCanvasSlice } from 'features/controlLayers/store/selectors'; import { selectCanvasSlice } from 'features/controlLayers/store/selectors';
import { round } from 'lodash-es';
import { memo } from 'react'; import { memo } from 'react';
const selectBbox = createSelector(selectCanvasSlice, (canvas) => canvas.bbox); const selectBbox = createSelector(selectCanvasSlice, (canvas) => canvas.bbox);
export const HeadsUpDisplay = memo(() => { export const HeadsUpDisplay = memo(() => {
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(selectBbox); const bbox = useAppSelector(selectBbox);
return ( return (
<Flex flexDir="column" bg="blackAlpha.400" borderBottomEndRadius="base" p={2} minW={64} gap={2}> <Grid
<HUDItem label="Zoom" value={`${round(stageAttrs.scale * 100, 2)}%`} /> bg="base.900"
<HUDItem label="Stage Pos" value={`${round(stageAttrs.x, 3)}, ${round(stageAttrs.y, 3)}`} /> borderBottomEndRadius="base"
<HUDItem p={2}
label="Stage Size" gap={2}
value={`${round(stageAttrs.width / stageAttrs.scale, 2)}×${round(stageAttrs.height / stageAttrs.scale, 2)} px`} borderRadius="base"
/> templateColumns="auto auto"
<HUDItem label="BBox Size" value={`${bbox.rect.width}×${bbox.rect.height} px`} /> opacity={0.6}
<HUDItem label="BBox Position" value={`${bbox.rect.x}, ${bbox.rect.y}`} /> >
<HUDItem label="BBox Width % 8" value={round(bbox.rect.width % 8, 2)} /> <HUDItem label="BBox" value={`${bbox.rect.width}×${bbox.rect.height} px`} />
<HUDItem label="BBox Height % 8" value={round(bbox.rect.height % 8, 2)} /> <HUDItem label="Scaled BBox" value={`${bbox.scaledSize.width}×${bbox.scaledSize.height} px`} />
<HUDItem label="BBox X % 8" value={round(bbox.rect.x % 8, 2)} /> </Grid>
<HUDItem label="BBox Y % 8" value={round(bbox.rect.y % 8, 2)} />
<HUDItem
label="Cursor Position"
value={cursorPos ? `${round(cursorPos.x, 2)}, ${round(cursorPos.y, 2)}` : '?, ?'}
/>
<HUDItem label="Is Drawing" value={isDrawing ? 'True' : 'False'} />
<HUDItem label="Is Mouse Down" value={isMouseDown ? 'True' : 'False'} />
<HUDItem
label="Last Mouse Down Pos"
value={lastMouseDownPos ? `${round(lastMouseDownPos.x, 2)}, ${round(lastMouseDownPos.y, 2)}` : '?, ?'}
/>
<HUDItem
label="Last Added Point"
value={lastAddedPoint ? `${round(lastAddedPoint.x, 2)}, ${round(lastAddedPoint.y, 2)}` : '?, ?'}
/>
</Flex>
); );
}); });
@ -55,12 +29,14 @@ HeadsUpDisplay.displayName = 'HeadsUpDisplay';
const HUDItem = memo(({ label, value }: { label: string; value: string | number }) => { const HUDItem = memo(({ label, value }: { label: string; value: string | number }) => {
return ( return (
<Box display="inline-block" lineHeight={1}> <>
<Text as="span">{label}: </Text> <GridItem>
<Text as="span" fontWeight="semibold"> <Text textAlign="end">{label}: </Text>
{value} </GridItem>
</Text> <GridItem fontWeight="semibold">
</Box> <Text>{value}</Text>
</GridItem>
</>
); );
}); });

View File

@ -18,6 +18,7 @@ import { CanvasSettingsInvertScrollCheckbox } from 'features/controlLayers/compo
import { CanvasSettingsLogDebugInfoButton } from 'features/controlLayers/components/Settings/CanvasSettingsLogDebugInfo'; import { CanvasSettingsLogDebugInfoButton } from 'features/controlLayers/components/Settings/CanvasSettingsLogDebugInfo';
import { CanvasSettingsRecalculateRectsButton } from 'features/controlLayers/components/Settings/CanvasSettingsRecalculateRectsButton'; import { CanvasSettingsRecalculateRectsButton } from 'features/controlLayers/components/Settings/CanvasSettingsRecalculateRectsButton';
import { CanvasSettingsResetButton } from 'features/controlLayers/components/Settings/CanvasSettingsResetButton'; import { CanvasSettingsResetButton } from 'features/controlLayers/components/Settings/CanvasSettingsResetButton';
import { CanvasSettingsShowHUDSwitch } from 'features/controlLayers/components/Settings/CanvasSettingsShowHUDSwitch';
import { memo } from 'react'; import { memo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { RiSettings4Fill } from 'react-icons/ri'; import { RiSettings4Fill } from 'react-icons/ri';
@ -37,6 +38,7 @@ export const CanvasSettingsPopover = memo(() => {
<CanvasSettingsInvertScrollCheckbox /> <CanvasSettingsInvertScrollCheckbox />
<CanvasSettingsClipToBboxCheckbox /> <CanvasSettingsClipToBboxCheckbox />
<CanvasSettingsDynamicGridSwitch /> <CanvasSettingsDynamicGridSwitch />
<CanvasSettingsShowHUDSwitch />
<CanvasSettingsResetButton /> <CanvasSettingsResetButton />
<DebugSettings /> <DebugSettings />
</Flex> </Flex>

View File

@ -0,0 +1,28 @@
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { selectCanvasSettingsSlice, settingsShowHUDToggled } from 'features/controlLayers/store/canvasSettingsSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
const selectShowHUD = createSelector(selectCanvasSettingsSlice, (canvasSettings) => canvasSettings.showHUD);
export const CanvasSettingsShowHUDSwitch = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const showHUD = useAppSelector(selectShowHUD);
const onChange = useCallback(() => {
dispatch(settingsShowHUDToggled());
}, [dispatch]);
return (
<FormControl>
<FormLabel m={0} flexGrow={1}>
{t('controlLayers.showHUD')}
</FormLabel>
<Switch size="sm" isChecked={showHUD} onChange={onChange} />
</FormControl>
);
});
CanvasSettingsShowHUDSwitch.displayName = 'CanvasSettingsShowHUDSwitch';

View File

@ -48,9 +48,11 @@ const useStageRenderer = (stage: Konva.Stage, container: HTMLDivElement | null)
}; };
const selectDynamicGrid = createSelector(selectCanvasSettingsSlice, (canvasSettings) => canvasSettings.dynamicGrid); const selectDynamicGrid = createSelector(selectCanvasSettingsSlice, (canvasSettings) => canvasSettings.dynamicGrid);
const selectShowHUD = createSelector(selectCanvasSettingsSlice, (canvasSettings) => canvasSettings.showHUD);
export const StageComponent = memo(() => { export const StageComponent = memo(() => {
const dynamicGrid = useAppSelector(selectDynamicGrid); const dynamicGrid = useAppSelector(selectDynamicGrid);
const showHUD = useAppSelector(selectShowHUD);
const [stage] = useState( const [stage] = useState(
() => () =>
@ -99,9 +101,11 @@ export const StageComponent = memo(() => {
overflow="hidden" overflow="hidden"
data-testid="control-layers-canvas" data-testid="control-layers-canvas"
/> />
{showHUD && (
<Flex position="absolute" top={1} insetInlineStart={1} pointerEvents="none"> <Flex position="absolute" top={1} insetInlineStart={1} pointerEvents="none">
<HeadsUpDisplay /> <HeadsUpDisplay />
</Flex> </Flex>
)}
</Flex> </Flex>
); );
}); });

View File

@ -35,10 +35,14 @@ export const canvasSettingsSlice = createSlice({
settingsAutoSaveToggled: (state) => { settingsAutoSaveToggled: (state) => {
state.autoSave = !state.autoSave; state.autoSave = !state.autoSave;
}, },
settingsShowHUDToggled: (state) => {
state.showHUD = !state.showHUD;
},
}, },
}); });
export const { clipToBboxChanged, settingsAutoSaveToggled, settingsDynamicGridToggled } = canvasSettingsSlice.actions; export const { clipToBboxChanged, settingsAutoSaveToggled, settingsDynamicGridToggled, settingsShowHUDToggled } =
canvasSettingsSlice.actions;
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const migrate = (state: any): any => { const migrate = (state: any): any => {