feat: improve zoom performance by adding a tiny rand offset to nodes
This commit is contained in:
parent
06ba3a8fe9
commit
c33e2642e1
@ -119,6 +119,7 @@ export class GraphManager extends EventEmitter<{ "save": Graph, "result": any }>
|
||||
const nodeType = this.nodeRegistry.getNode(node.type);
|
||||
if (nodeType) {
|
||||
node.tmp = {
|
||||
random: (Math.random() - 0.5) * 2,
|
||||
type: nodeType
|
||||
};
|
||||
}
|
||||
@ -173,6 +174,7 @@ export class GraphManager extends EventEmitter<{ "save": Graph, "result": any }>
|
||||
return;
|
||||
}
|
||||
node.tmp = node.tmp || {};
|
||||
node.tmp.random = (Math.random() - 0.5) * 2;
|
||||
node.tmp.type = nodeType;
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,23 @@
|
||||
<script lang="ts">
|
||||
import type { Edge as EdgeType, Node as NodeType } from '@nodes/types';
|
||||
import { HTML } from '@threlte/extras';
|
||||
import Edge from '../edges/Edge.svelte';
|
||||
import Node from '../node/Node.svelte';
|
||||
import { getContext, onMount } from 'svelte';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import { activeSocket } from './stores.js';
|
||||
import type { Edge as EdgeType, Node as NodeType } from "@nodes/types";
|
||||
import { HTML } from "@threlte/extras";
|
||||
import Edge from "../edges/Edge.svelte";
|
||||
import Node from "../node/Node.svelte";
|
||||
import { getContext, onMount } from "svelte";
|
||||
import type { Writable } from "svelte/store";
|
||||
import { activeSocket } from "./stores.js";
|
||||
|
||||
export let nodes: Writable<Map<number, NodeType>>;
|
||||
export let edges: Writable<EdgeType[]>;
|
||||
|
||||
export let cameraPosition = [0, 0, 4];
|
||||
|
||||
const isNodeInView = getContext<(n: NodeType) => boolean>('isNodeInView');
|
||||
const isNodeInView = getContext<(n: NodeType) => boolean>("isNodeInView");
|
||||
|
||||
const getSocketPosition =
|
||||
getContext<(node: NodeType, index: string | number) => [number, number]>('getSocketPosition');
|
||||
getContext<(node: NodeType, index: string | number) => [number, number]>(
|
||||
"getSocketPosition",
|
||||
);
|
||||
|
||||
function getEdgePosition(edge: EdgeType) {
|
||||
const pos1 = getSocketPosition(edge[0], edge[1]);
|
||||
@ -27,8 +29,8 @@
|
||||
onMount(() => {
|
||||
for (const node of $nodes.values()) {
|
||||
if (node?.tmp?.ref) {
|
||||
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("--nx", `${node.position[0] * 10}px`);
|
||||
node.tmp.ref.style.setProperty("--ny", `${node.position[1] * 10}px`);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -40,11 +42,11 @@
|
||||
<Edge
|
||||
from={{
|
||||
x: x1,
|
||||
y: y1
|
||||
y: y1,
|
||||
}}
|
||||
to={{
|
||||
x: x2,
|
||||
y: y2
|
||||
y: y2,
|
||||
}}
|
||||
/>
|
||||
{/each}
|
||||
@ -55,12 +57,15 @@
|
||||
id="graph"
|
||||
tabindex="0"
|
||||
class="wrapper"
|
||||
class:zoom-small={cameraPosition[2] < 2}
|
||||
style:transform={`scale(${cameraPosition[2] * 0.1})`}
|
||||
class:hovering-sockets={activeSocket}
|
||||
style={`--cz: ${cameraPosition[2]}; --node-display: ${cameraPosition[2] < 2 ? 'none' : 'block'};`}
|
||||
>
|
||||
{#each $nodes.values() as node (node.id)}
|
||||
<Node {node} inView={cameraPosition && isNodeInView(node)} z={cameraPosition[2]} />
|
||||
<Node
|
||||
{node}
|
||||
inView={cameraPosition && isNodeInView(node)}
|
||||
z={cameraPosition[2]}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</HTML>
|
||||
@ -71,8 +76,5 @@
|
||||
z-index: 100;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
transform: scale(calc(var(--cz) * 0.1));
|
||||
display: var(--node-display, block);
|
||||
opacity: calc((var(--cz) - 2.5) / 3.5);
|
||||
}
|
||||
</style>
|
||||
|
@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { Node } from '@nodes/types';
|
||||
import { getContext, onMount } from 'svelte';
|
||||
import NodeHeader from './NodeHeader.svelte';
|
||||
import NodeParameter from './NodeParameter.svelte';
|
||||
import { activeNodeId, selectedNodes } from '../graph/stores.js';
|
||||
import { T } from '@threlte/core';
|
||||
import { Color, type Mesh } from 'three';
|
||||
import NodeFrag from './Node.frag';
|
||||
import NodeVert from './Node.vert';
|
||||
import type { Node } from "@nodes/types";
|
||||
import { getContext, onMount } from "svelte";
|
||||
import NodeHeader from "./NodeHeader.svelte";
|
||||
import NodeParameter from "./NodeParameter.svelte";
|
||||
import { activeNodeId, selectedNodes } from "../graph/stores.js";
|
||||
import { T } from "@threlte/core";
|
||||
import { Color, type Mesh } from "three";
|
||||
import NodeFrag from "./Node.frag";
|
||||
import NodeVert from "./Node.vert";
|
||||
|
||||
export let node: Node;
|
||||
export let inView = true;
|
||||
@ -16,15 +16,20 @@
|
||||
$: isActive = $activeNodeId === node.id;
|
||||
$: isSelected = !!$selectedNodes?.has(node.id);
|
||||
|
||||
const updateNodePosition = getContext<(n: Node) => void>('updateNodePosition');
|
||||
const updateNodePosition =
|
||||
getContext<(n: Node) => void>("updateNodePosition");
|
||||
|
||||
const getNodeHeight = getContext<(n: string) => number>('getNodeHeight');
|
||||
const getNodeHeight = getContext<(n: string) => number>("getNodeHeight");
|
||||
|
||||
const type = node?.tmp?.type;
|
||||
|
||||
const zOffset = (node.tmp?.random || 0) * 0.5;
|
||||
const zLimit = 2 - zOffset;
|
||||
$: visible = inView && z > zLimit;
|
||||
|
||||
const parameters = Object.entries(type?.inputs || {})
|
||||
.filter((p) => p[1].type !== 'seed')
|
||||
.filter((p) => !('setting' in p[1]));
|
||||
.filter((p) => p[1].type !== "seed")
|
||||
.filter((p) => !("setting" in p[1]));
|
||||
|
||||
let ref: HTMLDivElement;
|
||||
let meshRef: Mesh;
|
||||
@ -46,10 +51,10 @@
|
||||
});
|
||||
|
||||
const colorDark = new Color();
|
||||
colorDark.setStyle('#151515');
|
||||
colorDark.setStyle("#151515");
|
||||
//colorDark.();
|
||||
|
||||
const colorBright = new Color('#202020');
|
||||
const colorBright = new Color("#202020");
|
||||
//colorBright.convertLinearToSRGB();
|
||||
</script>
|
||||
|
||||
@ -59,7 +64,7 @@
|
||||
position.y={0.8}
|
||||
rotation.x={-Math.PI / 2}
|
||||
bind:ref={meshRef}
|
||||
visible={z < 7}
|
||||
visible={inView && z < 7}
|
||||
>
|
||||
<T.PlaneGeometry args={[20, height]} radius={1} />
|
||||
<T.ShaderMaterial
|
||||
@ -69,13 +74,13 @@
|
||||
uniforms={{
|
||||
uColorBright: { value: colorBright },
|
||||
uColorDark: { value: colorDark },
|
||||
uSelectedColor: { value: new Color('#9d5f28') },
|
||||
uActiveColor: { value: new Color('white') },
|
||||
uSelectedColor: { value: new Color("#9d5f28") },
|
||||
uActiveColor: { value: new Color("white") },
|
||||
uSelected: { value: false },
|
||||
uActive: { value: false },
|
||||
uStrokeWidth: { value: 1.0 },
|
||||
uWidth: { value: 20 },
|
||||
uHeight: { value: height }
|
||||
uHeight: { value: height },
|
||||
}}
|
||||
uniforms.uSelected.value={isSelected}
|
||||
uniforms.uActive.value={isActive}
|
||||
@ -86,6 +91,8 @@
|
||||
<div
|
||||
class="node"
|
||||
class:active={isActive}
|
||||
style:--cz={z + zOffset}
|
||||
style:display={inView && z > zLimit ? "block" : "none"}
|
||||
class:selected={isSelected}
|
||||
class:out-of-view={!inView}
|
||||
data-node-id={node.id}
|
||||
@ -94,7 +101,12 @@
|
||||
<NodeHeader {node} />
|
||||
|
||||
{#each parameters as [key, value], i}
|
||||
<NodeParameter bind:node id={key} input={value} isLast={i == parameters.length - 1} />
|
||||
<NodeParameter
|
||||
bind:node
|
||||
id={key}
|
||||
input={value}
|
||||
isLast={i == parameters.length - 1}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@ -108,6 +120,7 @@
|
||||
color: var(--text-color);
|
||||
transform: translate3d(var(--nx), var(--ny), 0);
|
||||
z-index: 1;
|
||||
opacity: calc((var(--cz) - 2.5) / 3.5);
|
||||
font-weight: 300;
|
||||
--stroke: var(--background-color-lighter);
|
||||
--stroke-width: 2px;
|
||||
@ -122,8 +135,4 @@
|
||||
--stroke: #9d5f28;
|
||||
--stroke-width: 1px;
|
||||
}
|
||||
|
||||
.node.out-of-view {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
@ -156,10 +156,6 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:global(.zoom-small) .content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
|
@ -183,7 +183,7 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
|
||||
return value;
|
||||
});
|
||||
|
||||
console.log(transformed_inputs);
|
||||
// console.log(transformed_inputs);
|
||||
|
||||
const a2 = performance.now();
|
||||
|
||||
@ -191,7 +191,7 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
|
||||
|
||||
const _inputs = concat_encoded(transformed_inputs);
|
||||
const a3 = performance.now();
|
||||
console.log(`executing ${node_type.id || node.id}`, _inputs);
|
||||
// console.log(`executing ${node_type.id || node.id}`, _inputs);
|
||||
results[node.id] = node_type.execute(_inputs) as number;
|
||||
const duration = performance.now() - a3;
|
||||
if (duration > 5) {
|
||||
|
@ -75,7 +75,7 @@
|
||||
header
|
||||
<button
|
||||
on:click={() => {
|
||||
graph = templates.grid(10, 10);
|
||||
graph = templates.grid(15, 15);
|
||||
}}>grid stress-test</button
|
||||
>
|
||||
</header>
|
||||
|
@ -8,6 +8,7 @@ export type Node = {
|
||||
tmp?: {
|
||||
depth?: number;
|
||||
mesh?: any;
|
||||
random?: number;
|
||||
parents?: Node[],
|
||||
children?: Node[],
|
||||
inputNodes?: Record<string, Node>
|
||||
|
Loading…
Reference in New Issue
Block a user