Drag out links to disconnect nodes (#894)
* Disconnecting Links * Fix bug if nodeid is 0
This commit is contained in:
parent
81f365c999
commit
49b1770c34
|
|
@ -25,6 +25,10 @@ pub enum NodeGraphMessage {
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
},
|
},
|
||||||
DeleteSelectedNodes,
|
DeleteSelectedNodes,
|
||||||
|
DisconnectNodes {
|
||||||
|
node_id: NodeId,
|
||||||
|
input_index: usize,
|
||||||
|
},
|
||||||
DoubleClickNode {
|
DoubleClickNode {
|
||||||
node: NodeId,
|
node: NodeId,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -392,6 +392,22 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NodeGraphMessage::DisconnectNodes { node_id, input_index } => {
|
||||||
|
let Some(network) = self.get_active_network_mut(document) else {
|
||||||
|
warn!("No network");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(node) = network.nodes.get_mut(&node_id) else {
|
||||||
|
warn!("Invalid node");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(node_type) = resolve_document_node_type(&node.name) else {
|
||||||
|
warn!("Node {} not in library", node.name);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
node.inputs[input_index] = node_type.inputs[input_index].default.clone();
|
||||||
|
Self::send_graph(network, responses);
|
||||||
|
}
|
||||||
NodeGraphMessage::DoubleClickNode { node } => {
|
NodeGraphMessage::DoubleClickNode { node } => {
|
||||||
self.selected_nodes = Vec::new();
|
self.selected_nodes = Vec::new();
|
||||||
if let Some(network) = self.get_active_network_mut(document) {
|
if let Some(network) = self.get_active_network_mut(document) {
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,7 @@ export default defineComponent({
|
||||||
selectIfNotDragged: undefined as undefined | bigint,
|
selectIfNotDragged: undefined as undefined | bigint,
|
||||||
linkInProgressFromConnector: undefined as HTMLDivElement | undefined,
|
linkInProgressFromConnector: undefined as HTMLDivElement | undefined,
|
||||||
linkInProgressToConnector: undefined as HTMLDivElement | DOMRect | undefined,
|
linkInProgressToConnector: undefined as HTMLDivElement | DOMRect | undefined,
|
||||||
|
disconnecting: undefined as { nodeId: bigint; inputIndex: number; linkIndex: number } | undefined,
|
||||||
nodeLinkPaths: [] as [string, string][],
|
nodeLinkPaths: [] as [string, string][],
|
||||||
searchTerm: "",
|
searchTerm: "",
|
||||||
nodeListLocation: undefined as { x: number; y: number } | undefined,
|
nodeListLocation: undefined as { x: number; y: number } | undefined,
|
||||||
|
|
@ -394,7 +395,7 @@ export default defineComponent({
|
||||||
if (!containerBounds) return;
|
if (!containerBounds) return;
|
||||||
|
|
||||||
const links = this.nodeGraph.state.links;
|
const links = this.nodeGraph.state.links;
|
||||||
this.nodeLinkPaths = links.flatMap((link) => {
|
this.nodeLinkPaths = links.flatMap((link, index) => {
|
||||||
const connectorIndex = Number(link.linkEndInputIndex);
|
const connectorIndex = Number(link.linkEndInputIndex);
|
||||||
|
|
||||||
const nodePrimaryOutput = (containerBounds.querySelector(`[data-node="${String(link.linkStart)}"] [data-port="output"]`) || undefined) as HTMLDivElement | undefined;
|
const nodePrimaryOutput = (containerBounds.querySelector(`[data-node="${String(link.linkStart)}"] [data-port="output"]`) || undefined) as HTMLDivElement | undefined;
|
||||||
|
|
@ -403,6 +404,8 @@ export default defineComponent({
|
||||||
const nodePrimaryInput = nodeInputConnectors?.[connectorIndex] as HTMLDivElement | undefined;
|
const nodePrimaryInput = nodeInputConnectors?.[connectorIndex] as HTMLDivElement | undefined;
|
||||||
|
|
||||||
if (!nodePrimaryInput || !nodePrimaryOutput) return [];
|
if (!nodePrimaryInput || !nodePrimaryOutput) return [];
|
||||||
|
if (this.disconnecting?.linkIndex === index) return [];
|
||||||
|
|
||||||
return [this.createWirePath(nodePrimaryOutput, nodePrimaryInput.getBoundingClientRect(), false, false)];
|
return [this.createWirePath(nodePrimaryOutput, nodePrimaryInput.getBoundingClientRect(), false, false)];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -506,15 +509,35 @@ export default defineComponent({
|
||||||
const node = (e.target as HTMLElement).closest("[data-node]") as HTMLElement | undefined;
|
const node = (e.target as HTMLElement).closest("[data-node]") as HTMLElement | undefined;
|
||||||
const nodeId = node?.getAttribute("data-node") || undefined;
|
const nodeId = node?.getAttribute("data-node") || undefined;
|
||||||
const nodeList = (e.target as HTMLElement).closest("[data-node-list]") as HTMLElement | undefined;
|
const nodeList = (e.target as HTMLElement).closest("[data-node-list]") as HTMLElement | undefined;
|
||||||
|
const containerBounds = this.$refs.nodesContainer as HTMLDivElement | undefined;
|
||||||
|
if (!containerBounds) return;
|
||||||
|
|
||||||
// If the user is clicking on the add nodes list, exit here
|
// If the user is clicking on the add nodes list, exit here
|
||||||
if (nodeList) return;
|
if (nodeList) return;
|
||||||
|
|
||||||
// Clicked on a port dot
|
// Clicked on a port dot
|
||||||
if (port) {
|
if (port && node) {
|
||||||
const isOutput = Boolean(port.getAttribute("data-port") === "output");
|
const isOutput = Boolean(port.getAttribute("data-port") === "output");
|
||||||
|
|
||||||
if (isOutput) this.linkInProgressFromConnector = port;
|
if (isOutput) this.linkInProgressFromConnector = port;
|
||||||
|
else {
|
||||||
|
const inputNodeInPorts = Array.from(node.querySelectorAll(`[data-port="input"]`));
|
||||||
|
const inputNodeConnectionIndexSearch = inputNodeInPorts.indexOf(port);
|
||||||
|
const inputIndex = inputNodeConnectionIndexSearch > -1 ? inputNodeConnectionIndexSearch : undefined;
|
||||||
|
// Set the link to draw from the input that a previous link was on
|
||||||
|
if (inputIndex !== undefined && nodeId) {
|
||||||
|
const nodeIdInt = BigInt(nodeId);
|
||||||
|
const inputIndexInt = BigInt(inputIndex);
|
||||||
|
const links = this.nodeGraph.state.links;
|
||||||
|
const linkIndex = links.findIndex((value) => value.linkEnd === nodeIdInt && value.linkEndInputIndex === inputIndexInt);
|
||||||
|
const queryString = `[data-node="${String(links[linkIndex].linkStart)}"] [data-port="output"]`;
|
||||||
|
this.linkInProgressFromConnector = (containerBounds.querySelector(queryString) || undefined) as HTMLDivElement | undefined;
|
||||||
|
const nodeInputConnectors = containerBounds.querySelectorAll(`[data-node="${String(links[linkIndex].linkEnd)}"] [data-port="input"]`) || undefined;
|
||||||
|
this.linkInProgressToConnector = nodeInputConnectors?.[Number(links[linkIndex].linkEndInputIndex)] as HTMLDivElement | undefined;
|
||||||
|
this.disconnecting = { nodeId: nodeIdInt, inputIndex, linkIndex };
|
||||||
|
this.refreshLinks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -578,6 +601,11 @@ export default defineComponent({
|
||||||
pointerUp(e: PointerEvent) {
|
pointerUp(e: PointerEvent) {
|
||||||
this.panning = false;
|
this.panning = false;
|
||||||
|
|
||||||
|
if (this.disconnecting) {
|
||||||
|
this.editor.instance.disconnectNodes(BigInt(this.disconnecting.nodeId), this.disconnecting.inputIndex);
|
||||||
|
}
|
||||||
|
this.disconnecting = undefined;
|
||||||
|
|
||||||
if (this.linkInProgressToConnector instanceof HTMLDivElement && this.linkInProgressFromConnector) {
|
if (this.linkInProgressToConnector instanceof HTMLDivElement && this.linkInProgressFromConnector) {
|
||||||
const outputNode = this.linkInProgressFromConnector.closest("[data-node]");
|
const outputNode = this.linkInProgressFromConnector.closest("[data-node]");
|
||||||
const inputNode = this.linkInProgressToConnector.closest("[data-node]");
|
const inputNode = this.linkInProgressToConnector.closest("[data-node]");
|
||||||
|
|
@ -598,7 +626,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
} else if (this.draggingNodes) {
|
} else if (this.draggingNodes) {
|
||||||
if (this.draggingNodes.startX === e.x || this.draggingNodes.startY === e.y) {
|
if (this.draggingNodes.startX === e.x || this.draggingNodes.startY === e.y) {
|
||||||
if (this.selectIfNotDragged) {
|
if (this.selectIfNotDragged !== undefined) {
|
||||||
this.selected = [this.selectIfNotDragged];
|
this.selected = [this.selectIfNotDragged];
|
||||||
this.editor.instance.selectNodes(new BigUint64Array(this.selected));
|
this.editor.instance.selectNodes(new BigUint64Array(this.selected));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -587,6 +587,13 @@ impl JsEditorHandle {
|
||||||
self.dispatch(message);
|
self.dispatch(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Notifies the backend that the user disconnected a node
|
||||||
|
#[wasm_bindgen(js_name = disconnectNodes)]
|
||||||
|
pub fn disconnect_nodes(&self, node_id: u64, input_index: usize) {
|
||||||
|
let message = NodeGraphMessage::DisconnectNodes { node_id, input_index };
|
||||||
|
self.dispatch(message);
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new document node in the node graph
|
/// Creates a new document node in the node graph
|
||||||
#[wasm_bindgen(js_name = createNode)]
|
#[wasm_bindgen(js_name = createNode)]
|
||||||
pub fn create_node(&self, node_type: String, x: i32, y: i32) {
|
pub fn create_node(&self, node_type: String, x: i32, y: i32) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue