feat(ui): add selected entity status to HUD

This commit is contained in:
psychedelicious
2024-09-09 10:06:06 +10:00
parent eff9ddc980
commit 1b65884dbe
4 changed files with 151 additions and 18 deletions

View File

@@ -1824,7 +1824,16 @@
"HUD": {
"bbox": "Bbox",
"scaledBbox": "Scaled Bbox",
"autoSave": "Auto Save"
"autoSave": "Auto Save",
"entityStatus": {
"selectedEntity": "Selected Entity",
"filtering": "Filtering",
"transforming": "Transforming",
"locked": "Locked",
"hidden": "Hidden",
"disabled": "Disabled",
"enabled": "Enabled"
}
}
},
"upscaling": {

View File

@@ -2,26 +2,31 @@ import { Grid } from '@invoke-ai/ui-library';
import { CanvasHUDItemAutoSave } from 'features/controlLayers/components/HUD/CanvasHUDItemAutoSave';
import { CanvasHUDItemBbox } from 'features/controlLayers/components/HUD/CanvasHUDItemBbox';
import { CanvasHUDItemScaledBbox } from 'features/controlLayers/components/HUD/CanvasHUDItemScaledBbox';
import { CanvasHUDItemSelectedEntityStatus } from 'features/controlLayers/components/HUD/CanvasHUDItemSelectedEntityStatus';
import { CanvasHUDItemSnapToGrid } from 'features/controlLayers/components/HUD/CanvasHUDItemSnapToGrid';
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { memo } from 'react';
export const CanvasHUD = memo(() => {
return (
<Grid
bg="base.900"
borderBottomEndRadius="base"
p={2}
gap={2}
borderRadius="base"
templateColumns="1fr 1fr"
opacity={0.6}
minW={64}
>
<CanvasHUDItemBbox />
<CanvasHUDItemScaledBbox />
<CanvasHUDItemSnapToGrid />
<CanvasHUDItemAutoSave />
</Grid>
<CanvasManagerProviderGate>
<Grid
bg="base.900"
borderBottomEndRadius="base"
p={2}
gap={2}
borderRadius="base"
templateColumns="1fr 1fr"
opacity={0.6}
minW={64}
>
<CanvasHUDItemBbox />
<CanvasHUDItemScaledBbox />
<CanvasHUDItemSnapToGrid />
<CanvasHUDItemAutoSave />
<CanvasHUDItemSelectedEntityStatus />
</Grid>
</CanvasManagerProviderGate>
);
});

View File

@@ -1,14 +1,23 @@
import { GridItem, Text } from '@invoke-ai/ui-library';
import type { Property } from 'csstype';
import { memo } from 'react';
export const CanvasHUDItem = memo(({ label, value }: { label: string; value: string | number }) => {
type Props = {
label: string;
value: string | number;
color?: Property.Color;
};
export const CanvasHUDItem = memo(({ label, value, color }: Props) => {
return (
<>
<GridItem>
<Text textAlign="end">{label}: </Text>
</GridItem>
<GridItem fontWeight="semibold">
<Text textAlign="end">{value}</Text>
<Text textAlign="end" color={color}>
{value}
</Text>
</GridItem>
</>
);

View File

@@ -0,0 +1,110 @@
import { useStore } from '@nanostores/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import type { Property } from 'csstype';
import { CanvasHUDItem } from 'features/controlLayers/components/HUD/CanvasHUDItem';
import { useEntityAdapter } from 'features/controlLayers/hooks/useEntityAdapter';
import { useEntityTypeIsHidden } from 'features/controlLayers/hooks/useEntityTypeIsHidden';
import {
selectCanvasSlice,
selectEntityOrThrow,
selectSelectedEntityIdentifier,
} from 'features/controlLayers/store/selectors';
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
import { atom } from 'nanostores';
import { memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
type ContentProps = {
entityIdentifier: CanvasEntityIdentifier;
};
const $isFilteringFallback = atom(false);
type EntityStatus = {
value: string;
color?: Property.Color;
};
const CanvasHUDItemSelectedEntityStatusContent = memo(({ entityIdentifier }: ContentProps) => {
const { t } = useTranslation();
const adapter = useEntityAdapter(entityIdentifier);
const selectIsEnabled = useMemo(
() => createSelector(selectCanvasSlice, (canvas) => selectEntityOrThrow(canvas, entityIdentifier).isEnabled),
[entityIdentifier]
);
const selectIsLocked = useMemo(
() => createSelector(selectCanvasSlice, (canvas) => selectEntityOrThrow(canvas, entityIdentifier).isLocked),
[entityIdentifier]
);
const isEnabled = useAppSelector(selectIsEnabled);
const isLocked = useAppSelector(selectIsLocked);
const isHidden = useEntityTypeIsHidden(entityIdentifier.type);
const isFiltering = useStore(adapter.filterer?.$isFiltering ?? $isFilteringFallback);
const isTransforming = useStore(adapter.transformer.$isTransforming);
const status = useMemo<EntityStatus>(() => {
if (isFiltering) {
return {
value: t('controlLayers.HUD.entityStatus.filtering'),
color: 'invokeYellow.300',
};
}
if (isTransforming) {
return {
value: t('controlLayers.HUD.entityStatus.transforming'),
color: 'invokeYellow.300',
};
}
if (isHidden) {
return {
value: t('controlLayers.HUD.entityStatus.hidden'),
color: 'invokePurple.300',
};
}
if (isLocked) {
return {
value: t('controlLayers.HUD.entityStatus.locked'),
color: 'invokeRed.300',
};
}
if (!isEnabled) {
return {
value: t('controlLayers.HUD.entityStatus.disabled'),
color: 'invokeRed.300',
};
}
return {
value: t('controlLayers.HUD.entityStatus.enabled'),
};
}, [isFiltering, isTransforming, isHidden, isLocked, isEnabled, t]);
return (
<>
<CanvasHUDItem
label={t('controlLayers.HUD.entityStatus.selectedEntity')}
value={status.value}
color={status.color}
/>
</>
);
});
CanvasHUDItemSelectedEntityStatusContent.displayName = 'CanvasHUDItemSelectedEntityStatusContent';
export const CanvasHUDItemSelectedEntityStatus = memo(() => {
const selectedEntityIdentifier = useAppSelector(selectSelectedEntityIdentifier);
if (!selectedEntityIdentifier) {
return null;
}
return <CanvasHUDItemSelectedEntityStatusContent entityIdentifier={selectedEntityIdentifier} />;
});
CanvasHUDItemSelectedEntityStatus.displayName = 'CanvasHUDItemSelectedEntityStatus';