mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): copy/paste input edges when copying node
- Copy edges to selected nodes on copy - If pasted with `ctrl/meta-shift-v`, also paste the input edges
This commit is contained in:
parent
575ecb4028
commit
32dff2c4e3
@ -231,6 +231,15 @@ export const Flow = memo(() => {
|
|||||||
);
|
);
|
||||||
useHotkeys(['Ctrl+v', 'Meta+v'], onPasteHotkey);
|
useHotkeys(['Ctrl+v', 'Meta+v'], onPasteHotkey);
|
||||||
|
|
||||||
|
const onPasteWithEdgesToNodesHotkey = useCallback(
|
||||||
|
(e: KeyboardEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
pasteSelection(true);
|
||||||
|
},
|
||||||
|
[pasteSelection]
|
||||||
|
);
|
||||||
|
useHotkeys(['Ctrl+shift+v', 'Meta+shift+v'], onPasteWithEdgesToNodesHotkey);
|
||||||
|
|
||||||
const onUndoHotkey = useCallback(() => {
|
const onUndoHotkey = useCallback(() => {
|
||||||
if (mayUndo) {
|
if (mayUndo) {
|
||||||
dispatch(undo());
|
dispatch(undo());
|
||||||
|
@ -4,10 +4,12 @@ import {
|
|||||||
$copiedEdges,
|
$copiedEdges,
|
||||||
$copiedNodes,
|
$copiedNodes,
|
||||||
$cursorPos,
|
$cursorPos,
|
||||||
|
$edgesToCopiedNodes,
|
||||||
selectionPasted,
|
selectionPasted,
|
||||||
selectNodesSlice,
|
selectNodesSlice,
|
||||||
} from 'features/nodes/store/nodesSlice';
|
} from 'features/nodes/store/nodesSlice';
|
||||||
import { findUnoccupiedPosition } from 'features/nodes/store/util/findUnoccupiedPosition';
|
import { findUnoccupiedPosition } from 'features/nodes/store/util/findUnoccupiedPosition';
|
||||||
|
import { isEqual, uniqWith } from 'lodash-es';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
const copySelection = () => {
|
const copySelection = () => {
|
||||||
@ -16,17 +18,24 @@ const copySelection = () => {
|
|||||||
const { nodes, edges } = selectNodesSlice(getState());
|
const { nodes, edges } = selectNodesSlice(getState());
|
||||||
const selectedNodes = nodes.filter((node) => node.selected);
|
const selectedNodes = nodes.filter((node) => node.selected);
|
||||||
const selectedEdges = edges.filter((edge) => edge.selected);
|
const selectedEdges = edges.filter((edge) => edge.selected);
|
||||||
|
const edgesToSelectedNodes = edges.filter((edge) => selectedNodes.some((node) => node.id === edge.target));
|
||||||
$copiedNodes.set(selectedNodes);
|
$copiedNodes.set(selectedNodes);
|
||||||
$copiedEdges.set(selectedEdges);
|
$copiedEdges.set(selectedEdges);
|
||||||
|
$edgesToCopiedNodes.set(edgesToSelectedNodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
const pasteSelection = () => {
|
const pasteSelection = (withEdgesToCopiedNodes?: boolean) => {
|
||||||
const { getState, dispatch } = getStore();
|
const { getState, dispatch } = getStore();
|
||||||
const currentNodes = selectNodesSlice(getState()).nodes;
|
const currentNodes = selectNodesSlice(getState()).nodes;
|
||||||
const cursorPos = $cursorPos.get();
|
const cursorPos = $cursorPos.get();
|
||||||
|
|
||||||
const copiedNodes = deepClone($copiedNodes.get());
|
const copiedNodes = deepClone($copiedNodes.get());
|
||||||
const copiedEdges = deepClone($copiedEdges.get());
|
let copiedEdges = deepClone($copiedEdges.get());
|
||||||
|
|
||||||
|
if (withEdgesToCopiedNodes) {
|
||||||
|
const edgesToCopiedNodes = deepClone($edgesToCopiedNodes.get());
|
||||||
|
copiedEdges = uniqWith([...copiedEdges, ...edgesToCopiedNodes], isEqual);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate an offset to reposition nodes to surround the cursor position, maintaining relative positioning
|
// Calculate an offset to reposition nodes to surround the cursor position, maintaining relative positioning
|
||||||
const xCoords = copiedNodes.map((node) => node.position.x);
|
const xCoords = copiedNodes.map((node) => node.position.x);
|
||||||
|
@ -498,6 +498,7 @@ export const $cursorPos = atom<XYPosition | null>(null);
|
|||||||
export const $templates = atom<Templates>({});
|
export const $templates = atom<Templates>({});
|
||||||
export const $copiedNodes = atom<AnyNode[]>([]);
|
export const $copiedNodes = atom<AnyNode[]>([]);
|
||||||
export const $copiedEdges = atom<InvocationNodeEdge[]>([]);
|
export const $copiedEdges = atom<InvocationNodeEdge[]>([]);
|
||||||
|
export const $edgesToCopiedNodes = atom<InvocationNodeEdge[]>([]);
|
||||||
export const $pendingConnection = atom<PendingConnection | null>(null);
|
export const $pendingConnection = atom<PendingConnection | null>(null);
|
||||||
export const $isUpdatingEdge = atom(false);
|
export const $isUpdatingEdge = atom(false);
|
||||||
export const $viewport = atom<Viewport>({ x: 0, y: 0, zoom: 1 });
|
export const $viewport = atom<Viewport>({ x: 0, y: 0, zoom: 1 });
|
||||||
|
Loading…
Reference in New Issue
Block a user