From 71ebbfc348c0a25b1fd9c222890ad7c4290c5c55 Mon Sep 17 00:00:00 2001 From: Max Richter Date: Wed, 6 Mar 2024 18:31:06 +0100 Subject: [PATCH] feat: initial design of parameter ui --- frontend/.gitignore | 2 + frontend/histoire.config.ts | 8 + frontend/package.json | 8 +- frontend/src/lib/components/App.svelte | 36 - .../lib/components/Background.story.svelte | 28 + frontend/src/lib/components/Background.svelte | 64 ++ frontend/src/lib/components/Camera.svelte | 56 + frontend/src/lib/components/Edge.svelte | 10 +- frontend/src/lib/components/Graph.svelte | 110 ++ frontend/src/lib/components/Node.svelte | 46 + frontend/src/lib/components/NodeHeader.svelte | 97 ++ .../src/lib/components/NodeParameter.svelte | 120 +++ frontend/src/lib/components/Scene.svelte | 265 +---- .../src/lib/components/nodes/Output.svelte | 11 - frontend/src/lib/components/nodes/Test.svelte | 11 - frontend/src/lib/components/nodes/index.ts | 6 - frontend/src/lib/graph-manager.ts | 114 +++ frontend/src/lib/helpers.ts | 3 + frontend/src/lib/types.ts | 39 +- frontend/src/routes/+page.svelte | 12 +- pnpm-lock.yaml | 958 +++++++++++++++++- 21 files changed, 1667 insertions(+), 337 deletions(-) create mode 100644 frontend/histoire.config.ts delete mode 100644 frontend/src/lib/components/App.svelte create mode 100644 frontend/src/lib/components/Background.story.svelte create mode 100644 frontend/src/lib/components/Background.svelte create mode 100644 frontend/src/lib/components/Camera.svelte create mode 100644 frontend/src/lib/components/Graph.svelte create mode 100644 frontend/src/lib/components/Node.svelte create mode 100644 frontend/src/lib/components/NodeHeader.svelte create mode 100644 frontend/src/lib/components/NodeParameter.svelte delete mode 100644 frontend/src/lib/components/nodes/Output.svelte delete mode 100644 frontend/src/lib/components/nodes/Test.svelte delete mode 100644 frontend/src/lib/components/nodes/index.ts create mode 100644 frontend/src/lib/graph-manager.ts create mode 100644 frontend/src/lib/helpers.ts diff --git a/frontend/.gitignore b/frontend/.gitignore index 8b466fd..3187a0f 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -7,6 +7,8 @@ yarn-error.log* pnpm-debug.log* lerna-debug.log* +.svelte-kit/ + vite.config.ts.timestamp* node_modules diff --git a/frontend/histoire.config.ts b/frontend/histoire.config.ts new file mode 100644 index 0000000..d7d0f18 --- /dev/null +++ b/frontend/histoire.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'histoire' +import { HstSvelte } from '@histoire/plugin-svelte' + +export default defineConfig({ + plugins: [ + HstSvelte(), + ], +}) diff --git a/frontend/package.json b/frontend/package.json index 3f5d67f..ff24d6c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -7,8 +7,10 @@ "dev": "vite", "build": "vite build", "preview": "vite preview", - "check": "svelte-check --tsconfig ./tsconfig.json", - "tauri": "tauri" + "tauri:dev": "tauri dev", + "story:dev": "histoire dev", + "story:build": "histoire build", + "story:preview": "histoire preview" }, "dependencies": { "@sveltejs/kit": "^2.5.0", @@ -21,10 +23,12 @@ "three": "^0.159.0" }, "devDependencies": { + "@histoire/plugin-svelte": "^0.17.9", "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/vite-plugin-svelte": "^3.0.1", "@tauri-apps/cli": "2.0.0-beta.3", "@tsconfig/svelte": "^5.0.2", + "histoire": "^0.17.9", "internal-ip": "^7.0.0", "svelte": "^4.2.8", "svelte-check": "^3.4.6", diff --git a/frontend/src/lib/components/App.svelte b/frontend/src/lib/components/App.svelte deleted file mode 100644 index df17bcc..0000000 --- a/frontend/src/lib/components/App.svelte +++ /dev/null @@ -1,36 +0,0 @@ - - - - - diff --git a/frontend/src/lib/components/Background.story.svelte b/frontend/src/lib/components/Background.story.svelte new file mode 100644 index 0000000..f88f68a --- /dev/null +++ b/frontend/src/lib/components/Background.story.svelte @@ -0,0 +1,28 @@ + + + + + + + + + + + + diff --git a/frontend/src/lib/components/Background.svelte b/frontend/src/lib/components/Background.svelte new file mode 100644 index 0000000..c497ed4 --- /dev/null +++ b/frontend/src/lib/components/Background.svelte @@ -0,0 +1,64 @@ + + + + + + + + diff --git a/frontend/src/lib/components/Camera.svelte b/frontend/src/lib/components/Camera.svelte new file mode 100644 index 0000000..1af33f5 --- /dev/null +++ b/frontend/src/lib/components/Camera.svelte @@ -0,0 +1,56 @@ + + + { + ref.onBeforeRender = () => { + console.log(ref.position); + }; + + cleanup(() => {}); + }} +> + + diff --git a/frontend/src/lib/components/Edge.svelte b/frontend/src/lib/components/Edge.svelte index 06a83d5..53269dc 100644 --- a/frontend/src/lib/components/Edge.svelte +++ b/frontend/src/lib/components/Edge.svelte @@ -9,8 +9,6 @@ let samples = 20; - console.log("edge"); - const curve = new CubicBezierCurve( new Vector2(from.position.x + 20, from.position.y), new Vector2(from.position.x + 2, from.position.y), @@ -33,10 +31,10 @@ last_from_x = new_x; last_from_y = new_y; } - curve.v0.set(from.position.x + 5, from.position.y + 1.25); - curve.v1.set(from.position.x + 6, from.position.y + 1.25); - curve.v2.set(to.position.x - 1, to.position.y + 1.25); - curve.v3.set(to.position.x, to.position.y + 1.25); + curve.v0.set(from.position.x + 5, from.position.y + 5 / 8); + curve.v1.set(from.position.x + 7, from.position.y + 5 / 8); + curve.v2.set(to.position.x - 2, to.position.y + 2.55); + curve.v3.set(to.position.x + 0.2, to.position.y + 2.55); points = curve.getPoints(samples).map((p) => new Vector3(p.x, 0, p.y)); } diff --git a/frontend/src/lib/components/Graph.svelte b/frontend/src/lib/components/Graph.svelte new file mode 100644 index 0000000..922602c --- /dev/null +++ b/frontend/src/lib/components/Graph.svelte @@ -0,0 +1,110 @@ + + + + +{#each edges as edge} + +{/each} + + +
+ {#each graph.nodes as node} + + {/each} +
+ + + diff --git a/frontend/src/lib/components/Node.svelte b/frontend/src/lib/components/Node.svelte new file mode 100644 index 0000000..a7d8688 --- /dev/null +++ b/frontend/src/lib/components/Node.svelte @@ -0,0 +1,46 @@ + + +
+ + + {#each parameters as [key, value], i} + + {/each} +
+ + diff --git a/frontend/src/lib/components/NodeHeader.svelte b/frontend/src/lib/components/NodeHeader.svelte new file mode 100644 index 0000000..f66fac2 --- /dev/null +++ b/frontend/src/lib/components/NodeHeader.svelte @@ -0,0 +1,97 @@ + + +
+
+ {node.type} +
+ + + +
+ + diff --git a/frontend/src/lib/components/NodeParameter.svelte b/frontend/src/lib/components/NodeParameter.svelte new file mode 100644 index 0000000..0538a92 --- /dev/null +++ b/frontend/src/lib/components/NodeParameter.svelte @@ -0,0 +1,120 @@ + + +
+
+ + + +
+ + + + +
+ + diff --git a/frontend/src/lib/components/Scene.svelte b/frontend/src/lib/components/Scene.svelte index 4425acc..e0da6e1 100644 --- a/frontend/src/lib/components/Scene.svelte +++ b/frontend/src/lib/components/Scene.svelte @@ -1,24 +1,16 @@ - + + + + -{#if true} - - - - - - +{#if $status === "idle"} + +{:else if $status === "loading"} + Loading... +{:else if $status === "error"} + Error {/if} - - - - - - - - - - - - -{#each edges as edge} - -{/each} - - -
- {#each graph.nodes as node} -
- {node.id} -
- {/each} -
- - - diff --git a/frontend/src/lib/components/nodes/Output.svelte b/frontend/src/lib/components/nodes/Output.svelte deleted file mode 100644 index d764c3c..0000000 --- a/frontend/src/lib/components/nodes/Output.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - - -

output

diff --git a/frontend/src/lib/components/nodes/Test.svelte b/frontend/src/lib/components/nodes/Test.svelte deleted file mode 100644 index 93e784c..0000000 --- a/frontend/src/lib/components/nodes/Test.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/frontend/src/lib/components/nodes/index.ts b/frontend/src/lib/components/nodes/index.ts deleted file mode 100644 index a53f827..0000000 --- a/frontend/src/lib/components/nodes/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import Test from './Test.svelte'; -import Output from './Output.svelte'; -export const nodes = { - test: Test, - output: Output, -} as const; diff --git a/frontend/src/lib/graph-manager.ts b/frontend/src/lib/graph-manager.ts new file mode 100644 index 0000000..214dcb0 --- /dev/null +++ b/frontend/src/lib/graph-manager.ts @@ -0,0 +1,114 @@ +import { writable, type Writable } from "svelte/store"; +import type { Graph, NodeRegistry as INodeRegistry, NodeType, Node } from "./types"; +import { snapToGrid } from "./helpers"; + +const nodeTypes: NodeType[] = [ + { + id: "input/float", + inputs: { + "value": { type: "float" }, + }, + outputs: ["float"], + }, + { + id: "math", + inputs: { + "a": { type: "float" }, + "b": { type: "float" }, + }, + outputs: ["float"], + }, +] + +export class NodeRegistry implements INodeRegistry { + getNode(id: string): NodeType | undefined { + return nodeTypes.find((nodeType) => nodeType.id === id); + } +} + + +export class GraphManager { + + status: Writable<"loading" | "idle" | "error"> = writable("loading"); + + nodes: Node[] = []; + edges: { from: string, to: string }[] = []; + + private constructor(private graph: Graph, private nodeRegistry: NodeRegistry = new NodeRegistry()) { + } + + async load() { + + const nodes = this.graph.nodes; + + for (const node of nodes) { + const nodeType = this.getNodeType(node.type); + if (!nodeType) { + console.error(`Node type not found: ${node.type}`); + this.status.set("error"); + return; + } + } + + this.nodes = this.graph.nodes; + this.edges = this.graph.edges; + this.status.set("idle"); + } + + getNode(id: string) { + return this.nodes.find((node) => node.id === id); + } + + public getNodeType(id: string): NodeType { + return this.nodeRegistry.getNode(id)!; + } + + public getEdges() { + return this.edges + .map((edge) => { + const from = this.nodes.find((node) => node.id === edge.from); + const to = this.nodes.find((node) => node.id === edge.to); + if (!from || !to) return; + return [from, to] as const; + }) + .filter(Boolean) as unknown as [Node, Node][]; + } + + + static createEmptyGraph(): GraphManager { + + const graph: Graph = { + edges: [], + nodes: [], + }; + + for (let i = 0; i < 40; i++) { + const x = i % 20; + const y = Math.floor(i / 20); + + graph.nodes.push({ + id: `${i.toString()}`, + tmp: { + visible: false, + }, + position: { + x: x * 7.5, + y: y * 5, + }, + props: i == 0 ? { value: 0 } : {}, + type: i == 0 ? "input/float" : "math", + }); + + graph.edges.push({ + from: i.toString(), + to: (i + 1).toString(), + }); + } + + return new GraphManager(graph); + } + + +} + + diff --git a/frontend/src/lib/helpers.ts b/frontend/src/lib/helpers.ts new file mode 100644 index 0000000..87c43f1 --- /dev/null +++ b/frontend/src/lib/helpers.ts @@ -0,0 +1,3 @@ +export function snapToGrid(value: number, gridSize: number = 10) { + return Math.round(value / gridSize) * gridSize; + } diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts index 337fd51..4046b2a 100644 --- a/frontend/src/lib/types.ts +++ b/frontend/src/lib/types.ts @@ -1,8 +1,7 @@ -import { nodes } from "$lib/components/nodes" export type Node = { id: string; - type: keyof typeof nodes; + type: string; props?: Record, tmp?: { downX?: number; @@ -19,6 +18,42 @@ export type Node = { } } +type NodeInputFloat = { + type: "float"; + value?: number; + min?: number; + max?: number; +} + +type NodeInputInteger = { + type: "integer"; + value?: number; + min?: number; + max?: number; +} + +type NodeInputSelect = { + type: "select"; + value?: string; + options: string[]; +} + +export type NodeInput = NodeInputFloat | NodeInputInteger | NodeInputSelect; + +export type NodeType = { + id: string; + inputs?: Record; + outputs?: string[]; + meta?: { + title?: string; + } +} + +export interface NodeRegistry { + getNode: (id: string) => NodeType | undefined; +} + + export type Edge = { from: string; to: string; diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 8664dfc..a10faf2 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,8 +1,14 @@
- + + +