feat: improve loading times

This commit is contained in:
max_richter 2024-03-20 17:39:52 +01:00
parent 92a7e62d6a
commit 84bcfa61d8
12 changed files with 62 additions and 51 deletions

View File

@ -24,7 +24,7 @@
.selection {
width: 40px;
height: 20px;
border: solid 0.2px white;
border: solid 0.2px rgba(200, 200, 200, 0.8);
border-style: dashed;
border-radius: 2px;
}

View File

@ -19,17 +19,11 @@
import { CubicBezierCurve } from "three/src/extras/curves/CubicBezierCurve.js";
import { Vector3 } from "three/src/math/Vector3.js";
import { Vector2 } from "three/src/math/Vector2.js";
import { LineMaterial } from "three/examples/jsm/Addons.js";
export let from: { x: number; y: number };
export let to: { x: number; y: number };
const samples = Math.max(
5,
Math.floor(
Math.sqrt(Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2)) / 2,
),
);
let samples = 5;
const curve = new CubicBezierCurve(
new Vector2(from.x, from.y),
@ -45,8 +39,6 @@
let mesh: Mesh;
const color = new Color(32 / 255, 32 / 255, 32 / 255);
export const update = function (force = false) {
if (!force) {
const new_x = from.x + to.x;
@ -60,18 +52,17 @@
const mid = new Vector2((from.x + to.x) / 2, (from.y + to.y) / 2);
// const length = Math.sqrt(
// Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2),
// );
//
const length = Math.floor(
Math.sqrt(Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2)) / 4,
);
samples = Math.min(Math.max(10, length), 100);
curve.v0.set(from.x, from.y);
curve.v1.set(mid.x, from.y);
curve.v2.set(mid.x, to.y);
curve.v3.set(to.x, to.y);
points = curve.getPoints(samples).map((p) => new Vector3(p.x, 0, p.y));
// mesh.setGeometry(points);
// mesh.needsUpdate = true;
};
update();
@ -101,7 +92,9 @@
</T.Mesh>
<T.Mesh position.y={0.5} bind:ref={mesh}>
<MeshLineGeometry {points} />
{#key samples}
<MeshLineGeometry {points} />
{/key}
<MeshLineMaterial
width={4}
attenuate={false}

View File

@ -24,6 +24,7 @@
const status = graph.status;
const nodes = graph.nodes;
const edges = graph.edges;
const graphId = graph.id;
let camera: OrthographicCamera;
const minZoom = 1;
@ -523,8 +524,6 @@
const clickedNodeId = getNodeIdFromEvent(event);
console.log({ clickedNodeId });
if (clickedNodeId !== -1) {
if (activeNode) {
if (!activeNode?.tmp?.isMoving && !event.ctrlKey && !event.shiftKey) {
@ -676,7 +675,9 @@
to={{ x: mousePosition[0], y: mousePosition[1] }}
/>
{/if}
<GraphView {nodes} {edges} {cameraPosition} />
{#key $graphId}
<GraphView {nodes} {edges} {cameraPosition} />
{/key}
{:else if $status === "loading"}
<span>Loading</span>
{:else if $status === "error"}

View File

@ -78,6 +78,7 @@
width: 0px;
height: 0px;
transform: scale(calc(var(--cz) * 0.1));
--input-opacity: calc((var(--cz) - 2) / 5);
display: var(--node-display, block);
opacity: calc((var(--cz) - 2) / 5);
}
</style>

View File

@ -4,7 +4,7 @@ import { writable, type Writable } from "svelte/store";
import { Color } from "three/src/math/Color.js";
export const activeNodeId: Writable<number> = writable(-1);
export const selectedNodes: Writable<Set<number> | null> = writable(null);
export const selectedNodes: Writable<Set<number> | null> = writable(new Set());
export const activeSocket: Writable<Socket | null> = writable(null);
export const hoveredSocket: Writable<Socket | null> = writable(null);

View File

@ -68,7 +68,7 @@
uniforms={{
uColorBright: { value: colorBright },
uColorDark: { value: colorDark },
uSelectedColor: { value: new Color("#f2be90") },
uSelectedColor: { value: new Color("#9d5f28") },
uActiveColor: { value: new Color("white") },
uSelected: { value: false },
uActive: { value: false },
@ -113,10 +113,8 @@
transform: translate3d(var(--nx), var(--ny), 0);
z-index: 1;
font-weight: 300;
display: var(--node-display, block);
--stroke: var(--background-color-lighter);
--stroke-width: 2px;
opacity: var(--input-opacity);
}
.node.active {
@ -125,7 +123,7 @@
}
.node.selected {
--stroke: #f2be90;
--stroke: #9d5f28;
--stroke-width: 1px;
}

View File

@ -3,12 +3,15 @@ import { type Graph, type Node, type Edge, type Socket, type NodeRegistry, type
import { HistoryManager } from "./history-manager";
import * as templates from "./graphs";
import EventEmitter from "./helpers/EventEmitter";
import throttle from "./helpers/throttle";
export class GraphManager extends EventEmitter<{ "save": Graph }> {
status: Writable<"loading" | "idle" | "error"> = writable("loading");
loaded = false;
graph: Graph = { nodes: [], edges: [] };
graph: Graph = { id: 0, nodes: [], edges: [] };
id = writable(0);
private _nodes: Map<number, Node> = new Map();
nodes: Writable<Map<number, Node>> = writable(new Map());
@ -32,6 +35,7 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> {
}
this.inputSockets.set(s);
});
this.execute = throttle(() => this._execute(), 100);
}
serialize(): Graph {
@ -42,11 +46,12 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> {
props: node.props,
}));
const edges = this._edges.map(edge => [edge[0].id, edge[1], edge[2].id, edge[3]]) as Graph["edges"];
return { nodes, edges };
return { id: this.graph.id, nodes, edges };
}
execute() {
if (!this.runtime["loaded"]) return;
execute() { }
_execute() {
if (this.loaded === false) return;
const start = performance.now();
const result = this.runtime.execute(this.serialize());
const end = performance.now();
@ -64,12 +69,11 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> {
return [node.id, node]
}));
this.edges.set(graph.edges.map((edge) => {
const edges = graph.edges.map((edge) => {
const from = nodes.get(edge[0]);
const to = nodes.get(edge[2]);
if (!from || !to) {
console.error("Edge references non-existing node");
return;
throw new Error("Edge references non-existing node");
};
from.tmp = from.tmp || {};
from.tmp.children = from.tmp.children || [];
@ -77,19 +81,22 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> {
to.tmp = to.tmp || {};
to.tmp.parents = to.tmp.parents || [];
to.tmp.parents.push(from);
return [from, edge[1], to, edge[3]] as const;
return [from, edge[1], to, edge[3]] as Edge;
})
.filter(Boolean) as unknown as [Node, number, Node, string][]
);
this.edges.set(edges);
this.nodes.set(nodes);
}
async load(graph: Graph) {
this.loaded = false;
this.graph = graph;
const a = performance.now();
this.status.set("loading");
this.id.set(graph.id);
const b = performance.now();
for (const node of this.graph.nodes) {
const nodeType = this.nodeRegistry.getNode(node.type);
if (!nodeType) {
@ -100,13 +107,24 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> {
node.tmp = node.tmp || {};
node.tmp.type = nodeType;
}
const c = performance.now();
this._init(this.graph);
setTimeout(() => {
this.status.set("idle");
this.save();
}, 100)
const d = performance.now();
this.save();
const e = performance.now();
this.status.set("idle");
this.loaded = true;
const f = performance.now();
requestAnimationFrame(() => {
console.log(`Loading took ${f - a}ms; a-b: ${b - a}ms; b-c: ${c - b}ms; c-d: ${d - c}ms; d-e: ${e - d}ms; e-f: ${f - e}ms`);
this.execute();
});
}

View File

@ -3,6 +3,7 @@ import type { Graph } from "$lib/types";
export function grid(width: number, height: number) {
const graph: Graph = {
id: Math.floor(Math.random() * 100000),
edges: [],
nodes: [],
};

View File

@ -47,6 +47,10 @@ export function tree(depth: number): Graph {
}
return { nodes, edges };
return {
id: Math.floor(Math.random() * 100000),
nodes,
edges
};
}

View File

@ -1,14 +1,8 @@
import type { Graph, Node, NodeRegistry, NodeType, RuntimeExecutor } from "./types";
import type { Graph, NodeRegistry, NodeType, RuntimeExecutor } from "./types";
export class MemoryRuntimeExecutor implements RuntimeExecutor {
loaded = false;
constructor(private registry: NodeRegistry) {
setTimeout(() => {
this.loaded = true;
}, 500);
}
constructor(private registry: NodeRegistry) { }
private getNodeTypes(graph: Graph) {
@ -92,7 +86,6 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
}
execute(graph: Graph) {
if (!this.loaded) return;
// Then we add some metadata to the graph
const [outputNode, nodes] = this.addMetaData(graph);

View File

@ -7,6 +7,7 @@ export type Node = {
props?: Record<string, any>,
tmp?: {
depth?: number;
mesh?: any;
parents?: Node[],
children?: Node[],
inputNodes?: Record<string, Node>
@ -58,6 +59,7 @@ export interface RuntimeExecutor {
export type Edge = [Node, number, Node, string];
export type Graph = {
id: number;
meta?: {
title?: string;
lastModified?: string;

View File

@ -37,7 +37,7 @@
<br />
<button
on:click={() =>
graphManager.load(graphManager.createTemplate("grid", 5, 5))}
graphManager.load(graphManager.createTemplate("grid", 10, 10))}
>load grid</button
>
<br />