mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): remove select layer on click in canvas
It's very easy to end up in a spot where you cannot select a layer at all to move it around. Too tricky to handle otherwise.
This commit is contained in:
parent
22f160bfcc
commit
a357a1ac9d
@ -11,7 +11,6 @@ import {
|
|||||||
$tool,
|
$tool,
|
||||||
isMaskedGuidanceLayer,
|
isMaskedGuidanceLayer,
|
||||||
layerBboxChanged,
|
layerBboxChanged,
|
||||||
layerSelected,
|
|
||||||
layerTranslated,
|
layerTranslated,
|
||||||
selectRegionalPromptsSlice,
|
selectRegionalPromptsSlice,
|
||||||
} from 'features/regionalPrompts/store/regionalPromptsSlice';
|
} from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
@ -66,13 +65,6 @@ const useStageRenderer = (
|
|||||||
[dispatch]
|
[dispatch]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onBboxMouseDown = useCallback(
|
|
||||||
(layerId: string) => {
|
|
||||||
dispatch(layerSelected(layerId));
|
|
||||||
},
|
|
||||||
[dispatch]
|
|
||||||
);
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
log.trace('Initializing stage');
|
log.trace('Initializing stage');
|
||||||
if (!container) {
|
if (!container) {
|
||||||
@ -182,8 +174,8 @@ const useStageRenderer = (
|
|||||||
// Preview should not display bboxes
|
// Preview should not display bboxes
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
renderers.renderBbox(stage, state.layers, state.selectedLayerId, tool, onBboxChanged, onBboxMouseDown);
|
renderers.renderBbox(stage, state.layers, tool, onBboxChanged);
|
||||||
}, [stage, asPreview, state.layers, state.selectedLayerId, tool, onBboxChanged, onBboxMouseDown, renderers]);
|
}, [stage, asPreview, state.layers, tool, onBboxChanged, renderers]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
log.trace('Rendering background');
|
log.trace('Rendering background');
|
||||||
|
@ -142,10 +142,12 @@ export const regionalPromptsSlice = createSlice({
|
|||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
layerSelected: (state, action: PayloadAction<string>) => {
|
layerSelected: (state, action: PayloadAction<string>) => {
|
||||||
for (const layer of state.layers) {
|
for (const layer of state.layers.filter(isRenderableLayer)) {
|
||||||
if (isRenderableLayer(layer) && layer.id === action.payload) {
|
if (layer.id === action.payload) {
|
||||||
layer.isSelected = true;
|
layer.isSelected = true;
|
||||||
state.selectedLayerId = action.payload;
|
state.selectedLayerId = action.payload;
|
||||||
|
} else {
|
||||||
|
layer.isSelected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -43,8 +43,6 @@ import { assert } from 'tsafe';
|
|||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
const BBOX_SELECTED_STROKE = 'rgba(78, 190, 255, 1)';
|
const BBOX_SELECTED_STROKE = 'rgba(78, 190, 255, 1)';
|
||||||
const BBOX_NOT_SELECTED_STROKE = 'rgba(255, 255, 255, 0.353)';
|
|
||||||
const BBOX_NOT_SELECTED_MOUSEOVER_STROKE = 'rgba(255, 255, 255, 0.661)';
|
|
||||||
const BRUSH_BORDER_INNER_COLOR = 'rgba(0,0,0,1)';
|
const BRUSH_BORDER_INNER_COLOR = 'rgba(0,0,0,1)';
|
||||||
const BRUSH_BORDER_OUTER_COLOR = 'rgba(255,255,255,0.8)';
|
const BRUSH_BORDER_OUTER_COLOR = 'rgba(255,255,255,0.8)';
|
||||||
// This is invokeai/frontend/web/public/assets/images/transparent_bg.png as a dataURL
|
// This is invokeai/frontend/web/public/assets/images/transparent_bg.png as a dataURL
|
||||||
@ -53,13 +51,6 @@ const STAGE_BG_DATAURL =
|
|||||||
|
|
||||||
const mapId = (object: { id: string }) => object.id;
|
const mapId = (object: { id: string }) => object.id;
|
||||||
|
|
||||||
const getIsSelected = (layerId?: string | null) => {
|
|
||||||
if (!layerId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return layerId === getStore().getState().regionalPrompts.present.selectedLayerId;
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectRenderableLayers = (n: Konva.Node) =>
|
const selectRenderableLayers = (n: Konva.Node) =>
|
||||||
n.name() === MASKED_GUIDANCE_LAYER_NAME || n.name() === CONTROLNET_LAYER_NAME;
|
n.name() === MASKED_GUIDANCE_LAYER_NAME || n.name() === CONTROLNET_LAYER_NAME;
|
||||||
|
|
||||||
@ -560,29 +551,12 @@ const renderLayers = (
|
|||||||
* @param konvaLayer The konva layer to attach the bounding box to.
|
* @param konvaLayer The konva layer to attach the bounding box to.
|
||||||
* @param onBboxMouseDown Callback for when the bounding box is clicked.
|
* @param onBboxMouseDown Callback for when the bounding box is clicked.
|
||||||
*/
|
*/
|
||||||
const createBboxRect = (reduxLayer: Layer, konvaLayer: Konva.Layer, onBboxMouseDown: (layerId: string) => void) => {
|
const createBboxRect = (reduxLayer: Layer, konvaLayer: Konva.Layer) => {
|
||||||
const rect = new Konva.Rect({
|
const rect = new Konva.Rect({
|
||||||
id: getLayerBboxId(reduxLayer.id),
|
id: getLayerBboxId(reduxLayer.id),
|
||||||
name: LAYER_BBOX_NAME,
|
name: LAYER_BBOX_NAME,
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
});
|
});
|
||||||
rect.on('mousedown', function () {
|
|
||||||
onBboxMouseDown(reduxLayer.id);
|
|
||||||
});
|
|
||||||
rect.on('mouseover', function (e) {
|
|
||||||
if (getIsSelected(e.target.getLayer()?.id())) {
|
|
||||||
this.stroke(BBOX_SELECTED_STROKE);
|
|
||||||
} else {
|
|
||||||
this.stroke(BBOX_NOT_SELECTED_MOUSEOVER_STROKE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
rect.on('mouseout', function (e) {
|
|
||||||
if (getIsSelected(e.target.getLayer()?.id())) {
|
|
||||||
this.stroke(BBOX_SELECTED_STROKE);
|
|
||||||
} else {
|
|
||||||
this.stroke(BBOX_NOT_SELECTED_STROKE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
konvaLayer.add(rect);
|
konvaLayer.add(rect);
|
||||||
return rect;
|
return rect;
|
||||||
};
|
};
|
||||||
@ -600,10 +574,8 @@ const createBboxRect = (reduxLayer: Layer, konvaLayer: Konva.Layer, onBboxMouseD
|
|||||||
const renderBbox = (
|
const renderBbox = (
|
||||||
stage: Konva.Stage,
|
stage: Konva.Stage,
|
||||||
reduxLayers: Layer[],
|
reduxLayers: Layer[],
|
||||||
selectedLayerId: string | null,
|
|
||||||
tool: Tool,
|
tool: Tool,
|
||||||
onBboxChanged: (layerId: string, bbox: IRect | null) => void,
|
onBboxChanged: (layerId: string, bbox: IRect | null) => void
|
||||||
onBboxMouseDown: (layerId: string) => void
|
|
||||||
) => {
|
) => {
|
||||||
// Hide all bboxes so they don't interfere with getClientRect
|
// Hide all bboxes so they don't interfere with getClientRect
|
||||||
for (const bboxRect of stage.find<Konva.Rect>(`.${LAYER_BBOX_NAME}`)) {
|
for (const bboxRect of stage.find<Konva.Rect>(`.${LAYER_BBOX_NAME}`)) {
|
||||||
@ -634,18 +606,16 @@ const renderBbox = (
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rect =
|
const rect = konvaLayer.findOne<Konva.Rect>(`.${LAYER_BBOX_NAME}`) ?? createBboxRect(reduxLayer, konvaLayer);
|
||||||
konvaLayer.findOne<Konva.Rect>(`.${LAYER_BBOX_NAME}`) ??
|
|
||||||
createBboxRect(reduxLayer, konvaLayer, onBboxMouseDown);
|
|
||||||
|
|
||||||
rect.setAttrs({
|
rect.setAttrs({
|
||||||
visible: true,
|
visible: true,
|
||||||
listening: true,
|
listening: reduxLayer.isSelected,
|
||||||
x: bbox.x,
|
x: bbox.x,
|
||||||
y: bbox.y,
|
y: bbox.y,
|
||||||
width: bbox.width,
|
width: bbox.width,
|
||||||
height: bbox.height,
|
height: bbox.height,
|
||||||
stroke: reduxLayer.id === selectedLayerId ? BBOX_SELECTED_STROKE : BBOX_NOT_SELECTED_STROKE,
|
stroke: reduxLayer.isSelected ? BBOX_SELECTED_STROKE : '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user