feat/debug-node #41
@@ -3,6 +3,7 @@ import { getContext, setContext } from 'svelte';
|
|||||||
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
||||||
import type { OrthographicCamera, Vector3 } from 'three';
|
import type { OrthographicCamera, Vector3 } from 'three';
|
||||||
import type { GraphManager } from './graph-manager.svelte';
|
import type { GraphManager } from './graph-manager.svelte';
|
||||||
|
import { getNodeHeight, getSocketPosition } from './helpers/nodeHelpers';
|
||||||
|
|
||||||
const graphStateKey = Symbol('graph-state');
|
const graphStateKey = Symbol('graph-state');
|
||||||
export function getGraphState() {
|
export function getGraphState() {
|
||||||
@@ -159,56 +160,6 @@ export class GraphState {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSocketPosition(
|
|
||||||
node: NodeInstance,
|
|
||||||
index: string | number
|
|
||||||
): [number, number] {
|
|
||||||
if (typeof index === 'number') {
|
|
||||||
return [
|
|
||||||
(node?.state?.x ?? node.position[0]) + 20,
|
|
||||||
(node?.state?.y ?? node.position[1]) + 2.5 + 10 * index
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
const _index = Object.keys(node.state?.type?.inputs || {}).indexOf(index);
|
|
||||||
return [
|
|
||||||
node?.state?.x ?? node.position[0],
|
|
||||||
(node?.state?.y ?? node.position[1]) + 10 + 10 * _index
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private nodeHeightCache: Record<string, number> = {};
|
|
||||||
getNodeHeight(nodeTypeId: string) {
|
|
||||||
if (nodeTypeId in this.nodeHeightCache) {
|
|
||||||
return this.nodeHeightCache[nodeTypeId];
|
|
||||||
}
|
|
||||||
const node = this.graph.getNodeType(nodeTypeId);
|
|
||||||
if (!node?.inputs) {
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
let height = 5;
|
|
||||||
|
|
||||||
for (const key of Object.keys(node.inputs)) {
|
|
||||||
if (key === 'seed') continue;
|
|
||||||
if (!node.inputs) continue;
|
|
||||||
if (node?.inputs?.[key] === undefined) continue;
|
|
||||||
if ('setting' in node.inputs[key]) continue;
|
|
||||||
if (node.inputs[key].hidden) continue;
|
|
||||||
if (
|
|
||||||
node.inputs[key].type === 'shape'
|
|
||||||
&& node.inputs[key].external !== true
|
|
||||||
&& node.inputs[key].internal !== false
|
|
||||||
) {
|
|
||||||
height += 20;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
height += 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.nodeHeightCache[nodeTypeId] = height;
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
copyNodes() {
|
copyNodes() {
|
||||||
if (this.activeNodeId === -1 && !this.selectedNodes?.size) {
|
if (this.activeNodeId === -1 && !this.selectedNodes?.size) {
|
||||||
return;
|
return;
|
||||||
@@ -266,7 +217,7 @@ export class GraphState {
|
|||||||
if (edge[3] === index) {
|
if (edge[3] === index) {
|
||||||
node = edge[0];
|
node = edge[0];
|
||||||
index = edge[1];
|
index = edge[1];
|
||||||
position = this.getSocketPosition(node, index);
|
position = getSocketPosition(node, index);
|
||||||
this.graph.removeEdge(edge);
|
this.graph.removeEdge(edge);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -286,7 +237,7 @@ export class GraphState {
|
|||||||
return {
|
return {
|
||||||
node,
|
node,
|
||||||
index,
|
index,
|
||||||
position: this.getSocketPosition(node, index)
|
position: getSocketPosition(node, index)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -323,7 +274,7 @@ export class GraphState {
|
|||||||
for (const node of this.graph.nodes.values()) {
|
for (const node of this.graph.nodes.values()) {
|
||||||
const x = node.position[0];
|
const x = node.position[0];
|
||||||
const y = node.position[1];
|
const y = node.position[1];
|
||||||
const height = this.getNodeHeight(node.type);
|
const height = getNodeHeight(node.state.type!);
|
||||||
if (downX > x && downX < x + 20 && downY > y && downY < y + height) {
|
if (downX > x && downX < x + 20 && downY > y && downY < y + height) {
|
||||||
clickedNodeId = node.id;
|
clickedNodeId = node.id;
|
||||||
break;
|
break;
|
||||||
@@ -335,14 +286,12 @@ export class GraphState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isNodeInView(node: NodeInstance) {
|
isNodeInView(node: NodeInstance) {
|
||||||
const height = this.getNodeHeight(node.type);
|
const height = getNodeHeight(node.state.type!);
|
||||||
const width = 20;
|
const width = 20;
|
||||||
return (
|
return node.position[0] > this.cameraBounds[0] - width
|
||||||
node.position[0] > this.cameraBounds[0] - width
|
|
||||||
&& node.position[0] < this.cameraBounds[1]
|
&& node.position[0] < this.cameraBounds[1]
|
||||||
&& node.position[1] > this.cameraBounds[2] - height
|
&& node.position[1] > this.cameraBounds[2] - height
|
||||||
&& node.position[1] < this.cameraBounds[3]
|
&& node.position[1] < this.cameraBounds[3];
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
openNodePalette() {
|
openNodePalette() {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
import Debug from '../debug/Debug.svelte';
|
import Debug from '../debug/Debug.svelte';
|
||||||
import EdgeEl from '../edges/Edge.svelte';
|
import EdgeEl from '../edges/Edge.svelte';
|
||||||
import { getGraphManager, getGraphState } from '../graph-state.svelte';
|
import { getGraphManager, getGraphState } from '../graph-state.svelte';
|
||||||
|
import { getSocketPosition } from '../helpers/nodeHelpers';
|
||||||
import NodeEl from '../node/Node.svelte';
|
import NodeEl from '../node/Node.svelte';
|
||||||
import { maxZoom, minZoom } from './constants';
|
import { maxZoom, minZoom } from './constants';
|
||||||
import { FileDropEventManager } from './drop.events';
|
import { FileDropEventManager } from './drop.events';
|
||||||
@@ -38,8 +39,8 @@
|
|||||||
return [0, 0, 0, 0];
|
return [0, 0, 0, 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const pos1 = graphState.getSocketPosition(fromNode, edge[1]);
|
const pos1 = getSocketPosition(fromNode, edge[1]);
|
||||||
const pos2 = graphState.getSocketPosition(toNode, edge[3]);
|
const pos2 = getSocketPosition(toNode, edge[3]);
|
||||||
return [pos1[0], pos1[1], pos2[0], pos2[1]];
|
return [pos1[0], pos1[1], pos2[0], pos2[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { type NodeInstance } from '@nodarium/types';
|
|||||||
import type { GraphManager } from '../graph-manager.svelte';
|
import type { GraphManager } from '../graph-manager.svelte';
|
||||||
import { type GraphState } from '../graph-state.svelte';
|
import { type GraphState } from '../graph-state.svelte';
|
||||||
import { snapToGrid as snapPointToGrid } from '../helpers';
|
import { snapToGrid as snapPointToGrid } from '../helpers';
|
||||||
|
import { getNodeHeight } from '../helpers/nodeHelpers';
|
||||||
import { maxZoom, minZoom, zoomSpeed } from './constants';
|
import { maxZoom, minZoom, zoomSpeed } from './constants';
|
||||||
import { EdgeInteractionManager } from './edge.events';
|
import { EdgeInteractionManager } from './edge.events';
|
||||||
|
|
||||||
@@ -289,7 +290,7 @@ export class MouseEventManager {
|
|||||||
if (!node?.state) continue;
|
if (!node?.state) continue;
|
||||||
const x = node.position[0];
|
const x = node.position[0];
|
||||||
const y = node.position[1];
|
const y = node.position[1];
|
||||||
const height = this.state.getNodeHeight(node.type);
|
const height = getNodeHeight(node.state.type!);
|
||||||
if (x > x1 - 20 && x < x2 && y > y1 - height && y < y2) {
|
if (x > x1 - 20 && x < x2 && y > y1 - height && y < y2) {
|
||||||
this.state.selectedNodes?.add(node.id);
|
this.state.selectedNodes?.add(node.id);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ export function createNodePath({
|
|||||||
rightBump = false,
|
rightBump = false,
|
||||||
aspectRatio = 1
|
aspectRatio = 1
|
||||||
} = {}) {
|
} = {}) {
|
||||||
|
const leftBumpTopY = y + height / 2;
|
||||||
|
const leftBumpBottomY = y - height / 2;
|
||||||
|
|
||||||
return `M0,${cornerTop}
|
return `M0,${cornerTop}
|
||||||
${
|
${
|
||||||
cornerTop
|
cornerTop
|
||||||
@@ -64,9 +67,7 @@ export function createNodePath({
|
|||||||
}
|
}
|
||||||
${
|
${
|
||||||
leftBump
|
leftBump
|
||||||
? ` V${y + height / 2} C${depth},${y + height / 2} ${depth},${y - height / 2} 0,${
|
? ` V${leftBumpTopY} C${depth},${leftBumpTopY} ${depth},${leftBumpBottomY} 0,${leftBumpBottomY}`
|
||||||
y - height / 2
|
|
||||||
}`
|
|
||||||
: ` H0`
|
: ` H0`
|
||||||
}
|
}
|
||||||
Z`.replace(/\s+/g, ' ');
|
Z`.replace(/\s+/g, ' ');
|
||||||
|
|||||||
73
app/src/lib/graph-interface/helpers/nodeHelpers.ts
Normal file
73
app/src/lib/graph-interface/helpers/nodeHelpers.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import type { NodeDefinition, NodeInstance } from '@nodarium/types';
|
||||||
|
|
||||||
|
export function getParameterHeight(node: NodeDefinition, inputKey: string) {
|
||||||
|
const input = node.inputs?.[inputKey];
|
||||||
|
if (!input) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputKey === 'seed') return 0;
|
||||||
|
if (!node.inputs) return 0;
|
||||||
|
if ('setting' in input) return 0;
|
||||||
|
if (input.hidden) return 0;
|
||||||
|
|
||||||
|
if (input.type === 'shape' && input.external !== true) {
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
input?.label !== '' && !input.external && input.type !== 'path'
|
||||||
|
&& input.type !== 'geometry'
|
||||||
|
) {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSocketPosition(
|
||||||
|
node: NodeInstance,
|
||||||
|
index: string | number
|
||||||
|
): [number, number] {
|
||||||
|
if (typeof index === 'number') {
|
||||||
|
return [
|
||||||
|
(node?.state?.x ?? node.position[0]) + 20,
|
||||||
|
(node?.state?.y ?? node.position[1]) + 2.5 + 10 * index
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
let height = 5;
|
||||||
|
let nodeType = node.state.type!;
|
||||||
|
const inputs = nodeType.inputs || {};
|
||||||
|
for (const inputKey in inputs) {
|
||||||
|
const h = getParameterHeight(nodeType, inputKey) / 10;
|
||||||
|
console.log({ inputKey, h });
|
||||||
|
if (inputKey === index) {
|
||||||
|
height += h / 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
height += h;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
node?.state?.x ?? node.position[0],
|
||||||
|
(node?.state?.y ?? node.position[1]) + height
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeHeightCache: Record<string, number> = {};
|
||||||
|
export function getNodeHeight(node: NodeDefinition) {
|
||||||
|
if (node.id in nodeHeightCache) {
|
||||||
|
return nodeHeightCache[node.id];
|
||||||
|
}
|
||||||
|
if (!node?.inputs) {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
let height = 5;
|
||||||
|
console.log('Get Node Height', node.id);
|
||||||
|
|
||||||
|
for (const key in node.inputs) {
|
||||||
|
const h = getParameterHeight(node, key) / 10;
|
||||||
|
height += h;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeHeightCache[node.id] = height;
|
||||||
|
return height;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
import { type Mesh } from 'three';
|
import { type Mesh } from 'three';
|
||||||
import { getGraphState } from '../graph-state.svelte';
|
import { getGraphState } from '../graph-state.svelte';
|
||||||
import { colors } from '../graph/colors.svelte';
|
import { colors } from '../graph/colors.svelte';
|
||||||
|
import { getNodeHeight } from '../helpers/nodeHelpers';
|
||||||
import NodeFrag from './Node.frag';
|
import NodeFrag from './Node.frag';
|
||||||
import NodeVert from './Node.vert';
|
import NodeVert from './Node.vert';
|
||||||
import NodeHtml from './NodeHTML.svelte';
|
import NodeHtml from './NodeHTML.svelte';
|
||||||
@@ -31,7 +32,7 @@
|
|||||||
|
|
||||||
let meshRef: Mesh | undefined = $state();
|
let meshRef: Mesh | undefined = $state();
|
||||||
|
|
||||||
const height = graphState.getNodeHeight(node.type);
|
const height = getNodeHeight(node.state.type!);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (meshRef && !node.state?.mesh) {
|
if (meshRef && !node.state?.mesh) {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { appSettings } from '$lib/settings/app-settings.svelte';
|
||||||
import type { NodeInstance } from '@nodarium/types';
|
import type { NodeInstance } from '@nodarium/types';
|
||||||
import { getGraphState } from '../graph-state.svelte';
|
import { getGraphState } from '../graph-state.svelte';
|
||||||
import { createNodePath } from '../helpers/index.js';
|
import { createNodePath } from '../helpers/index.js';
|
||||||
|
import { getSocketPosition } from '../helpers/nodeHelpers';
|
||||||
|
|
||||||
const graphState = getGraphState();
|
const graphState = getGraphState();
|
||||||
|
|
||||||
@@ -14,7 +16,7 @@
|
|||||||
graphState.setDownSocket?.({
|
graphState.setDownSocket?.({
|
||||||
node,
|
node,
|
||||||
index: 0,
|
index: 0,
|
||||||
position: graphState.getSocketPosition?.(node, 0)
|
position: getSocketPosition?.(node, 0)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,6 +49,9 @@
|
|||||||
|
|
||||||
<div class="wrapper" data-node-id={node.id} data-node-type={node.type}>
|
<div class="wrapper" data-node-id={node.id} data-node-type={node.type}>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
{#if appSettings.value.debug.advancedMode}
|
||||||
|
<span class="bg-white text-black! mr-2 px-1 rounded-sm opacity-30">{node.id}</span>
|
||||||
|
{/if}
|
||||||
{node.type.split('/').pop()}
|
{node.type.split('/').pop()}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import type { NodeInput, NodeInstance } from '@nodarium/types';
|
import type { NodeInput, NodeInstance } from '@nodarium/types';
|
||||||
import { getGraphManager, getGraphState } from '../graph-state.svelte';
|
import { getGraphManager, getGraphState } from '../graph-state.svelte';
|
||||||
import { createNodePath } from '../helpers';
|
import { createNodePath } from '../helpers';
|
||||||
|
import { getParameterHeight, getSocketPosition } from '../helpers/nodeHelpers';
|
||||||
import NodeInputEl from './NodeInput.svelte';
|
import NodeInputEl from './NodeInput.svelte';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -12,19 +13,18 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const graph = getGraphManager();
|
const graph = getGraphManager();
|
||||||
|
const graphState = getGraphState();
|
||||||
|
const graphId = graph?.id;
|
||||||
|
const elementId = `input-${Math.random().toString(36).substring(7)}`;
|
||||||
|
|
||||||
let { node = $bindable(), input, id, isLast }: Props = $props();
|
let { node = $bindable(), input, id, isLast }: Props = $props();
|
||||||
|
|
||||||
const inputType = $derived(node?.state?.type?.inputs?.[id]);
|
const nodeType = $derived(node.state.type!);
|
||||||
|
|
||||||
|
const inputType = $derived(nodeType.inputs?.[id]);
|
||||||
|
|
||||||
const socketId = $derived(`${node.id}-${id}`);
|
const socketId = $derived(`${node.id}-${id}`);
|
||||||
const isShape = $derived(input.type === 'shape' && input.external !== true);
|
const height = $derived(getParameterHeight(nodeType, id));
|
||||||
const height = $derived(isShape ? 200 : 100);
|
|
||||||
|
|
||||||
const graphState = getGraphState();
|
|
||||||
const graphId = graph?.id;
|
|
||||||
|
|
||||||
const elementId = `input-${Math.random().toString(36).substring(7)}`;
|
|
||||||
|
|
||||||
function handleMouseDown(ev: MouseEvent) {
|
function handleMouseDown(ev: MouseEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
@@ -32,18 +32,18 @@
|
|||||||
graphState.setDownSocket({
|
graphState.setDownSocket({
|
||||||
node,
|
node,
|
||||||
index: id,
|
index: id,
|
||||||
position: graphState.getSocketPosition?.(node, id)
|
position: getSocketPosition(node, id)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const leftBump = $derived(node.state?.type?.inputs?.[id].internal !== true);
|
const leftBump = $derived(nodeType.inputs?.[id].internal !== true);
|
||||||
const cornerBottom = $derived(isLast ? 5 : 0);
|
const cornerBottom = $derived(isLast ? 5 : 0);
|
||||||
const aspectRatio = 0.5;
|
const aspectRatio = 0.5;
|
||||||
|
|
||||||
const path = $derived(
|
const path = $derived(
|
||||||
createNodePath({
|
createNodePath({
|
||||||
depth: 6,
|
depth: 6,
|
||||||
height: 18,
|
height: 1700 / height,
|
||||||
y: 50.5,
|
y: 50.5,
|
||||||
cornerBottom,
|
cornerBottom,
|
||||||
leftBump,
|
leftBump,
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
const pathHover = $derived(
|
const pathHover = $derived(
|
||||||
createNodePath({
|
createNodePath({
|
||||||
depth: 7,
|
depth: 7,
|
||||||
height: 20,
|
height: 2000 / height,
|
||||||
y: 50.5,
|
y: 50.5,
|
||||||
cornerBottom,
|
cornerBottom,
|
||||||
leftBump,
|
leftBump,
|
||||||
@@ -74,10 +74,6 @@
|
|||||||
{#if inputType?.label !== ''}
|
{#if inputType?.label !== ''}
|
||||||
<label for={elementId} title={input.description}>{input.label || id}</label>
|
<label for={elementId} title={input.description}>{input.label || id}</label>
|
||||||
{/if}
|
{/if}
|
||||||
<span
|
|
||||||
class="absolute i-[tabler--help-circle] size-4 block top-2 right-2 opacity-30"
|
|
||||||
title={JSON.stringify(input, null, 2)}
|
|
||||||
></span>
|
|
||||||
{#if inputType?.external !== true}
|
{#if inputType?.external !== true}
|
||||||
<NodeInputEl {graph} {elementId} bind:node {input} {id} />
|
<NodeInputEl {graph} {elementId} bind:node {input} {id} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user