mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 07:18:04 +08:00
Nested networks UI (#885)
* Initial UI for nested nodes * Clean up deleting nodes * Print address of nested network * Add exiting network message * Implement the breadcrumb trail * Remove whitespace * Fix double click not registering in Chromium Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
parent
52117d642c
commit
9d40539dc7
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<LayoutCol class="node-graph">
|
||||
<LayoutRow class="options-bar"></LayoutRow>
|
||||
<LayoutRow class="options-bar"><WidgetLayout :layout="nodeGraphBarLayout" /></LayoutRow>
|
||||
<LayoutRow
|
||||
class="graph"
|
||||
ref="graph"
|
||||
@@ -8,6 +8,7 @@
|
||||
@pointerdown="(e: PointerEvent) => pointerDown(e)"
|
||||
@pointermove="(e: PointerEvent) => pointerMove(e)"
|
||||
@pointerup="(e: PointerEvent) => pointerUp(e)"
|
||||
@dblclick="(e: MouseEvent) => doubleClick(e)"
|
||||
:style="{
|
||||
'--grid-spacing': `${gridSpacing}px`,
|
||||
'--grid-offset-x': `${transform.x * transform.scale}px`,
|
||||
@@ -15,7 +16,7 @@
|
||||
'--dot-radius': `${dotRadius}px`,
|
||||
}"
|
||||
>
|
||||
<LayoutCol class="node-list" v-if="nodeListLocation" :style="{ marginLeft: `${nodeListX}px`, marginTop: `${nodeListY}px` }">
|
||||
<LayoutCol class="node-list" data-node-list v-if="nodeListLocation" :style="{ marginLeft: `${nodeListX}px`, marginTop: `${nodeListY}px` }">
|
||||
<TextInput placeholder="Search Nodes..." :value="searchTerm" @update:value="(val) => (searchTerm = val)" v-focus />
|
||||
<LayoutCol v-for="nodeCategory in nodeCategories" :key="nodeCategory[0]">
|
||||
<TextLabel>{{ nodeCategory[0] }}</TextLabel>
|
||||
@@ -305,6 +306,7 @@ import TextButton from "@/components/widgets/buttons/TextButton.vue";
|
||||
import TextInput from "@/components/widgets/inputs/TextInput.vue";
|
||||
import IconLabel from "@/components/widgets/labels/IconLabel.vue";
|
||||
import TextLabel from "@/components/widgets/labels/TextLabel.vue";
|
||||
import WidgetLayout from "@/components/widgets/WidgetLayout.vue";
|
||||
|
||||
const WHEEL_RATE = (1 / 600) * 3;
|
||||
const GRID_COLLAPSE_SPACING = 10;
|
||||
@@ -343,6 +345,9 @@ export default defineComponent({
|
||||
nodes() {
|
||||
return this.nodeGraph.state.nodes;
|
||||
},
|
||||
nodeGraphBarLayout() {
|
||||
return this.nodeGraph.state.nodeGraphBarLayout;
|
||||
},
|
||||
nodeCategories() {
|
||||
const categories = new Map();
|
||||
this.nodeGraph.state.nodeTypes.forEach((node) => {
|
||||
@@ -484,6 +489,7 @@ export default defineComponent({
|
||||
this.transform.x -= scrollY / this.transform.scale;
|
||||
}
|
||||
},
|
||||
// TODO: Move the event listener from the graph to the window so dragging outside the graph area (or even the browser window) works
|
||||
pointerDown(e: PointerEvent) {
|
||||
if (e.button === 2) {
|
||||
const graphDiv: HTMLDivElement | undefined = (this.$refs.graph as typeof LayoutCol | undefined)?.$el;
|
||||
@@ -497,40 +503,53 @@ export default defineComponent({
|
||||
|
||||
const port = (e.target as HTMLDivElement).closest("[data-port]") as HTMLDivElement;
|
||||
const node = (e.target as HTMLElement).closest("[data-node]") as HTMLElement | undefined;
|
||||
const nodeList = (e.target as HTMLElement).closest(".node-list") as HTMLElement | undefined;
|
||||
const nodeId = node?.getAttribute("data-node") || undefined;
|
||||
const nodeList = (e.target as HTMLElement).closest("[data-node-list]") as HTMLElement | undefined;
|
||||
|
||||
// If the user is clicking on the add nodes list, exit here
|
||||
if (nodeList) return;
|
||||
|
||||
// Clicked on a port dot
|
||||
if (port) {
|
||||
const isOutput = Boolean(port.getAttribute("data-port") === "output");
|
||||
|
||||
if (isOutput) this.linkInProgressFromConnector = port;
|
||||
} else {
|
||||
const nodeId = node?.getAttribute("data-node") || undefined;
|
||||
if (nodeId) {
|
||||
const id = BigInt(nodeId);
|
||||
if (e.shiftKey || e.ctrlKey) {
|
||||
if (this.selected.includes(id)) this.selected.splice(this.selected.lastIndexOf(id), 1);
|
||||
else this.selected.push(id);
|
||||
} else if (!this.selected.includes(id)) {
|
||||
this.selected = [id];
|
||||
} else {
|
||||
this.selectIfNotDragged = id;
|
||||
}
|
||||
|
||||
if (this.selected.includes(id)) {
|
||||
this.draggingNodes = { startX: e.x, startY: e.y, roundX: 0, roundY: 0 };
|
||||
const graphDiv: HTMLDivElement | undefined = (this.$refs.graph as typeof LayoutCol | undefined)?.$el;
|
||||
graphDiv?.setPointerCapture(e.pointerId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.editor.instance.selectNodes(new BigUint64Array(this.selected));
|
||||
} else if (!nodeList) {
|
||||
this.selected = [];
|
||||
this.editor.instance.selectNodes(new BigUint64Array(this.selected));
|
||||
const graphDiv: HTMLDivElement | undefined = (this.$refs.graph as typeof LayoutCol | undefined)?.$el;
|
||||
graphDiv?.setPointerCapture(e.pointerId);
|
||||
|
||||
this.panning = true;
|
||||
// Clicked on a node
|
||||
if (nodeId) {
|
||||
const id = BigInt(nodeId);
|
||||
if (e.shiftKey || e.ctrlKey) {
|
||||
if (this.selected.includes(id)) this.selected.splice(this.selected.lastIndexOf(id), 1);
|
||||
else this.selected.push(id);
|
||||
} else if (!this.selected.includes(id)) {
|
||||
this.selected = [id];
|
||||
} else {
|
||||
this.selectIfNotDragged = id;
|
||||
}
|
||||
|
||||
if (this.selected.includes(id)) {
|
||||
this.draggingNodes = { startX: e.x, startY: e.y, roundX: 0, roundY: 0 };
|
||||
}
|
||||
|
||||
this.editor.instance.selectNodes(new BigUint64Array(this.selected));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Clicked on the graph background
|
||||
this.panning = true;
|
||||
this.selected = [];
|
||||
this.editor.instance.selectNodes(new BigUint64Array(this.selected));
|
||||
},
|
||||
doubleClick(e: MouseEvent) {
|
||||
const node = (e.target as HTMLElement).closest("[data-node]") as HTMLElement | undefined;
|
||||
const nodeId = node?.getAttribute("data-node") || undefined;
|
||||
if (nodeId) {
|
||||
const id = BigInt(nodeId);
|
||||
this.editor.instance.doubleClickNode(id);
|
||||
}
|
||||
},
|
||||
pointerMove(e: PointerEvent) {
|
||||
@@ -556,9 +575,6 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
pointerUp(e: PointerEvent) {
|
||||
const graph: HTMLDivElement | undefined = (this.$refs.graph as typeof LayoutCol | undefined)?.$el;
|
||||
graph?.releasePointerCapture(e.pointerId);
|
||||
|
||||
this.panning = false;
|
||||
|
||||
if (this.linkInProgressToConnector instanceof HTMLDivElement && this.linkInProgressFromConnector) {
|
||||
@@ -617,6 +633,7 @@ export default defineComponent({
|
||||
TextLabel,
|
||||
TextButton,
|
||||
TextInput,
|
||||
WidgetLayout,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user