From 5c1c8c480b1e70dcc7250411877884da6e9994d5 Mon Sep 17 00:00:00 2001 From: Max Richter Date: Tue, 17 Dec 2024 19:22:57 +0100 Subject: [PATCH] feat: some shit --- app/src/app.html | 2 +- app/src/lib/graph-interface/HelpView.svelte | 10 +- .../background/Background.svelte | 13 +- app/src/lib/graph-interface/edges/Edge.svelte | 31 +-- .../graph-interface/edges/FloatingEdge.svelte | 10 +- .../edges/createEdgeGeometry.ts | 32 ++- app/src/lib/graph-interface/graph-manager.ts | 3 +- .../lib/graph-interface/graph/Graph.svelte | 194 ++++++++++-------- .../graph-interface/graph/GraphView.svelte | 21 +- .../lib/graph-interface/graph/Wrapper.svelte | 18 +- .../graph-interface/graph/colors.svelte.ts | 31 +++ app/src/lib/graph-interface/graph/colors.ts | 48 ----- .../lib/graph-interface/graph/state.svelte.ts | 10 +- app/src/lib/graph-interface/node/Node.svelte | 42 ++-- .../lib/graph-interface/node/NodeHTML.svelte | 31 +-- .../graph-interface/node/NodeHeader.svelte | 18 +- .../graph-interface/node/NodeParameter.svelte | 10 +- app/src/lib/helpers/createKeyMap.ts | 1 - .../performance/SmallPerformanceViewer.svelte | 6 +- app/src/lib/result-viewer/Scene.svelte | 86 ++++---- app/src/lib/result-viewer/Viewer.svelte | 49 +++-- app/src/lib/result-viewer/geometryPool.ts | 4 +- app/src/lib/runtime/runtime-executor.ts | 6 +- .../lib/runtime/worker-runtime-executor.ts | 3 - app/src/lib/settings/app-settings.svelte.ts | 10 +- app/src/lib/settings/app-settings.ts | 136 ------------ .../settings/panels/ActiveNodeSelected.svelte | 92 +++++++++ .../settings/panels/ActiveNodeSettings.svelte | 83 +------- app/src/lib/settings/panels/Keymap.svelte | 70 ++++--- .../lib/settings/panels/NestedSettings.svelte | 58 +++--- app/src/routes/+page.svelte | 119 ++++++----- nodes/max/plantarium/gravity/src/input.json | 4 +- packages/ui/src/lib/Details.svelte | 2 +- 33 files changed, 620 insertions(+), 633 deletions(-) create mode 100644 app/src/lib/graph-interface/graph/colors.svelte.ts delete mode 100644 app/src/lib/graph-interface/graph/colors.ts delete mode 100644 app/src/lib/settings/app-settings.ts create mode 100644 app/src/lib/settings/panels/ActiveNodeSelected.svelte diff --git a/app/src/app.html b/app/src/app.html index d45afd4..addab35 100644 --- a/app/src/app.html +++ b/app/src/app.html @@ -14,7 +14,7 @@ var value = JSON.parse(store); var themes = ["dark", "light", "catppuccin"]; if (themes[value.theme]) { - document.body.classList.add("theme-" + themes[value.theme]); + document.documentElement.classList.add("theme-" + themes[value.theme]); } } catch (e) { } } diff --git a/app/src/lib/graph-interface/HelpView.svelte b/app/src/lib/graph-interface/HelpView.svelte index a5bfbc1..8ef214c 100644 --- a/app/src/lib/graph-interface/HelpView.svelte +++ b/app/src/lib/graph-interface/HelpView.svelte @@ -1,6 +1,6 @@ @@ -91,8 +92,9 @@ border-radius: 5px; top: 10px; left: 10px; + max-width: 250px; border: 1px solid var(--outline); - z-index: 1000; + z-index: 10000; display: none; } diff --git a/app/src/lib/graph-interface/background/Background.svelte b/app/src/lib/graph-interface/background/Background.svelte index 29a3c02..6a0cdaa 100644 --- a/app/src/lib/graph-interface/background/Background.svelte +++ b/app/src/lib/graph-interface/background/Background.svelte @@ -1,10 +1,10 @@ - + {/if} diff --git a/app/src/lib/graph-interface/edges/FloatingEdge.svelte b/app/src/lib/graph-interface/edges/FloatingEdge.svelte index c266804..b65baac 100644 --- a/app/src/lib/graph-interface/edges/FloatingEdge.svelte +++ b/app/src/lib/graph-interface/edges/FloatingEdge.svelte @@ -1,8 +1,12 @@ - + diff --git a/app/src/lib/graph-interface/edges/createEdgeGeometry.ts b/app/src/lib/graph-interface/edges/createEdgeGeometry.ts index b5e00aa..3243d45 100644 --- a/app/src/lib/graph-interface/edges/createEdgeGeometry.ts +++ b/app/src/lib/graph-interface/edges/createEdgeGeometry.ts @@ -1,11 +1,29 @@ -import { BufferGeometry, Vector3, BufferAttribute } from 'three' -import { setXY, setXYZ, setXYZW, setXYZXYZ } from './utils.js' +import { BufferAttribute, BufferGeometry, Vector3 } from 'three'; +import { setXY, setXYZ, setXYZW, setXYZXYZ } from './utils.js'; export function createEdgeGeometry(points: Vector3[]) { - let shape = 'none' - let shapeFunction = (p: number) => 1 + const length = points[0].distanceTo(points[points.length - 1]); + + const startRadius = 10.5; + const constantWidth = 2; + const taperFraction = 0.8 / length; + + function ease(t: number) { + return t * t * (3 - 2 * t); + } + let shapeFunction = (alpha: number) => { + if (alpha < taperFraction) { + const easedAlpha = ease(alpha / taperFraction); + return startRadius + (constantWidth - startRadius) * easedAlpha; + } else if (alpha > 1 - taperFraction) { + const easedAlpha = ease((alpha - (1 - taperFraction)) / taperFraction); + return constantWidth + (startRadius - constantWidth) * easedAlpha; + } else { + return constantWidth; + } + }; // When the component first runs we create the buffer geometry and allocate the buffer attributes let pointCount = points.length @@ -19,9 +37,7 @@ export function createEdgeGeometry(points: Vector3[]) { let indices: number[] = [] let indicesIndex = 0 - if (shape === 'taper') { - shapeFunction = (p: number) => 1 * Math.pow(4 * p * (1 - p), 1) - } + for (let j = 0; j < pointCount; j++) { const c = j / points.length @@ -30,7 +46,7 @@ export function createEdgeGeometry(points: Vector3[]) { counterIndex += 2 setXY(side, doubleIndex, 1, -1) - let width = shape === 'none' ? 1 : shapeFunction(j / (pointCount - 1)) + let width = shapeFunction((j / (pointCount - 1))) setXY(widthArray, doubleIndex, width, width) doubleIndex += 2 diff --git a/app/src/lib/graph-interface/graph-manager.ts b/app/src/lib/graph-interface/graph-manager.ts index c962126..c7f63aa 100644 --- a/app/src/lib/graph-interface/graph-manager.ts +++ b/app/src/lib/graph-interface/graph-manager.ts @@ -1,6 +1,6 @@ import type { Edge, Graph, Node, NodeInput, NodeRegistry, Socket, } from "@nodes/types"; import { fastHashString } from "@nodes/utils"; -import { writable, type Writable } from "svelte/store"; +import { get, writable, type Writable } from "svelte/store"; import EventEmitter from "./helpers/EventEmitter.js"; import { createLogger } from "./helpers/index.js"; import throttle from "./helpers/throttle.js"; @@ -42,6 +42,7 @@ export class GraphManager extends EventEmitter<{ "save": Graph, "result": any, " history: HistoryManager = new HistoryManager(); execute = throttle(() => { + console.log("Props", get(this.nodes).values().find(n => n.type === "max/plantarium/gravity")?.props); if (this.loaded === false) return; this.emit("result", this.serialize()); }, 10); diff --git a/app/src/lib/graph-interface/graph/Graph.svelte b/app/src/lib/graph-interface/graph/Graph.svelte index b51f7fc..ca28f77 100644 --- a/app/src/lib/graph-interface/graph/Graph.svelte +++ b/app/src/lib/graph-interface/graph/Graph.svelte @@ -6,7 +6,6 @@ } from "../helpers/index.js"; import type { OrthographicCamera } from "three"; import Background from "../background/Background.svelte"; - import type { GraphManager } from "../graph-manager.js"; import { getContext, onMount, setContext } from "svelte"; import Camera from "../Camera.svelte"; import GraphView from "./GraphView.svelte"; @@ -23,14 +22,13 @@ import { Canvas } from "@threlte/core"; import { getGraphManager } from "./context.js"; - const state = getGraphState(); + const graphState = getGraphState(); export let snapToGrid = true; export let showGrid = true; export let showHelp = false; - let keymap = - getContext>("keymap") || createKeyMap([]); + const keymap = getContext>("keymap"); const manager = getGraphManager(); @@ -179,7 +177,7 @@ } setContext("setDownSocket", (socket: Socket) => { - state.activeSocket = socket; + graphState.activeSocket = socket; let { node, index, position } = socket; @@ -198,14 +196,14 @@ } mouseDown = position; - state.activeSocket = { + graphState.activeSocket = { node, index, position, }; - state.possibleSockets = manager - .getPossibleSockets(state.activeSocket) + graphState.possibleSockets = manager + .getPossibleSockets(graphState.activeSocket) .map(([node, index]) => { return { node, @@ -259,14 +257,15 @@ let my = event.clientY - rect.y; mousePosition = projectScreenToWorld(mx, my); + hoveredNodeId = getNodeIdFromEvent(event); if (!mouseDown) return; // we are creating a new edge here - if (state.activeSocket || state.possibleSockets?.length) { + if (graphState.activeSocket || graphState.possibleSockets?.length) { let smallestDist = 1000; let _socket; - for (const socket of state.possibleSockets) { + for (const socket of graphState.possibleSockets) { const dist = Math.sqrt( (socket.position[0] - mousePosition[0]) ** 2 + (socket.position[1] - mousePosition[1]) ** 2, @@ -279,9 +278,9 @@ if (_socket && smallestDist < 0.9) { mousePosition = _socket.position; - state.hoveredSocket = _socket; + graphState.hoveredSocket = _socket; } else { - state.hoveredSocket = null; + graphState.hoveredSocket = null; } return; } @@ -301,17 +300,17 @@ const y = node.position[1]; const height = getNodeHeight(node.type); if (x > x1 - 20 && x < x2 && y > y1 - height && y < y2) { - state.selectedNodes?.add(node.id); + graphState.selectedNodes?.add(node.id); } else { - state.selectedNodes?.delete(node.id); + graphState.selectedNodes?.delete(node.id); } } return; } // here we are handling dragging of nodes - if (state.activeNodeId !== -1 && mouseDownId !== -1) { - const node = manager.getNode(state.activeNodeId); + if (graphState.activeNodeId !== -1 && mouseDownId !== -1) { + const node = manager.getNode(graphState.activeNodeId); if (!node || event.buttons !== 1) return; node.tmp = node.tmp || {}; @@ -340,8 +339,8 @@ const vecX = oldX - newX; const vecY = oldY - newY; - if (state.selectedNodes?.size) { - for (const nodeId of state.selectedNodes) { + if (graphState.selectedNodes?.size) { + for (const nodeId of graphState.selectedNodes) { const n = manager.getNode(nodeId); if (!n?.tmp) continue; n.tmp.x = (n?.tmp?.downX || 0) - vecX; @@ -360,6 +359,7 @@ } // here we are handling panning of camera + isPanning = true; let newX = cameraDown[0] - (mx - mouseDown[0]) / cameraPosition[2]; let newY = cameraDown[1] - (my - mouseDown[1]) / cameraPosition[2]; @@ -424,43 +424,46 @@ // if we clicked on a node if (clickedNodeId !== -1) { - if (state.activeNodeId === -1) { - state.activeNodeId = clickedNodeId; + if (graphState.activeNodeId === -1) { + graphState.activeNodeId = clickedNodeId; // if the selected node is the same as the clicked node - } else if (state.activeNodeId === clickedNodeId) { + } else if (graphState.activeNodeId === clickedNodeId) { //$activeNodeId = -1; // if the clicked node is different from the selected node and secondary } else if (event.ctrlKey) { - state.selectedNodes = state.selectedNodes || new Set(); - state.selectedNodes.add(state.activeNodeId); - state.selectedNodes.delete(clickedNodeId); - state.activeNodeId = clickedNodeId; + graphState.selectedNodes.add(graphState.activeNodeId); + graphState.selectedNodes.delete(clickedNodeId); + graphState.activeNodeId = clickedNodeId; // select the node } else if (event.shiftKey) { - const activeNode = manager.getNode(state.activeNodeId); + const activeNode = manager.getNode(graphState.activeNodeId); const newNode = manager.getNode(clickedNodeId); if (activeNode && newNode) { const edge = manager.getNodesBetween(activeNode, newNode); if (edge) { - const selected = new Set(edge.map((n) => n.id)); - selected.add(clickedNodeId); - state.selectedNodes = selected; + graphState.selectedNodes.clear(); + for (const node of edge) { + graphState.selectedNodes.add(node.id); + } + graphState.selectedNodes.add(clickedNodeId); } } - } else if (!state.selectedNodes?.has(clickedNodeId)) { - state.activeNodeId = clickedNodeId; - state.clearSelection(); + } else if (!graphState.selectedNodes.has(clickedNodeId)) { + graphState.activeNodeId = clickedNodeId; + graphState.clearSelection(); } } else if (event.ctrlKey) { boxSelection = true; } - const node = manager.getNode(state.activeNodeId); + + const node = manager.getNode(graphState.activeNodeId); if (!node) return; node.tmp = node.tmp || {}; node.tmp.downX = node.position[0]; node.tmp.downY = node.position[1]; - if (state.selectedNodes) { - for (const nodeId of state.selectedNodes) { + + if (graphState.selectedNodes) { + for (const nodeId of graphState.selectedNodes) { const n = manager.getNode(nodeId); if (!n) continue; n.tmp = n.tmp || {}; @@ -471,8 +474,12 @@ } function copyNodes() { - if (state.activeNodeId === -1 && !state.selectedNodes?.size) return; - let _nodes = [state.activeNodeId, ...(state.selectedNodes?.values() || [])] + if (graphState.activeNodeId === -1 && !graphState.selectedNodes?.size) + return; + let _nodes = [ + graphState.activeNodeId, + ...(graphState.selectedNodes?.values() || []), + ] .map((id) => manager.getNode(id)) .filter(Boolean) as Node[]; @@ -508,7 +515,10 @@ .filter(Boolean) as Node[]; const newNodes = manager.createGraph(_nodes, clipboard.edges); - state.selectedNodes = new Set(newNodes.map((n) => n.id)); + graphState.selectedNodes.clear(); + for (const node of newNodes) { + graphState.selectedNodes.add(node.id); + } } const isBodyFocused = () => document?.activeElement?.nodeName !== "INPUT"; @@ -517,12 +527,14 @@ key: "l", description: "Select linked nodes", callback: () => { - const activeNode = manager.getNode(state.activeNodeId); + const activeNode = manager.getNode(graphState.activeNodeId); if (activeNode) { const nodes = manager.getLinkedNodes(activeNode); - state.selectedNodes = new Set(nodes.map((n) => n.id)); + graphState.selectedNodes.clear(); + for (const node of nodes) { + graphState.selectedNodes.add(node.id); + } } - console.log(activeNode); }, }); @@ -552,8 +564,8 @@ key: "Escape", description: "Deselect nodes", callback: () => { - state.activeNodeId = -1; - state.clearSelection(); + graphState.activeNodeId = -1; + graphState.clearSelection(); (document.activeElement as HTMLElement)?.blur(); }, }); @@ -605,7 +617,9 @@ description: "Select all nodes", callback: () => { if (!isBodyFocused()) return; - state.selectedNodes = new Set($nodes.keys()); + for (const node of $nodes.keys()) { + graphState.selectedNodes.add(node); + } }, }); @@ -654,38 +668,39 @@ callback: (event) => { if (!isBodyFocused()) return; manager.startUndoGroup(); - if (state.activeNodeId !== -1) { - const node = manager.getNode(state.activeNodeId); + if (graphState.activeNodeId !== -1) { + const node = manager.getNode(graphState.activeNodeId); if (node) { manager.removeNode(node, { restoreEdges: event.ctrlKey }); - state.activeNodeId = -1; + graphState.activeNodeId = -1; } } - if (state.selectedNodes) { - for (const nodeId of state.selectedNodes) { + if (graphState.selectedNodes) { + for (const nodeId of graphState.selectedNodes) { const node = manager.getNode(nodeId); if (node) { manager.removeNode(node, { restoreEdges: event.ctrlKey }); } } - state.clearSelection(); + graphState.clearSelection(); } manager.saveUndoGroup(); }, }); function handleMouseUp(event: MouseEvent) { + isPanning = false; if (!mouseDown) return; - const activeNode = manager.getNode(state.activeNodeId); + const activeNode = manager.getNode(graphState.activeNodeId); const clickedNodeId = getNodeIdFromEvent(event); if (clickedNodeId !== -1) { if (activeNode) { if (!activeNode?.tmp?.isMoving && !event.ctrlKey && !event.shiftKey) { - state.clearSelection(); - state.activeNodeId = clickedNodeId; + graphState.activeNodeId = clickedNodeId; + graphState.clearSelection(); } } } @@ -708,7 +723,7 @@ activeNode.position[1] = activeNode?.tmp?.y ?? activeNode.position[1]; } const nodes = [ - ...[...(state.selectedNodes?.values() || [])].map((id) => + ...[...(graphState.selectedNodes?.values() || [])].map((id) => manager.getNode(id), ), ] as NodeType[]; @@ -747,26 +762,26 @@ $edges = $edges; }); manager.save(); - } else if (state.hoveredSocket && state.activeSocket) { + } else if (graphState.hoveredSocket && graphState.activeSocket) { if ( - typeof state.hoveredSocket.index === "number" && - typeof state.activeSocket.index === "string" + typeof graphState.hoveredSocket.index === "number" && + typeof graphState.activeSocket.index === "string" ) { manager.createEdge( - state.hoveredSocket.node, - state.hoveredSocket.index || 0, - state.activeSocket.node, - state.activeSocket.index, + graphState.hoveredSocket.node, + graphState.hoveredSocket.index || 0, + graphState.activeSocket.node, + graphState.activeSocket.index, ); } else if ( - typeof state.activeSocket.index == "number" && - typeof state.hoveredSocket.index === "string" + typeof graphState.activeSocket.index == "number" && + typeof graphState.hoveredSocket.index === "string" ) { manager.createEdge( - state.activeSocket.node, - state.activeSocket.index || 0, - state.hoveredSocket.node, - state.hoveredSocket.index, + graphState.activeSocket.node, + graphState.activeSocket.index || 0, + graphState.hoveredSocket.node, + graphState.hoveredSocket.index, ); } manager.save(); @@ -780,22 +795,25 @@ cameraDown[1] === cameraPosition[1] && isBodyFocused() ) { - state.activeNodeId = -1; - state.clearSelection(); + graphState.activeNodeId = -1; + graphState.clearSelection(); } mouseDown = null; boxSelection = false; - state.activeSocket = null; - state.possibleSockets = []; - state.hoveredSocket = null; + graphState.activeSocket = null; + graphState.possibleSockets = []; + graphState.hoveredSocket = null; addMenuPosition = null; } + let isPanning = false; let isDragging = false; + let hoveredNodeId = -1; function handleMouseLeave() { isDragging = false; + isPanning = false; } function handleDrop(event: DragEvent) { @@ -865,16 +883,19 @@ function handleDragEnter(e: DragEvent) { e.preventDefault(); isDragging = true; + isPanning = false; } function handlerDragOver(e: DragEvent) { - isDragging = true; e.preventDefault(); + isDragging = true; + isPanning = false; } function handleDragEnd(e: DragEvent) { - isDragging = false; e.preventDefault(); + isDragging = true; + isPanning = false; } onMount(() => { @@ -893,6 +914,8 @@ on:wheel={handleMouseScroll} bind:this={wrapper} class="graph-wrapper" + class:is-panning={isPanning} + class:is-hovering={hoveredNodeId !== -1} aria-label="Graph" role="button" tabindex="0" @@ -916,9 +939,6 @@ /> - {#if showHelp} - - {/if} @@ -943,11 +963,12 @@ {/if} - {#if state.activeSocket} + {#if graphState.activeSocket} @@ -962,6 +983,10 @@ +{#if showHelp} + +{/if} + diff --git a/app/src/lib/settings/panels/NestedSettings.svelte b/app/src/lib/settings/panels/NestedSettings.svelte index bf1914d..74acbbe 100644 --- a/app/src/lib/settings/panels/NestedSettings.svelte +++ b/app/src/lib/settings/panels/NestedSettings.svelte @@ -1,3 +1,7 @@ + + {#if key && isNodeInput(type?.[key]) } -
+
{#if type[key].type === "button"}