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 @@
| Float |
-
+ {
+ 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]}
| {index} |
@@ -168,7 +190,7 @@
+
+
+
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]