From 571bb2a5d3e973275e880cc684a957ec757c3b9a Mon Sep 17 00:00:00 2001 From: Max Richter Date: Fri, 23 Jan 2026 02:28:17 +0100 Subject: [PATCH] feat: some shit --- .../graph-interface/node/NodeHeader.svelte | 8 +- app/src/lib/runtime/runtime-executor.ts | 38 +++- app/src/lib/settings/app-settings.svelte.ts | 181 +++++++++--------- app/src/routes/dev/+page.svelte | 65 +++++-- app/src/routes/dev/dev-graph.json | 49 +++-- nodes/max/plantarium/float/src/lib.rs | 5 +- nodes/max/plantarium/output/src/lib.rs | 21 +- nodes/max/plantarium/vec3/src/lib.rs | 12 +- package.json | 1 + packages/utils/src/lib.rs | 16 +- 10 files changed, 243 insertions(+), 153 deletions(-) diff --git a/app/src/lib/graph-interface/node/NodeHeader.svelte b/app/src/lib/graph-interface/node/NodeHeader.svelte index 83478e5..f1453cb 100644 --- a/app/src/lib/graph-interface/node/NodeHeader.svelte +++ b/app/src/lib/graph-interface/node/NodeHeader.svelte @@ -2,6 +2,7 @@ import { getGraphState } from "../graph-state.svelte"; import { createNodePath } from "../helpers/index.js"; import type { NodeInstance } from "@nodarium/types"; + import { appSettings } from "$lib/settings/app-settings.svelte"; const graphState = getGraphState(); @@ -43,7 +44,12 @@
- {node.type.split("/").pop()} ({node.id}) + {#if appSettings.value.nodeInterface.showNodeIds} + {node.id} + {/if} + {node.type.split("/").pop()}
= {}; inputPtrs: Record = {}; + allPtrs: Pointer[] = []; - seed = 123123; + seed = 42424242; perf?: PerformanceStore; @@ -202,11 +203,13 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor { this.offset += length; - return { + const ptr = { start, end, _title: title }; + this.allPtrs.push(ptr); + return ptr; } private printMemory() { @@ -214,10 +217,13 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor { console.log('MEMORY', this.memoryView.slice(0, 10)); } - async execute(graph: Graph, _settings: Record) { + async execute(graph: Graph, settings: Record) { this.offset = 0; this.inputPtrs = {}; + this.seed = this.seed += 2; this.results = {}; + this.allPtrs = []; + if (this.isRunning) return undefined as unknown as Int32Array; this.isRunning = true; @@ -240,11 +246,22 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor { (a, b) => (b.state?.depth || 0) - (a.state?.depth || 0) ); + console.log({ settings }); + + this.printMemory(); + const seedPtr = this.writeToMemory(this.seed, 'seed'); + + const settingPtrs = new Map( + Object.entries(settings).map(( + [key, value] + ) => [key as string, this.writeToMemory(value as number, `setting.${key}`)]) + ); + for (const node of sortedNodes) { const node_type = this.nodes.get(node.type)!; console.log('---------------'); - console.log('STARTING NODE EXECUTION', node_type.definition.id); + console.log('STARTING NODE EXECUTION', node_type.definition.id + '/' + node.id); this.printMemory(); // console.log(node_type.definition.inputs); @@ -252,23 +269,24 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor { ([key, input]) => { // We should probably initially write this to memory if (input.type === 'seed') { - return this.writeToMemory(this.seed); + return seedPtr; } const title = `${node.id}.${key}`; // We should probably initially write this to memory // If the input is linked to a setting, we use that value - // if (input.setting) { - // return getValue(input, settings[input.setting]); - // } + // TODO: handle nodes which reference undefined settings + if (input.setting) { + return settingPtrs.get(input.setting)!; + } // check if the input is connected to another node const inputNode = node.state.inputNodes[key]; if (inputNode) { if (this.results[inputNode.id] === undefined) { throw new Error( - `Node ${node.type} is missing input from node ${inputNode.type}` + `Node ${node.type}/${node.id} is missing input from node ${inputNode.type}/${inputNode.id}` ); } return this.results[inputNode.id]; @@ -317,6 +335,7 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor { end: args[1], _title: `${node.id} ->` }; + this.allPtrs.push(this.results[node.id]); } else { this.results[node.id] = { start: this.offset, @@ -324,6 +343,7 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor { _title: `${node.id} ->` }; this.offset += bytesWritten / 4; + this.allPtrs.push(this.results[node.id]); } console.log('FINISHED EXECUTION', { bytesWritten, diff --git a/app/src/lib/settings/app-settings.svelte.ts b/app/src/lib/settings/app-settings.svelte.ts index d5f5829..1c656cc 100644 --- a/app/src/lib/settings/app-settings.svelte.ts +++ b/app/src/lib/settings/app-settings.svelte.ts @@ -1,148 +1,147 @@ -import { localState } from "$lib/helpers/localState.svelte"; +import { localState } from '$lib/helpers/localState.svelte'; const themes = [ - "dark", - "light", - "catppuccin", - "solarized", - "high-contrast", - "nord", - "dracula", + 'dark', + 'light', + 'catppuccin', + 'solarized', + 'high-contrast', + 'nord', + 'dracula' ] as const; export const AppSettingTypes = { theme: { - type: "select", + type: 'select', options: themes, - label: "Theme", - value: themes[0], + label: 'Theme', + value: themes[0] }, showGrid: { - type: "boolean", - label: "Show Grid", - value: true, + type: 'boolean', + label: 'Show Grid', + value: true }, centerCamera: { - type: "boolean", - label: "Center Camera", - value: true, + type: 'boolean', + label: 'Center Camera', + value: true }, nodeInterface: { - title: "Node Interface", + title: 'Node Interface', showNodeGrid: { - type: "boolean", - label: "Show Grid", - value: true, + type: 'boolean', + label: 'Show Grid', + value: true }, snapToGrid: { - type: "boolean", - label: "Snap to Grid", - value: true, + type: 'boolean', + label: 'Snap to Grid', + value: true }, showHelp: { - type: "boolean", - label: "Show Help", - value: false, + type: 'boolean', + label: 'Show Help', + value: false }, + showNodeIds: { + type: 'boolean', + label: 'Show Node Ids', + value: false + } }, debug: { - title: "Debug", + title: 'Debug', wireframe: { - type: "boolean", - label: "Wireframe", - value: false, + type: 'boolean', + label: 'Wireframe', + value: false }, useWorker: { - type: "boolean", - label: "Execute in WebWorker", - value: true, + type: 'boolean', + label: 'Execute in WebWorker', + value: true }, showIndices: { - type: "boolean", - label: "Show Indices", - value: false, + type: 'boolean', + label: 'Show Indices', + value: false }, showPerformancePanel: { - type: "boolean", - label: "Show Performance Panel", - value: false, + type: 'boolean', + label: 'Show Performance Panel', + value: false }, showBenchmarkPanel: { - type: "boolean", - label: "Show Benchmark Panel", - value: false, + type: 'boolean', + label: 'Show Benchmark Panel', + value: false }, showVertices: { - type: "boolean", - label: "Show Vertices", - value: false, + type: 'boolean', + label: 'Show Vertices', + value: false }, showStemLines: { - type: "boolean", - label: "Show Stem Lines", - value: false, + type: 'boolean', + label: 'Show Stem Lines', + value: false }, showGraphJson: { - type: "boolean", - label: "Show Graph Source", - value: false, + type: 'boolean', + label: 'Show Graph Source', + value: false }, cache: { - title: "Cache", + title: 'Cache', useRuntimeCache: { - type: "boolean", - label: "Node Results", - value: true, + type: 'boolean', + label: 'Node Results', + value: true }, useRegistryCache: { - type: "boolean", - label: "Node Source", - value: true, - }, + type: 'boolean', + label: 'Node Source', + value: true + } }, stressTest: { - title: "Stress Test", + title: 'Stress Test', amount: { - type: "integer", + type: 'integer', min: 2, max: 15, - value: 4, + value: 4 }, loadGrid: { - type: "button", - label: "Load Grid", + type: 'button', + label: 'Load Grid' }, loadTree: { - type: "button", - label: "Load Tree", + type: 'button', + label: 'Load Tree' }, lottaFaces: { - type: "button", - label: "Load 'lots of faces'", + type: 'button', + label: "Load 'lots of faces'" }, lottaNodes: { - type: "button", - label: "Load 'lots of nodes'", + type: 'button', + label: "Load 'lots of nodes'" }, lottaNodesAndFaces: { - type: "button", - label: "Load 'lots of nodes and faces'", - }, - }, - }, + type: 'button', + label: "Load 'lots of nodes and faces'" + } + } + } } as const; -type SettingsToStore = - T extends { value: infer V } - ? V extends readonly string[] - ? V[number] +type SettingsToStore = T extends { value: infer V } ? V extends readonly string[] ? V[number] : V - : T extends any[] - ? {} - : T extends object - ? { - [K in keyof T as T[K] extends object ? K : never]: - SettingsToStore + : T extends any[] ? {} + : T extends object ? { + [K in keyof T as T[K] extends object ? K : never]: SettingsToStore; } : never; @@ -150,8 +149,8 @@ export function settingsToStore(settings: T): SettingsToStore { const result = {} as any; for (const key in settings) { const value = settings[key]; - if (value && typeof value === "object") { - if ("value" in value) { + if (value && typeof value === 'object') { + if ('value' in value) { result[key] = value.value; } else { result[key] = settingsToStore(value); @@ -162,8 +161,8 @@ export function settingsToStore(settings: T): SettingsToStore { } export let appSettings = localState( - "app-settings", - settingsToStore(AppSettingTypes), + 'app-settings', + settingsToStore(AppSettingTypes) ); $effect.root(() => { @@ -173,7 +172,7 @@ $effect.root(() => { const newClassName = `theme-${theme}`; if (classes) { for (const className of classes) { - if (className.startsWith("theme-") && className !== newClassName) { + if (className.startsWith('theme-') && className !== newClassName) { classes.remove(className); } } diff --git a/app/src/routes/dev/+page.svelte b/app/src/routes/dev/+page.svelte index 0e8ae01..a5b9718 100644 --- a/app/src/routes/dev/+page.svelte +++ b/app/src/routes/dev/+page.svelte @@ -6,9 +6,14 @@ import { type Graph, type NodeInstance } from "@nodarium/types"; import Grid from "$lib/grid"; import { MemoryRuntimeExecutor, type Pointer } from "$lib/runtime"; - import devPlant from "./dev-graph.json"; import { decodeFloat } from "@nodarium/utils"; import { localState } from "$lib/helpers/localState.svelte"; + import * as templates from "$lib/graph-templates"; + import NestedSettings from "$lib/settings/NestedSettings.svelte"; + import { + appSettings, + AppSettingTypes, + } from "$lib/settings/app-settings.svelte"; const nodeRegistry = new RemoteNodeRegistry(""); nodeRegistry.overwriteNode("max/plantarium/output", { @@ -23,29 +28,30 @@ }, }, execute(outputPos: number, args: number[]) { + console.log({ outputPos, args }); return 0; }, }); const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry); - let inputPtrs: Record; + let allPtrs = $state([]); let activeNode = $state(); let isCalculating = $state(false); let windowHeight = $state(500); - let start = $state(0); + const start = localState("nodes.dev.scroll", 0); const rowHeight = 40; const numRows = $derived(Math.floor(windowHeight / rowHeight)); let memory = $state(); - const visibleRows = $derived(memory?.slice(start, start + numRows)); + const visibleRows = $derived( + memory?.slice(start.value, start.value + numRows), + ); - const ptrs = $derived.by(() => { - if (!inputPtrs) return []; + const sortedPtrs = $derived.by(() => { const seen = new Set(); - const ptrs = [...Object.values(inputPtrs)] - .flat() + const _ptrs = [...allPtrs] .sort((a, b) => (a.start > b.start ? 1 : -1)) .filter((ptr) => { const id = `${ptr.start}-${ptr.end}`; @@ -53,12 +59,15 @@ seen.add(id); return true; }); - if (!ptrs) return []; + if (!_ptrs) return []; + return _ptrs; + }); + const ptrs = $derived.by(() => { let out = []; for (let i = 0; i < numRows; i++) { - let rowIndex = start + i; - const activePtr = ptrs.find( + let rowIndex = start.value + i; + const activePtr = sortedPtrs.find( (ptr) => ptr.start < rowIndex && ptr.end >= rowIndex, ); if (activePtr) { @@ -75,7 +84,7 @@ let graph = $state( localStorage.getItem("nodes.dev.graph") ? JSON.parse(localStorage.getItem("nodes.dev.graph")!) - : devPlant, + : templates.defaultPlant, ); function handleSave(g: Graph) { localStorage.setItem("nodes.dev.graph", JSON.stringify(g)); @@ -92,12 +101,16 @@ isCalculating = true; if (res) handleSave(res); try { - await runtimeExecutor.execute(res || graph, graphSettings); + await runtimeExecutor.execute( + res || graph, + $state.snapshot(graphSettings), + ); } catch (e) { console.log(e); } memory = runtimeExecutor.getMemory(); - inputPtrs = runtimeExecutor.inputPtrs; + allPtrs = runtimeExecutor.allPtrs; + clearTimeout(calcTimeout); calcTimeout = setTimeout(() => { isCalculating = false; @@ -120,7 +133,11 @@ {#if visibleRows?.length} { + const scrollTop = e.currentTarget.scrollTop; + start.value = Math.floor(scrollTop / rowHeight); + }} > @@ -133,9 +150,14 @@ - + { + const scrollTop = e.currentTarget.scrollTop; + start.value = Math.floor(scrollTop / rowHeight); + }} + > {#each visibleRows as r, i} - {@const index = i + start} + {@const index = i + start.value} {@const ptr = ptrs[i]} @@ -168,7 +190,7 @@
Float
{index}
+ + + Vec { - let a_val = read_f32(a.0); - vec![encode_float(a_val)] + vec![read_i32(a.0)] } diff --git a/nodes/max/plantarium/output/src/lib.rs b/nodes/max/plantarium/output/src/lib.rs index 9b2f4b3..a0cef75 100644 --- a/nodes/max/plantarium/output/src/lib.rs +++ b/nodes/max/plantarium/output/src/lib.rs @@ -1,5 +1,8 @@ use nodarium_macros::nodarium_definition_file; use nodarium_macros::nodarium_execute; +use nodarium_utils::encode_float; +use nodarium_utils::evaluate_float; +use nodarium_utils::evaluate_vec3; use nodarium_utils::log; use nodarium_utils::read_i32_slice; @@ -7,8 +10,18 @@ nodarium_definition_file!("src/input.json"); #[nodarium_execute] pub fn execute(input: (i32, i32), _res: (i32, i32)) -> Vec { - log!("HERE"); - let mut vecs = read_i32_slice(input); - vecs.push(42); - vecs + let inp = read_i32_slice(input); + let length = inp.len(); + if length == 1 { + let f = evaluate_float(inp.as_slice()); + log!("out.float f={:?}", f); + return vec![encode_float(f)]; + } + if length == 3 { + let f = evaluate_vec3(inp.as_slice()); + log!("out.vec3 x={:?} y={:?} z={:?}", f[0], f[1], f[2]); + return vec![encode_float(f[0]), encode_float(f[1]), encode_float(f[2])]; + } + + return inp; } diff --git a/nodes/max/plantarium/vec3/src/lib.rs b/nodes/max/plantarium/vec3/src/lib.rs index e8bea17..9b0fc44 100644 --- a/nodes/max/plantarium/vec3/src/lib.rs +++ b/nodes/max/plantarium/vec3/src/lib.rs @@ -1,15 +1,17 @@ use nodarium_macros::nodarium_definition_file; use nodarium_macros::nodarium_execute; -use nodarium_utils::concat_arg_vecs; +use nodarium_utils::concat_args; +use nodarium_utils::log; use nodarium_utils::read_i32_slice; nodarium_definition_file!("src/input.json"); #[nodarium_execute] pub fn execute(x: (i32, i32), y: (i32, i32), z: (i32, i32)) -> Vec { - concat_arg_vecs(vec![ - read_i32_slice(x), - read_i32_slice(y), - read_i32_slice(z), + log!("vec3 x: {:?}", x); + concat_args(vec![ + read_i32_slice(x).as_slice(), + read_i32_slice(y).as_slice(), + read_i32_slice(z).as_slice(), ]) } diff --git a/package.json b/package.json index 115c7dc..ab44190 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "build:story": "pnpm -r --filter 'ui' story:build", "build:app": "BASE_PATH=/ui pnpm -r --filter 'ui' build && pnpm -r --filter 'app' build", "build:nodes": "cargo build --workspace --target wasm32-unknown-unknown --release && rm -rf ./app/static/nodes/max/plantarium/ && mkdir -p ./app/static/nodes/max/plantarium/ && cp -R ./target/wasm32-unknown-unknown/release/*.wasm ./app/static/nodes/max/plantarium/", + "build:nodes:debug": "cargo build --workspace --target wasm32-unknown-unknown && rm -rf ./app/static/nodes/max/plantarium/ && mkdir -p ./app/static/nodes/max/plantarium/ && cp -R ./target/wasm32-unknown-unknown/release/*.wasm ./app/static/nodes/max/plantarium/", "build:node": "cargo build --package float --package output --package math --package nodarium_macros --package nodarium_utils --target wasm32-unknown-unknown --release && rm -rf ./app/static/nodes/max/plantarium/ && mkdir -p ./app/static/nodes/max/plantarium/ && cp -R ./target/wasm32-unknown-unknown/release/*.wasm ./app/static/nodes/max/plantarium/", "build:deploy": "pnpm build", "dev:nodes": "chokidar './nodes/**' --initial -i '/pkg/' -c 'pnpm build:nodes'", diff --git a/packages/utils/src/lib.rs b/packages/utils/src/lib.rs index 3fb32f7..912ff2c 100644 --- a/packages/utils/src/lib.rs +++ b/packages/utils/src/lib.rs @@ -11,7 +11,7 @@ extern "C" { pub fn __nodarium_log(ptr: *const u8, len: usize); } -// #[cfg(debug_assertions)] +#[cfg(debug_assertions)] #[macro_export] macro_rules! log { ($($t:tt)*) => {{ @@ -25,13 +25,13 @@ macro_rules! log { }} } -// #[cfg(not(debug_assertions))] -// #[macro_export] -// macro_rules! log { -// ($($arg:tt)*) => {{ -// // This will expand to nothing in release builds -// }}; -// } +#[cfg(not(debug_assertions))] +#[macro_export] +macro_rules! log { + ($($arg:tt)*) => {{ + // This will expand to nothing in release builds + }}; +} #[allow(dead_code)] #[rustfmt::skip]