feat: fix some issue with dragging sockets
This commit is contained in:
parent
3d3ea5b5f8
commit
097b99ef55
@ -1,35 +1,37 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { animate, lerp, snapToGrid } from '../helpers/index.js';
|
import { animate, lerp, snapToGrid } from "../helpers/index.js";
|
||||||
import { LinearSRGBColorSpace } from 'three';
|
import { LinearSRGBColorSpace } from "three";
|
||||||
import { Canvas } from '@threlte/core';
|
import { Canvas } from "@threlte/core";
|
||||||
import type { OrthographicCamera } from 'three';
|
import type { OrthographicCamera } from "three";
|
||||||
import Background from '../background/Background.svelte';
|
import Background from "../background/Background.svelte";
|
||||||
import type { GraphManager } from '../graph-manager.js';
|
import type { GraphManager } from "../graph-manager.js";
|
||||||
import { onMount, setContext } from 'svelte';
|
import { onMount, setContext } from "svelte";
|
||||||
import Camera from '../Camera.svelte';
|
import Camera from "../Camera.svelte";
|
||||||
import GraphView from './GraphView.svelte';
|
import GraphView from "./GraphView.svelte";
|
||||||
import type { Node, Node as NodeType, Socket } from '@nodes/types';
|
import type { Node, Node as NodeType, Socket } from "@nodes/types";
|
||||||
import FloatingEdge from '../edges/FloatingEdge.svelte';
|
import FloatingEdge from "../edges/FloatingEdge.svelte";
|
||||||
import {
|
import {
|
||||||
activeNodeId,
|
activeNodeId,
|
||||||
activeSocket,
|
activeSocket,
|
||||||
hoveredSocket,
|
hoveredSocket,
|
||||||
possibleSockets,
|
possibleSockets,
|
||||||
possibleSocketIds,
|
possibleSocketIds,
|
||||||
selectedNodes
|
selectedNodes,
|
||||||
} from './stores.js';
|
} from "./stores.js";
|
||||||
import BoxSelection from '../BoxSelection.svelte';
|
import BoxSelection from "../BoxSelection.svelte";
|
||||||
import AddMenu from '../AddMenu.svelte';
|
import AddMenu from "../AddMenu.svelte";
|
||||||
|
|
||||||
export let graph: GraphManager;
|
export let graph: GraphManager;
|
||||||
setContext('graphManager', graph);
|
setContext("graphManager", graph);
|
||||||
const status = graph.status;
|
const status = graph.status;
|
||||||
const nodes = graph.nodes;
|
const nodes = graph.nodes;
|
||||||
const edges = graph.edges;
|
const edges = graph.edges;
|
||||||
|
|
||||||
let wrapper: HTMLDivElement;
|
let wrapper: HTMLDivElement;
|
||||||
$: rect =
|
$: rect =
|
||||||
wrapper && width ? wrapper.getBoundingClientRect() : { x: 0, y: 0, width: 0, height: 0 };
|
wrapper && width
|
||||||
|
? wrapper.getBoundingClientRect()
|
||||||
|
: { x: 0, y: 0, width: 0, height: 0 };
|
||||||
|
|
||||||
let camera: OrthographicCamera;
|
let camera: OrthographicCamera;
|
||||||
const minZoom = 1;
|
const minZoom = 1;
|
||||||
@ -55,47 +57,59 @@
|
|||||||
cameraPosition[0] - width / cameraPosition[2] / 2,
|
cameraPosition[0] - width / cameraPosition[2] / 2,
|
||||||
cameraPosition[0] + width / cameraPosition[2] / 2,
|
cameraPosition[0] + width / cameraPosition[2] / 2,
|
||||||
cameraPosition[1] - height / cameraPosition[2] / 2,
|
cameraPosition[1] - height / cameraPosition[2] / 2,
|
||||||
cameraPosition[1] + height / cameraPosition[2] / 2
|
cameraPosition[1] + height / cameraPosition[2] / 2,
|
||||||
];
|
];
|
||||||
function setCameraTransform(x = cameraPosition[0], y = cameraPosition[1], z = cameraPosition[2]) {
|
function setCameraTransform(
|
||||||
|
x = cameraPosition[0],
|
||||||
|
y = cameraPosition[1],
|
||||||
|
z = cameraPosition[2],
|
||||||
|
) {
|
||||||
if (camera) {
|
if (camera) {
|
||||||
camera.position.x = x;
|
camera.position.x = x;
|
||||||
camera.position.z = y;
|
camera.position.z = y;
|
||||||
camera.zoom = z;
|
camera.zoom = z;
|
||||||
}
|
}
|
||||||
cameraPosition = [x, y, z];
|
cameraPosition = [x, y, z];
|
||||||
localStorage.setItem('cameraPosition', JSON.stringify(cameraPosition));
|
localStorage.setItem("cameraPosition", JSON.stringify(cameraPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
export let debug = {};
|
export let debug = {};
|
||||||
$: debug = {
|
$: debug = {
|
||||||
activeNodeId: $activeNodeId,
|
activeNodeId: $activeNodeId,
|
||||||
activeSocket: $activeSocket ? `${$activeSocket?.node.id}-${$activeSocket?.index}` : null,
|
activeSocket: $activeSocket
|
||||||
hoveredSocket: $hoveredSocket ? `${$hoveredSocket?.node.id}-${$hoveredSocket?.index}` : null,
|
? `${$activeSocket?.node.id}-${$activeSocket?.index}`
|
||||||
|
: null,
|
||||||
|
hoveredSocket: $hoveredSocket
|
||||||
|
? `${$hoveredSocket?.node.id}-${$hoveredSocket?.index}`
|
||||||
|
: null,
|
||||||
selectedNodes: [...($selectedNodes?.values() || [])],
|
selectedNodes: [...($selectedNodes?.values() || [])],
|
||||||
cameraPosition
|
cameraPosition,
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateNodePosition(node: NodeType) {
|
function updateNodePosition(node: NodeType) {
|
||||||
if (node?.tmp?.ref) {
|
if (node?.tmp?.ref) {
|
||||||
if (node.tmp['x'] !== undefined && node.tmp['y'] !== undefined) {
|
if (node.tmp["x"] !== undefined && node.tmp["y"] !== undefined) {
|
||||||
node.tmp.ref.style.setProperty('--nx', `${node.tmp.x * 10}px`);
|
node.tmp.ref.style.setProperty("--nx", `${node.tmp.x * 10}px`);
|
||||||
node.tmp.ref.style.setProperty('--ny', `${node.tmp.y * 10}px`);
|
node.tmp.ref.style.setProperty("--ny", `${node.tmp.y * 10}px`);
|
||||||
node.tmp.mesh.position.x = node.tmp.x + 10;
|
node.tmp.mesh.position.x = node.tmp.x + 10;
|
||||||
node.tmp.mesh.position.z = node.tmp.y + getNodeHeight(node.type) / 2;
|
node.tmp.mesh.position.z = node.tmp.y + getNodeHeight(node.type) / 2;
|
||||||
if (node.tmp.x === node.position[0] && node.tmp.y === node.position[1]) {
|
if (
|
||||||
|
node.tmp.x === node.position[0] &&
|
||||||
|
node.tmp.y === node.position[1]
|
||||||
|
) {
|
||||||
delete node.tmp.x;
|
delete node.tmp.x;
|
||||||
delete node.tmp.y;
|
delete node.tmp.y;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
node.tmp.ref.style.setProperty('--nx', `${node.position[0] * 10}px`);
|
node.tmp.ref.style.setProperty("--nx", `${node.position[0] * 10}px`);
|
||||||
node.tmp.ref.style.setProperty('--ny', `${node.position[1] * 10}px`);
|
node.tmp.ref.style.setProperty("--ny", `${node.position[1] * 10}px`);
|
||||||
node.tmp.mesh.position.x = node.position[0] + 10;
|
node.tmp.mesh.position.x = node.position[0] + 10;
|
||||||
node.tmp.mesh.position.z = node.position[1] + getNodeHeight(node.type) / 2;
|
node.tmp.mesh.position.z =
|
||||||
|
node.position[1] + getNodeHeight(node.type) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setContext('updateNodePosition', updateNodePosition);
|
setContext("updateNodePosition", updateNodePosition);
|
||||||
|
|
||||||
const nodeHeightCache: Record<string, number> = {};
|
const nodeHeightCache: Record<string, number> = {};
|
||||||
function getNodeHeight(nodeTypeId: string) {
|
function getNodeHeight(nodeTypeId: string) {
|
||||||
@ -110,14 +124,15 @@
|
|||||||
5 +
|
5 +
|
||||||
10 *
|
10 *
|
||||||
Object.keys(node.inputs)
|
Object.keys(node.inputs)
|
||||||
.filter((i) => i !== 'seed')
|
.filter((i) => i !== "seed")
|
||||||
.filter((p) => node?.inputs && !('setting' in node?.inputs?.[p])).length;
|
.filter((p) => node?.inputs && !("setting" in node?.inputs?.[p]))
|
||||||
|
.length;
|
||||||
nodeHeightCache[nodeTypeId] = height;
|
nodeHeightCache[nodeTypeId] = height;
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
setContext('getNodeHeight', getNodeHeight);
|
setContext("getNodeHeight", getNodeHeight);
|
||||||
|
|
||||||
setContext('isNodeInView', (node: NodeType) => {
|
setContext("isNodeInView", (node: NodeType) => {
|
||||||
const height = getNodeHeight(node.type);
|
const height = getNodeHeight(node.type);
|
||||||
const width = 20;
|
const width = 20;
|
||||||
return (
|
return (
|
||||||
@ -137,8 +152,8 @@
|
|||||||
if (event.button === 0) {
|
if (event.button === 0) {
|
||||||
// check if the clicked element is a node
|
// check if the clicked element is a node
|
||||||
if (event.target instanceof HTMLElement) {
|
if (event.target instanceof HTMLElement) {
|
||||||
const nodeElement = event.target.closest('.node');
|
const nodeElement = event.target.closest(".node");
|
||||||
const nodeId = nodeElement?.getAttribute?.('data-node-id');
|
const nodeId = nodeElement?.getAttribute?.("data-node-id");
|
||||||
if (nodeId) {
|
if (nodeId) {
|
||||||
clickedNodeId = parseInt(nodeId, 10);
|
clickedNodeId = parseInt(nodeId, 10);
|
||||||
}
|
}
|
||||||
@ -162,13 +177,13 @@
|
|||||||
return clickedNodeId;
|
return clickedNodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
setContext('setDownSocket', (socket: Socket) => {
|
setContext("setDownSocket", (socket: Socket) => {
|
||||||
$activeSocket = socket;
|
$activeSocket = socket;
|
||||||
|
|
||||||
let { node, index, position } = socket;
|
let { node, index, position } = socket;
|
||||||
|
|
||||||
// remove existing edge
|
// remove existing edge
|
||||||
if (typeof index === 'string') {
|
if (typeof index === "string") {
|
||||||
const edges = graph.getEdgesToNode(node);
|
const edges = graph.getEdgesToNode(node);
|
||||||
for (const edge of edges) {
|
for (const edge of edges) {
|
||||||
if (edge[3] === index) {
|
if (edge[3] === index) {
|
||||||
@ -185,17 +200,21 @@
|
|||||||
$activeSocket = {
|
$activeSocket = {
|
||||||
node,
|
node,
|
||||||
index,
|
index,
|
||||||
position
|
position,
|
||||||
};
|
};
|
||||||
|
|
||||||
$possibleSockets = graph.getPossibleSockets($activeSocket).map(([node, index]) => {
|
$possibleSockets = graph
|
||||||
|
.getPossibleSockets($activeSocket)
|
||||||
|
.map(([node, index]) => {
|
||||||
return {
|
return {
|
||||||
node,
|
node,
|
||||||
index,
|
index,
|
||||||
position: getSocketPosition(node, index)
|
position: getSocketPosition(node, index),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
$possibleSocketIds = new Set($possibleSockets.map((s) => `${s.node.id}-${s.index}`));
|
$possibleSocketIds = new Set(
|
||||||
|
$possibleSockets.map((s) => `${s.node.id}-${s.index}`),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function getSnapLevel() {
|
function getSnapLevel() {
|
||||||
@ -211,26 +230,29 @@
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSocketPosition(node: NodeType, index: string | number): [number, number] {
|
function getSocketPosition(
|
||||||
if (typeof index === 'number') {
|
node: NodeType,
|
||||||
|
index: string | number,
|
||||||
|
): [number, number] {
|
||||||
|
if (typeof index === "number") {
|
||||||
return [
|
return [
|
||||||
(node?.tmp?.x ?? node.position[0]) + 20,
|
(node?.tmp?.x ?? node.position[0]) + 20,
|
||||||
(node?.tmp?.y ?? node.position[1]) + 2.5 + 10 * index
|
(node?.tmp?.y ?? node.position[1]) + 2.5 + 10 * index,
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
const _index = Object.keys(node.tmp?.type?.inputs || {}).indexOf(index);
|
const _index = Object.keys(node.tmp?.type?.inputs || {}).indexOf(index);
|
||||||
return [
|
return [
|
||||||
node?.tmp?.x ?? node.position[0],
|
node?.tmp?.x ?? node.position[0],
|
||||||
(node?.tmp?.y ?? node.position[1]) + 10 + 10 * _index
|
(node?.tmp?.y ?? node.position[1]) + 10 + 10 * _index,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setContext('getSocketPosition', getSocketPosition);
|
setContext("getSocketPosition", getSocketPosition);
|
||||||
|
|
||||||
function projectScreenToWorld(x: number, y: number): [number, number] {
|
function projectScreenToWorld(x: number, y: number): [number, number] {
|
||||||
return [
|
return [
|
||||||
cameraPosition[0] + (x - width / 2) / cameraPosition[2],
|
cameraPosition[0] + (x - width / 2) / cameraPosition[2],
|
||||||
cameraPosition[1] + (y - height / 2) / cameraPosition[2]
|
cameraPosition[1] + (y - height / 2) / cameraPosition[2],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,13 +265,13 @@
|
|||||||
if (!mouseDown) return;
|
if (!mouseDown) return;
|
||||||
|
|
||||||
// we are creating a new edge here
|
// we are creating a new edge here
|
||||||
if ($possibleSockets?.length) {
|
if ($activeSocket || $possibleSockets?.length) {
|
||||||
let smallestDist = 1000;
|
let smallestDist = 1000;
|
||||||
let _socket;
|
let _socket;
|
||||||
for (const socket of $possibleSockets) {
|
for (const socket of $possibleSockets) {
|
||||||
const dist = Math.sqrt(
|
const dist = Math.sqrt(
|
||||||
(socket.position[0] - mousePosition[0]) ** 2 +
|
(socket.position[0] - mousePosition[0]) ** 2 +
|
||||||
(socket.position[1] - mousePosition[1]) ** 2
|
(socket.position[1] - mousePosition[1]) ** 2,
|
||||||
);
|
);
|
||||||
if (dist < smallestDist) {
|
if (dist < smallestDist) {
|
||||||
smallestDist = dist;
|
smallestDist = dist;
|
||||||
@ -350,7 +372,7 @@
|
|||||||
const bodyIsFocused =
|
const bodyIsFocused =
|
||||||
document.activeElement === document.body ||
|
document.activeElement === document.body ||
|
||||||
document.activeElement === wrapper ||
|
document.activeElement === wrapper ||
|
||||||
document?.activeElement?.id === 'graph';
|
document?.activeElement?.id === "graph";
|
||||||
if (!bodyIsFocused) return;
|
if (!bodyIsFocused) return;
|
||||||
|
|
||||||
// Define zoom speed and clamp it between -1 and 1
|
// Define zoom speed and clamp it between -1 and 1
|
||||||
@ -361,7 +383,10 @@
|
|||||||
// Calculate new zoom level and clamp it between minZoom and maxZoom
|
// Calculate new zoom level and clamp it between minZoom and maxZoom
|
||||||
const newZoom = Math.max(
|
const newZoom = Math.max(
|
||||||
minZoom,
|
minZoom,
|
||||||
Math.min(maxZoom, isNegative ? cameraPosition[2] / delta : cameraPosition[2] * delta)
|
Math.min(
|
||||||
|
maxZoom,
|
||||||
|
isNegative ? cameraPosition[2] / delta : cameraPosition[2] * delta,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Calculate the ratio of the new zoom to the original zoom
|
// Calculate the ratio of the new zoom to the original zoom
|
||||||
@ -371,18 +396,20 @@
|
|||||||
setCameraTransform(
|
setCameraTransform(
|
||||||
mousePosition[0] - (mousePosition[0] - cameraPosition[0]) / zoomRatio,
|
mousePosition[0] - (mousePosition[0] - cameraPosition[0]) / zoomRatio,
|
||||||
mousePosition[1] - (mousePosition[1] - cameraPosition[1]) / zoomRatio,
|
mousePosition[1] - (mousePosition[1] - cameraPosition[1]) / zoomRatio,
|
||||||
newZoom
|
newZoom,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseDown(event: MouseEvent) {
|
function handleMouseDown(event: MouseEvent) {
|
||||||
if (mouseDown) return;
|
if (mouseDown) return;
|
||||||
|
|
||||||
|
console.log(event.target);
|
||||||
|
|
||||||
if (event.target instanceof HTMLElement) {
|
if (event.target instanceof HTMLElement) {
|
||||||
if (
|
if (
|
||||||
event.target.nodeName !== 'CANVAS' &&
|
event.target.nodeName !== "CANVAS" &&
|
||||||
!event.target.classList.contains('node') &&
|
!event.target.classList.contains("node") &&
|
||||||
!event.target.classList.contains('content')
|
!event.target.classList.contains("content")
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -460,15 +487,15 @@
|
|||||||
..._node,
|
..._node,
|
||||||
tmp: {
|
tmp: {
|
||||||
downX: mousePosition[0] - _node.position[0],
|
downX: mousePosition[0] - _node.position[0],
|
||||||
downY: mousePosition[1] - _node.position[1]
|
downY: mousePosition[1] - _node.position[1],
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
return node;
|
return node;
|
||||||
});
|
});
|
||||||
|
|
||||||
clipboard = {
|
clipboard = {
|
||||||
nodes: _nodes,
|
nodes: _nodes,
|
||||||
edges: _edges
|
edges: _edges,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,9 +517,10 @@
|
|||||||
|
|
||||||
function handleKeyDown(event: KeyboardEvent) {
|
function handleKeyDown(event: KeyboardEvent) {
|
||||||
const bodyIsFocused =
|
const bodyIsFocused =
|
||||||
document.activeElement === document.body || document?.activeElement?.id === 'graph';
|
document.activeElement === document.body ||
|
||||||
|
document?.activeElement?.id === "graph";
|
||||||
|
|
||||||
if (event.key === 'l') {
|
if (event.key === "l") {
|
||||||
const activeNode = graph.getNode($activeNodeId);
|
const activeNode = graph.getNode($activeNodeId);
|
||||||
if (activeNode) {
|
if (activeNode) {
|
||||||
const nodes = graph.getLinkedNodes(activeNode);
|
const nodes = graph.getLinkedNodes(activeNode);
|
||||||
@ -501,18 +529,18 @@
|
|||||||
console.log(activeNode);
|
console.log(activeNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'Escape') {
|
if (event.key === "Escape") {
|
||||||
$activeNodeId = -1;
|
$activeNodeId = -1;
|
||||||
$selectedNodes?.clear();
|
$selectedNodes?.clear();
|
||||||
$selectedNodes = $selectedNodes;
|
$selectedNodes = $selectedNodes;
|
||||||
(document.activeElement as HTMLElement)?.blur();
|
(document.activeElement as HTMLElement)?.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'A' && event.shiftKey) {
|
if (event.key === "A" && event.shiftKey) {
|
||||||
addMenuPosition = [mousePosition[0], mousePosition[1]];
|
addMenuPosition = [mousePosition[0], mousePosition[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === '.') {
|
if (event.key === ".") {
|
||||||
const average = [0, 0];
|
const average = [0, 0];
|
||||||
for (const node of $nodes.values()) {
|
for (const node of $nodes.values()) {
|
||||||
average[0] += node.position[0];
|
average[0] += node.position[0];
|
||||||
@ -531,32 +559,32 @@
|
|||||||
setCameraTransform(
|
setCameraTransform(
|
||||||
lerp(camX, average[0], ease(a)),
|
lerp(camX, average[0], ease(a)),
|
||||||
lerp(camY, average[1], ease(a)),
|
lerp(camY, average[1], ease(a)),
|
||||||
lerp(camZ, 2, ease(a))
|
lerp(camZ, 2, ease(a)),
|
||||||
);
|
);
|
||||||
if (mouseDown) return false;
|
if (mouseDown) return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'a' && event.ctrlKey && bodyIsFocused) {
|
if (event.key === "a" && event.ctrlKey && bodyIsFocused) {
|
||||||
$selectedNodes = new Set($nodes.keys());
|
$selectedNodes = new Set($nodes.keys());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'c' && event.ctrlKey) {
|
if (event.key === "c" && event.ctrlKey) {
|
||||||
copyNodes();
|
copyNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'v' && event.ctrlKey) {
|
if (event.key === "v" && event.ctrlKey) {
|
||||||
pasteNodes();
|
pasteNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'z' && event.ctrlKey) {
|
if (event.key === "z" && event.ctrlKey) {
|
||||||
graph.undo();
|
graph.undo();
|
||||||
for (const node of $nodes.values()) {
|
for (const node of $nodes.values()) {
|
||||||
updateNodePosition(node);
|
updateNodePosition(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'y' && event.ctrlKey) {
|
if (event.key === "y" && event.ctrlKey) {
|
||||||
graph.redo();
|
graph.redo();
|
||||||
for (const node of $nodes.values()) {
|
for (const node of $nodes.values()) {
|
||||||
updateNodePosition(node);
|
updateNodePosition(node);
|
||||||
@ -564,7 +592,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(event.key === 'Delete' || event.key === 'Backspace' || event.key === 'x') &&
|
(event.key === "Delete" ||
|
||||||
|
event.key === "Backspace" ||
|
||||||
|
event.key === "x") &&
|
||||||
bodyIsFocused
|
bodyIsFocused
|
||||||
) {
|
) {
|
||||||
graph.startUndoGroup();
|
graph.startUndoGroup();
|
||||||
@ -610,19 +640,19 @@
|
|||||||
const snapLevel = getSnapLevel();
|
const snapLevel = getSnapLevel();
|
||||||
activeNode.position[0] = snapToGrid(
|
activeNode.position[0] = snapToGrid(
|
||||||
activeNode?.tmp?.x ?? activeNode.position[0],
|
activeNode?.tmp?.x ?? activeNode.position[0],
|
||||||
5 / snapLevel
|
5 / snapLevel,
|
||||||
);
|
);
|
||||||
activeNode.position[1] = snapToGrid(
|
activeNode.position[1] = snapToGrid(
|
||||||
activeNode?.tmp?.y ?? activeNode.position[1],
|
activeNode?.tmp?.y ?? activeNode.position[1],
|
||||||
5 / snapLevel
|
5 / snapLevel,
|
||||||
);
|
);
|
||||||
const nodes = [
|
const nodes = [
|
||||||
...[...($selectedNodes?.values() || [])].map((id) => graph.getNode(id))
|
...[...($selectedNodes?.values() || [])].map((id) => graph.getNode(id)),
|
||||||
] as NodeType[];
|
] as NodeType[];
|
||||||
|
|
||||||
const vec = [
|
const vec = [
|
||||||
activeNode.position[0] - (activeNode?.tmp.x || 0),
|
activeNode.position[0] - (activeNode?.tmp.x || 0),
|
||||||
activeNode.position[1] - (activeNode?.tmp.y || 0)
|
activeNode.position[1] - (activeNode?.tmp.y || 0),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
@ -637,7 +667,11 @@
|
|||||||
nodes.push(activeNode);
|
nodes.push(activeNode);
|
||||||
animate(500, (a: number) => {
|
animate(500, (a: number) => {
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
if (node?.tmp && node.tmp['x'] !== undefined && node.tmp['y'] !== undefined) {
|
if (
|
||||||
|
node?.tmp &&
|
||||||
|
node.tmp["x"] !== undefined &&
|
||||||
|
node.tmp["y"] !== undefined
|
||||||
|
) {
|
||||||
node.tmp.x = lerp(node.tmp.x, node.position[0], a);
|
node.tmp.x = lerp(node.tmp.x, node.position[0], a);
|
||||||
node.tmp.y = lerp(node.tmp.y, node.position[1], a);
|
node.tmp.y = lerp(node.tmp.y, node.position[1], a);
|
||||||
updateNodePosition(node);
|
updateNodePosition(node);
|
||||||
@ -651,22 +685,25 @@
|
|||||||
});
|
});
|
||||||
graph.save();
|
graph.save();
|
||||||
} else if ($hoveredSocket && $activeSocket) {
|
} else if ($hoveredSocket && $activeSocket) {
|
||||||
if (typeof $hoveredSocket.index === 'number' && typeof $activeSocket.index === 'string') {
|
if (
|
||||||
|
typeof $hoveredSocket.index === "number" &&
|
||||||
|
typeof $activeSocket.index === "string"
|
||||||
|
) {
|
||||||
graph.createEdge(
|
graph.createEdge(
|
||||||
$hoveredSocket.node,
|
$hoveredSocket.node,
|
||||||
$hoveredSocket.index || 0,
|
$hoveredSocket.index || 0,
|
||||||
$activeSocket.node,
|
$activeSocket.node,
|
||||||
$activeSocket.index
|
$activeSocket.index,
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
typeof $activeSocket.index == 'number' &&
|
typeof $activeSocket.index == "number" &&
|
||||||
typeof $hoveredSocket.index === 'string'
|
typeof $hoveredSocket.index === "string"
|
||||||
) {
|
) {
|
||||||
graph.createEdge(
|
graph.createEdge(
|
||||||
$activeSocket.node,
|
$activeSocket.node,
|
||||||
$activeSocket.index || 0,
|
$activeSocket.index || 0,
|
||||||
$hoveredSocket.node,
|
$hoveredSocket.node,
|
||||||
$hoveredSocket.index
|
$hoveredSocket.index,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
graph.save();
|
graph.save();
|
||||||
@ -694,8 +731,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (localStorage.getItem('cameraPosition')) {
|
if (localStorage.getItem("cameraPosition")) {
|
||||||
const cPosition = JSON.parse(localStorage.getItem('cameraPosition')!);
|
const cPosition = JSON.parse(localStorage.getItem("cameraPosition")!);
|
||||||
if (Array.isArray(cPosition)) {
|
if (Array.isArray(cPosition)) {
|
||||||
setCameraTransform(cPosition[0], cPosition[1], cPosition[2]);
|
setCameraTransform(cPosition[0], cPosition[1], cPosition[2]);
|
||||||
}
|
}
|
||||||
@ -732,13 +769,14 @@
|
|||||||
{cameraPosition}
|
{cameraPosition}
|
||||||
p1={{
|
p1={{
|
||||||
x: cameraPosition[0] + (mouseDown[0] - width / 2) / cameraPosition[2],
|
x: cameraPosition[0] + (mouseDown[0] - width / 2) / cameraPosition[2],
|
||||||
y: cameraPosition[1] + (mouseDown[1] - height / 2) / cameraPosition[2]
|
y:
|
||||||
|
cameraPosition[1] + (mouseDown[1] - height / 2) / cameraPosition[2],
|
||||||
}}
|
}}
|
||||||
p2={{ x: mousePosition[0], y: mousePosition[1] }}
|
p2={{ x: mousePosition[0], y: mousePosition[1] }}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if $status === 'idle'}
|
{#if $status === "idle"}
|
||||||
{#if addMenuPosition}
|
{#if addMenuPosition}
|
||||||
<AddMenu bind:position={addMenuPosition} {graph} />
|
<AddMenu bind:position={addMenuPosition} {graph} />
|
||||||
{/if}
|
{/if}
|
||||||
@ -751,9 +789,9 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<GraphView {nodes} {edges} {cameraPosition} />
|
<GraphView {nodes} {edges} {cameraPosition} />
|
||||||
{:else if $status === 'loading'}
|
{:else if $status === "loading"}
|
||||||
<span>Loading</span>
|
<span>Loading</span>
|
||||||
{:else if $status === 'error'}
|
{:else if $status === "error"}
|
||||||
<span>Error</span>
|
<span>Error</span>
|
||||||
{/if}
|
{/if}
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"input": {
|
"input": {
|
||||||
"type": "float",
|
"type": "plant",
|
||||||
"value": 0.0,
|
|
||||||
"external": true
|
"external": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use utils::{evaluate_args, generate_outputs, get_args};
|
|||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use web_sys::console;
|
use web_sys::console;
|
||||||
|
|
||||||
generate_outputs!(["stem"]);
|
generate_outputs!(["plant"]);
|
||||||
generate_input_types_file!("src/input.json");
|
generate_input_types_file!("src/input.json");
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:nodes": "pnpm -r --filter './nodes/**' build",
|
"build:nodes": "pnpm -r --filter './nodes/**' build",
|
||||||
"dev:nodes": "pnpm -r --filter './nodes/**' dev",
|
"dev:nodes": "pnpm -r --parallel --filter './nodes/**' dev",
|
||||||
"dev": "pnpm -r --filter 'app' --filter './packages/node-registry' dev"
|
"dev": "pnpm -r --filter 'app' --filter './packages/node-registry' dev"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user