15 Commits

Author SHA1 Message Date
Niklas Koll
e84c715f4c chore: Add flake and direnv stuff 2026-01-19 12:51:33 +01:00
Max Richter
ecbcc814ed chore: remove store code 2026-01-19 01:29:28 +01:00
Max Richter
be97387252 feat: trying to remove wasm-bindgen 2026-01-19 01:29:12 +01:00
Max Richter
987ece2a4b fix: update performance bars to work with tailwind
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m15s
2026-01-18 18:55:18 +01:00
Max Richter
8d2e3f006b fix: make graph source work 2026-01-18 18:54:53 +01:00
Max Richter
80d3e117b4 feat: update sidebar to svelte-5
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m1s
2026-01-18 18:39:02 +01:00
Max Richter
8a540522dd chore: replace unocss with tailwind
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m4s
2026-01-18 17:11:47 +01:00
Max Richter
a11214072f chore: some updates
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m6s
2026-01-18 16:27:42 +01:00
d068828b68 refactor: rename state.svelte.ts to graph-state.svelte.ts
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 1m59s
2025-12-09 20:00:52 +01:00
3565a18364 feat: cache everything in node store not only wasm 2025-12-05 14:19:29 +01:00
73be4fdd73 feat: better handle node position updates 2025-12-05 14:19:11 +01:00
702c3ee6cf feat: better handle camera positioning 2025-12-05 14:18:56 +01:00
98672eb702 fix: error that changes in active node panel did not get saved 2025-12-05 12:28:30 +01:00
3eafdc50b1 feat: keep benchmark result if panel is hidden 2025-12-05 11:49:10 +01:00
Max Richter
548e445eb7 fix: correctly show hide geometries in geometrypool
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m4s
2025-12-03 22:59:06 +01:00
191 changed files with 5040 additions and 7244 deletions

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ node_modules/
# Added by cargo # Added by cargo
/target /target
.direnv/

367
Cargo.lock generated
View File

@@ -1,176 +1,80 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 4
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]] [[package]]
name = "box" name = "box"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
] ]
[[package]] [[package]]
name = "branch" name = "branch"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"glam",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if",
"wasm-bindgen",
] ]
[[package]] [[package]]
name = "float" name = "float"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
] ]
[[package]] [[package]]
name = "glam" name = "glam"
version = "0.27.0" version = "0.30.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9"
[[package]] [[package]]
name = "gravity" name = "gravity"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"glam", "glam",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"noise", ]
"serde",
"serde-wasm-bindgen", [[package]]
"wasm-bindgen", name = "instance"
"wasm-bindgen-test", version = "0.1.0"
"web-sys", dependencies = [
"glam",
"nodarium_macros",
"nodarium_utils",
] ]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.11" version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]] [[package]]
name = "math" name = "math"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
] ]
[[package]] [[package]]
name = "max-plantarium-triangle" name = "memchr"
version = "0.1.0" version = "2.7.6"
dependencies = [ source = "registry+https://github.com/rust-lang/crates.io-index"
"console_error_panic_hook", checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
"nodarium_macros",
"nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "max-plantarium-vec3"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"nodarium_macros",
"nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "nodarium_instance"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"glam",
"nodarium_macros",
"nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]] [[package]]
name = "nodarium_macros" name = "nodarium_macros"
@@ -180,7 +84,7 @@ dependencies = [
"quote", "quote",
"serde", "serde",
"serde_json", "serde_json",
"syn 1.0.109", "syn",
] ]
[[package]] [[package]]
@@ -195,29 +99,19 @@ dependencies = [
name = "nodarium_utils" name = "nodarium_utils"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"glam", "glam",
"noise", "noise 0.9.0",
"serde", "serde",
"serde_json", "serde_json",
"wasm-bindgen",
"web-sys",
] ]
[[package]] [[package]]
name = "nodes-noise" name = "noise"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"glam",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"noise", "noise 0.9.0",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
] ]
[[package]] [[package]]
@@ -233,48 +127,35 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "output" name = "output"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"glam",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"serde",
"serde_json",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.81" version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.36" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -307,103 +188,76 @@ dependencies = [
name = "random" name = "random"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
] ]
[[package]] [[package]]
name = "rotate" name = "rotate"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"glam", "glam",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"serde", "serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
] ]
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.198" version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde-wasm-bindgen"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.198" version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.60", "syn",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.116" version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "memchr",
"serde", "serde",
"serde_core",
"zmij",
] ]
[[package]] [[package]]
name = "stem" name = "stem"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook",
"nodarium_macros", "nodarium_macros",
"nodarium_utils", "nodarium_utils",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
] ]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "2.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -411,119 +265,30 @@ dependencies = [
] ]
[[package]] [[package]]
name = "syn" name = "triangle"
version = "2.0.60" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [ dependencies = [
"proc-macro2", "nodarium_macros",
"quote", "nodarium_utils",
"unicode-ident",
] ]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]] [[package]]
name = "wasm-bindgen" name = "vec3"
version = "0.2.92" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [ dependencies = [
"cfg-if", "nodarium_macros",
"wasm-bindgen-macro", "nodarium_utils",
"serde",
] ]
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "zmij"
version = "0.2.92" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" checksum = "94f63c051f4fe3c1509da62131a678643c5b6fbdc9273b2b79d4378ebda003d2"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.60",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b"
dependencies = [
"console_error_panic_hook",
"js-sys",
"scoped-tls",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
]
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]]
name = "web-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
]

View File

@@ -13,34 +13,35 @@
"@nodarium/registry": "link:../packages/registry", "@nodarium/registry": "link:../packages/registry",
"@nodarium/ui": "link:../packages/ui", "@nodarium/ui": "link:../packages/ui",
"@nodarium/utils": "link:../packages/utils", "@nodarium/utils": "link:../packages/utils",
"@sveltejs/kit": "^2.49.0", "@sveltejs/kit": "^2.50.0",
"@threlte/core": "8.3.0", "@tailwindcss/vite": "^4.1.18",
"@threlte/extras": "9.7.0", "@threlte/core": "8.3.1",
"@types/three": "^0.181.0", "@threlte/extras": "9.7.1",
"@unocss/reset": "^66.5.9",
"comlink": "^4.4.2", "comlink": "^4.4.2",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"idb": "^8.0.3", "idb": "^8.0.3",
"jsondiffpatch": "^0.7.3", "jsondiffpatch": "^0.7.3",
"three": "^0.181.2" "tailwindcss": "^4.1.18",
"three": "^0.182.0",
"wabt": "^1.0.39"
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/tabler": "^1.2.23", "@iconify-json/tabler": "^1.2.26",
"@iconify/tailwind4": "^1.2.1",
"@nodarium/types": "link:../packages/types", "@nodarium/types": "link:../packages/types",
"@sveltejs/adapter-static": "^3.0.10", "@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/vite-plugin-svelte": "^6.2.1", "@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tsconfig/svelte": "^5.0.6", "@tsconfig/svelte": "^5.0.6",
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
"@unocss/preset-icons": "^66.5.9", "@types/three": "^0.182.0",
"svelte": "^5.43.14", "svelte": "^5.46.4",
"svelte-check": "^4.3.4", "svelte-check": "^4.3.5",
"tslib": "^2.8.1", "tslib": "^2.8.1",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"unocss": "^66.5.9", "vite": "^7.3.1",
"vite": "^7.2.4",
"vite-plugin-comlink": "^5.3.0", "vite-plugin-comlink": "^5.3.0",
"vite-plugin-glsl": "^1.5.4", "vite-plugin-glsl": "^1.5.5",
"vite-plugin-wasm": "^3.5.0", "vite-plugin-wasm": "^3.5.0",
"vitest": "^4.0.13" "vitest": "^4.0.17"
} }
} }

6
app/src/app.css Normal file
View File

@@ -0,0 +1,6 @@
@import "tailwindcss";
@source "../../packages/ui/**/*.svelte";
@plugin "@iconify/tailwind4" {
prefix: "i";
icon-sets: from-folder(custom, "./src/lib/icons")
};

View File

@@ -2,7 +2,7 @@
import { HTML } from "@threlte/extras"; import { HTML } from "@threlte/extras";
import { onMount } from "svelte"; import { onMount } from "svelte";
import type { NodeInstance, NodeId } from "@nodarium/types"; import type { NodeInstance, NodeId } from "@nodarium/types";
import { getGraphManager, getGraphState } from "../graph/state.svelte"; import { getGraphManager, getGraphState } from "../graph-state.svelte";
type Props = { type Props = {
onnode: (n: NodeInstance) => void; onnode: (n: NodeInstance) => void;

View File

@@ -1,7 +1,7 @@
import type { NodeInstance, Socket } from "@nodarium/types"; import type { NodeInstance, Socket } from "@nodarium/types";
import { getContext, setContext } from "svelte"; import { getContext, setContext } from "svelte";
import { SvelteSet } from "svelte/reactivity"; import { SvelteSet } from "svelte/reactivity";
import type { GraphManager } from "../graph-manager.svelte"; import type { GraphManager } from "./graph-manager.svelte";
import type { OrthographicCamera } from "three"; import type { OrthographicCamera } from "three";
@@ -24,7 +24,24 @@ export function setGraphManager(manager: GraphManager) {
export class GraphState { export class GraphState {
constructor(private graph: GraphManager) { } constructor(private graph: GraphManager) {
$effect.root(() => {
$effect(() => {
localStorage.setItem("cameraPosition", `[${this.cameraPosition[0]},${this.cameraPosition[1]},${this.cameraPosition[2]}]`)
})
})
const storedPosition = localStorage.getItem("cameraPosition")
if (storedPosition) {
try {
const d = JSON.parse(storedPosition);
this.cameraPosition[0] = d[0];
this.cameraPosition[1] = d[1];
this.cameraPosition[2] = d[2];
} catch (e) {
console.log("Failed to parsed stored camera position", e);
}
}
}
width = $state(100); width = $state(100);
height = $state(100); height = $state(100);
@@ -80,42 +97,24 @@ export class GraphState {
isBodyFocused = () => document?.activeElement?.nodeName !== "INPUT"; isBodyFocused = () => document?.activeElement?.nodeName !== "INPUT";
setCameraTransform(
x = this.cameraPosition[0],
y = this.cameraPosition[1],
z = this.cameraPosition[2],
) {
if (this.camera) {
this.camera.position.x = x;
this.camera.position.z = y;
this.camera.zoom = z;
}
this.cameraPosition = [x, y, z];
localStorage.setItem("cameraPosition", JSON.stringify(this.cameraPosition));
}
updateNodePosition(node: NodeInstance) { updateNodePosition(node: NodeInstance) {
if (node.state.ref && node.state.mesh) { if (
if (node.state["x"] !== undefined && node.state["y"] !== undefined) { node.state.x === node.position[0] &&
node.state.y === node.position[1]
) {
delete node.state.x;
delete node.state.y;
}
if (node.state["x"] !== undefined && node.state["y"] !== undefined) {
if (node.state.ref) {
node.state.ref.style.setProperty("--nx", `${node.state.x * 10}px`); node.state.ref.style.setProperty("--nx", `${node.state.x * 10}px`);
node.state.ref.style.setProperty("--ny", `${node.state.y * 10}px`); node.state.ref.style.setProperty("--ny", `${node.state.y * 10}px`);
node.state.mesh.position.x = node.state.x + 10; }
node.state.mesh.position.z = node.state.y + this.getNodeHeight(node.type) / 2; } else {
if ( if (node.state.ref) {
node.state.x === node.position[0] &&
node.state.y === node.position[1]
) {
delete node.state.x;
delete node.state.y;
}
this.graph.edges = [...this.graph.edges];
} else {
node.state.ref.style.setProperty("--nx", `${node.position[0] * 10}px`); node.state.ref.style.setProperty("--nx", `${node.position[0] * 10}px`);
node.state.ref.style.setProperty("--ny", `${node.position[1] * 10}px`); node.state.ref.style.setProperty("--ny", `${node.position[1] * 10}px`);
node.state.mesh.position.x = node.position[0] + 10;
node.state.mesh.position.z =
node.position[1] + this.getNodeHeight(node.type) / 2;
} }
} }
} }

View File

@@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { Edge, NodeInstance } from "@nodarium/types"; import type { Edge, NodeInstance } from "@nodarium/types";
import { onMount } from "svelte";
import { createKeyMap } from "../../helpers/createKeyMap"; import { createKeyMap } from "../../helpers/createKeyMap";
import AddMenu from "../components/AddMenu.svelte"; import AddMenu from "../components/AddMenu.svelte";
import Background from "../background/Background.svelte"; import Background from "../background/Background.svelte";
@@ -10,7 +9,7 @@
import Camera from "../components/Camera.svelte"; import Camera from "../components/Camera.svelte";
import { Canvas } from "@threlte/core"; import { Canvas } from "@threlte/core";
import HelpView from "../components/HelpView.svelte"; import HelpView from "../components/HelpView.svelte";
import { getGraphManager, getGraphState } from "./state.svelte"; import { getGraphManager, getGraphState } from "../graph-state.svelte";
import { HTML } from "@threlte/extras"; import { HTML } from "@threlte/extras";
import { FileDropEventManager, MouseEventManager } from "./events"; import { FileDropEventManager, MouseEventManager } from "./events";
import { maxZoom, minZoom } from "./constants"; import { maxZoom, minZoom } from "./constants";
@@ -93,15 +92,6 @@
graphState.activeSocket = null; graphState.activeSocket = null;
graphState.addMenuPosition = null; graphState.addMenuPosition = null;
} }
onMount(() => {
if (localStorage.getItem("cameraPosition")) {
const cPosition = JSON.parse(localStorage.getItem("cameraPosition")!);
if (Array.isArray(cPosition)) {
graphState.setCameraTransform(cPosition[0], cPosition[1], cPosition[2]);
}
}
});
</script> </script>
<svelte:window <svelte:window

View File

@@ -3,7 +3,11 @@
import GraphEl from "./Graph.svelte"; import GraphEl from "./Graph.svelte";
import { GraphManager } from "../graph-manager.svelte"; import { GraphManager } from "../graph-manager.svelte";
import { createKeyMap } from "$lib/helpers/createKeyMap"; import { createKeyMap } from "$lib/helpers/createKeyMap";
import { GraphState, setGraphManager, setGraphState } from "./state.svelte"; import {
GraphState,
setGraphManager,
setGraphState,
} from "../graph-state.svelte";
import { setupKeymaps } from "../keymaps"; import { setupKeymaps } from "../keymaps";
type Props = { type Props = {

View File

@@ -1,6 +1,6 @@
import { GraphSchema, type NodeId, type NodeInstance } from "@nodarium/types"; import { GraphSchema, type NodeId, type NodeInstance } from "@nodarium/types";
import type { GraphManager } from "../graph-manager.svelte"; import type { GraphManager } from "../graph-manager.svelte";
import type { GraphState } from "./state.svelte"; import type { GraphState } from "../graph-state.svelte";
import { animate, lerp } from "$lib/helpers"; import { animate, lerp } from "$lib/helpers";
import { snapToGrid as snapPointToGrid } from "../helpers"; import { snapToGrid as snapPointToGrid } from "../helpers";
import { maxZoom, minZoom, zoomSpeed } from "./constants"; import { maxZoom, minZoom, zoomSpeed } from "./constants";
@@ -455,7 +455,8 @@ export class MouseEventManager {
this.state.cameraDown[1] - this.state.cameraDown[1] -
(my - this.state.mouseDown[1]) / this.state.cameraPosition[2]; (my - this.state.mouseDown[1]) / this.state.cameraPosition[2];
this.state.setCameraTransform(newX, newY); this.state.cameraPosition[0] = newX;
this.state.cameraPosition[1] = newY;
} }
@@ -486,15 +487,13 @@ export class MouseEventManager {
const zoomRatio = newZoom / this.state.cameraPosition[2]; const zoomRatio = newZoom / this.state.cameraPosition[2];
// Update camera position and zoom level // Update camera position and zoom level
this.state.setCameraTransform( this.state.cameraPosition[0] = this.state.mousePosition[0] -
this.state.mousePosition[0] -
(this.state.mousePosition[0] - this.state.cameraPosition[0]) / (this.state.mousePosition[0] - this.state.cameraPosition[0]) /
zoomRatio, zoomRatio;
this.state.mousePosition[1] - this.state.cameraPosition[1] = this.state.mousePosition[1] -
(this.state.mousePosition[1] - this.state.cameraPosition[1]) / (this.state.mousePosition[1] - this.state.cameraPosition[1]) /
zoomRatio, zoomRatio,
newZoom, this.state.cameraPosition[2] = newZoom;
);
} }
} }

View File

@@ -2,7 +2,7 @@ import { animate, lerp } from "$lib/helpers";
import type { createKeyMap } from "$lib/helpers/createKeyMap"; import type { createKeyMap } from "$lib/helpers/createKeyMap";
import FileSaver from "file-saver"; import FileSaver from "file-saver";
import type { GraphManager } from "./graph-manager.svelte"; import type { GraphManager } from "./graph-manager.svelte";
import type { GraphState } from "./graph/state.svelte"; import type { GraphState } from "./graph-state.svelte";
type Keymap = ReturnType<typeof createKeyMap>; type Keymap = ReturnType<typeof createKeyMap>;
export function setupKeymaps(keymap: Keymap, graph: GraphManager, graphState: GraphState) { export function setupKeymaps(keymap: Keymap, graph: GraphManager, graphState: GraphState) {
@@ -88,11 +88,9 @@ export function setupKeymaps(keymap: Keymap, graph: GraphManager, graphState: Gr
const ease = (t: number) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t); const ease = (t: number) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t);
animate(500, (a: number) => { animate(500, (a: number) => {
graphState.setCameraTransform( graphState.cameraPosition[0] = lerp(camX, average[0], ease(a));
lerp(camX, average[0], ease(a)), graphState.cameraPosition[1] = lerp(camY, average[1], ease(a));
lerp(camY, average[1], ease(a)), graphState.cameraPosition[2] = lerp(camZ, 2, ease(a))
lerp(camZ, 2, ease(a)),
);
if (graphState.mouseDown) return false; if (graphState.mouseDown) return false;
}); });
}, },

View File

@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { NodeInstance } from "@nodarium/types"; import type { NodeInstance } from "@nodarium/types";
import { getGraphState } from "../graph/state.svelte"; import { getGraphState } from "../graph-state.svelte";
import { T } from "@threlte/core"; import { T } from "@threlte/core";
import { type Mesh } from "three"; import { type Mesh } from "three";
import NodeFrag from "./Node.frag"; import NodeFrag from "./Node.frag";
@@ -16,7 +16,7 @@
inView: boolean; inView: boolean;
z: number; z: number;
}; };
let { node, inView, z }: Props = $props(); let { node = $bindable(), inView, z }: Props = $props();
const isActive = $derived(graphState.activeNodeId === node.id); const isActive = $derived(graphState.activeNodeId === node.id);
const isSelected = $derived(graphState.selectedNodes.has(node.id)); const isSelected = $derived(graphState.selectedNodes.has(node.id));
@@ -42,8 +42,8 @@
</script> </script>
<T.Mesh <T.Mesh
position.x={node.position[0] + 10} position.x={(node.state.x ?? node.position[0]) + 10}
position.z={node.position[1] + height / 2} position.z={(node.state.y ?? node.position[1]) + height / 2}
position.y={0.8} position.y={0.8}
rotation.x={-Math.PI / 2} rotation.x={-Math.PI / 2}
bind:ref={meshRef} bind:ref={meshRef}
@@ -67,4 +67,4 @@
/> />
</T.Mesh> </T.Mesh>
<NodeHtml {node} {inView} {isActive} {isSelected} {z} /> <NodeHtml bind:node {inView} {isActive} {isSelected} {z} />

View File

@@ -1,15 +1,15 @@
<script lang="ts"> <script lang="ts">
import type { NodeInstance, SerializedNode } from "@nodarium/types"; import type { NodeInstance } from "@nodarium/types";
import NodeHeader from "./NodeHeader.svelte"; import NodeHeader from "./NodeHeader.svelte";
import NodeParameter from "./NodeParameter.svelte"; import NodeParameter from "./NodeParameter.svelte";
import { getGraphState } from "../graph/state.svelte"; import { getGraphState } from "../graph-state.svelte";
let ref: HTMLDivElement; let ref: HTMLDivElement;
const graphState = getGraphState(); const graphState = getGraphState();
type Props = { type Props = {
node: SerializedNode | NodeInstance; node: NodeInstance;
position?: "absolute" | "fixed" | "relative"; position?: "absolute" | "fixed" | "relative";
isActive?: boolean; isActive?: boolean;
isSelected?: boolean; isSelected?: boolean;
@@ -30,15 +30,10 @@
const zOffset = Math.random() - 0.5; const zOffset = Math.random() - 0.5;
const zLimit = 2 - zOffset; const zLimit = 2 - zOffset;
const parameters = const parameters = Object.entries(node.state?.type?.inputs || {}).filter(
"state" in node (p) =>
? Object.entries(node.state?.type?.inputs || {}).filter( p[1].type !== "seed" && !("setting" in p[1]) && p[1]?.hidden !== true,
(p) => );
p[1].type !== "seed" &&
!("setting" in p[1]) &&
p[1]?.hidden !== true,
)
: [];
$effect(() => { $effect(() => {
if ("state" in node && !node.state.ref) { if ("state" in node && !node.state.ref) {

View File

@@ -1,11 +1,11 @@
<script lang="ts"> <script lang="ts">
import { getGraphState } from "../graph/state.svelte.js"; import { getGraphState } from "../graph-state.svelte";
import { createNodePath } from "../helpers/index.js"; import { createNodePath } from "../helpers/index.js";
import type { NodeInstance, SerializedNode } from "@nodarium/types"; import type { NodeInstance } from "@nodarium/types";
const graphState = getGraphState(); const graphState = getGraphState();
const { node }: { node: NodeInstance | SerializedNode } = $props(); const { node }: { node: NodeInstance } = $props();
function handleMouseDown(event: MouseEvent) { function handleMouseDown(event: MouseEvent) {
event.stopPropagation(); event.stopPropagation();
@@ -20,8 +20,7 @@
} }
const cornerTop = 10; const cornerTop = 10;
const rightBump = const rightBump = !!node?.state?.type?.outputs?.length;
"state" in node ? !!node?.state?.type?.outputs?.length : false;
const aspectRatio = 0.25; const aspectRatio = 0.25;
const path = createNodePath({ const path = createNodePath({

View File

@@ -1,16 +1,12 @@
<script lang="ts"> <script lang="ts">
import type { import type { NodeInput, NodeInstance } from "@nodarium/types";
NodeInput as NodeInputType, import { createNodePath } from "../helpers";
NodeInstance, import NodeInputEl from "./NodeInput.svelte";
SerializedNode, import { getGraphManager, getGraphState } from "../graph-state.svelte";
} from "@nodarium/types";
import { createNodePath } from "../helpers/index.js";
import NodeInput from "./NodeInput.svelte";
import { getGraphManager, getGraphState } from "../graph/state.svelte.js";
type Props = { type Props = {
node: NodeInstance | SerializedNode; node: NodeInstance;
input: NodeInputType; input: NodeInput;
id: string; id: string;
isLast?: boolean; isLast?: boolean;
}; };
@@ -80,7 +76,7 @@
<label for={elementId}>{input.label || id}</label> <label for={elementId}>{input.label || id}</label>
{/if} {/if}
{#if inputType.external !== true} {#if inputType.external !== true}
<NodeInput {graph} {elementId} bind:node {input} {id} /> <NodeInputEl {graph} {elementId} bind:node {input} {id} />
{/if} {/if}
</div> </div>

View File

@@ -1,12 +1,16 @@
<script lang="ts"> <script lang="ts">
import { getContext } from "svelte"; import { getContext, type Snippet } from "svelte";
let index = -1; let index = $state(-1);
let wrapper: HTMLDivElement; let wrapper: HTMLDivElement;
$: if (index === -1) { const { children } = $props<{ children?: Snippet }>();
index = getContext<() => number>("registerCell")();
} $effect(() => {
if (index === -1) {
index = getContext<() => number>("registerCell")();
}
});
const sizes = getContext<{ value: string[] }>("sizes"); const sizes = getContext<{ value: string[] }>("sizes");
@@ -31,8 +35,8 @@
</script> </script>
<svelte:window <svelte:window
on:mouseup={() => (mouseDown = false)} onmouseup={() => (mouseDown = false)}
on:mousemove={handleMouseMove} onmousemove={handleMouseMove}
/> />
{#if index > 0} {#if index > 0}
@@ -40,12 +44,12 @@
class="seperator" class="seperator"
role="button" role="button"
tabindex="0" tabindex="0"
on:mousedown={handleMouseDown} onmousedown={handleMouseDown}
></div> ></div>
{/if} {/if}
<div class="cell" bind:this={wrapper}> <div class="cell" bind:this={wrapper}>
<slot /> {@render children?.()}
</div> </div>
<style> <style>

View File

@@ -1,9 +1,9 @@
<script lang="ts"> <script lang="ts">
import { setContext } from "svelte"; import { setContext, type Snippet } from "svelte";
export let id = "grid-0"; const { children, id } = $props<{ children?: Snippet; id?: string }>();
setContext("grid-id", id); setContext("grid-id", id);
</script> </script>
<slot {id} /> {@render children({ id })}

View File

@@ -126,7 +126,7 @@ export function humanizeDuration(durationInMilliseconds: number) {
} }
if (millis > 0 || durationString === '') { if (millis > 0 || durationString === '') {
durationString += millis + 'ms'; durationString += Math.floor(millis) + 'ms';
} }
return durationString.trim(); return durationString.trim();

View File

@@ -1,4 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="17" y="8" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/> <rect x="17" y="8" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>
<rect x="2" y="3" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/> <rect x="2" y="3" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>
<rect x="2" y="14" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/> <rect x="2" y="14" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>

Before

Width:  |  Height:  |  Size: 519 B

After

Width:  |  Height:  |  Size: 496 B

View File

@@ -3,7 +3,7 @@ import fs from "fs/promises";
import path from "path"; import path from "path";
export async function getWasm(id: `${string}/${string}/${string}`) { export async function getWasm(id: `${string}/${string}/${string}`) {
const filePath = path.resolve(`../nodes/${id}/pkg/index_bg.wasm`); const filePath = path.resolve(`../nodes/${id}/pkg/node.wasm`);
try { try {
await fs.access(filePath); await fs.access(filePath);

View File

@@ -1,10 +1,11 @@
<script lang="ts"> <script lang="ts">
import { Select } from "@nodarium/ui"; import { Select } from "@nodarium/ui";
import type { Writable } from "svelte/store";
let activeStore = 0; let activeStore = $state(0);
export let activeId: Writable<string>; let { activeId }: { activeId: string } = $props();
$: [activeUser, activeCollection, activeNode] = $activeId.split(`/`); const [activeUser, activeCollection, activeNode] = $derived(
activeId.split(`/`),
);
</script> </script>
<div class="breadcrumbs"> <div class="breadcrumbs">
@@ -12,16 +13,16 @@
<Select id="root" options={["root"]} bind:value={activeStore}></Select> <Select id="root" options={["root"]} bind:value={activeStore}></Select>
{#if activeCollection} {#if activeCollection}
<button <button
on:click={() => { onclick={() => {
$activeId = activeUser; activeId = activeUser;
}} }}
> >
{activeUser} {activeUser}
</button> </button>
{#if activeNode} {#if activeNode}
<button <button
on:click={() => { onclick={() => {
$activeId = `${activeUser}/${activeCollection}`; activeId = `${activeUser}/${activeCollection}`;
}} }}
> >
{activeCollection} {activeCollection}

View File

@@ -1,17 +1,17 @@
<script lang="ts"> <script lang="ts">
import NodeHtml from "$lib/graph-interface/node/NodeHTML.svelte"; import NodeHtml from "$lib/graph-interface/node/NodeHTML.svelte";
import type { SerializedNode } from "@nodarium/types"; import type { NodeDefinition, NodeId, NodeInstance } from "@nodarium/types";
const { node }: { node: SerializedNode } = $props(); const { node }: { node: NodeDefinition } = $props();
let dragging = $state(false); let dragging = $state(false);
let nodeData = $state({ let nodeData = $state<NodeInstance>({
id: 0, id: 0,
type: node?.id, type: node.id as unknown as NodeId,
position: [0, 0] as [number, number], position: [0, 0] as [number, number],
props: {}, props: {},
tmp: { state: {
type: node, type: node,
}, },
}); });
@@ -46,7 +46,7 @@
tabindex="0" tabindex="0"
ondragstart={handleDragStart} ondragstart={handleDragStart}
> >
<NodeHtml inView={true} position={"relative"} z={5} bind:node={nodeData} /> <NodeHtml bind:node={nodeData} inView={true} position={"relative"} z={5} />
</div> </div>
</div> </div>

View File

@@ -1,19 +1,16 @@
<script lang="ts"> <script lang="ts">
import { writable } from "svelte/store";
import BreadCrumbs from "./BreadCrumbs.svelte"; import BreadCrumbs from "./BreadCrumbs.svelte";
import DraggableNode from "./DraggableNode.svelte"; import DraggableNode from "./DraggableNode.svelte";
import type { RemoteNodeRegistry } from "@nodarium/registry"; import type { RemoteNodeRegistry } from "@nodarium/registry";
export let registry: RemoteNodeRegistry; const { registry }: { registry: RemoteNodeRegistry } = $props();
const activeId = writable("max/plantarium"); let activeId = $state("max/plantarium");
let showBreadCrumbs = false; let showBreadCrumbs = false;
// const activeId = localStore< const [activeUser, activeCollection, activeNode] = $derived(
// `${string}` | `${string}/${string}` | `${string}/${string}/${string}` activeId.split(`/`),
// >("nodes.store.activeId", ""); );
$: [activeUser, activeCollection, activeNode] = $activeId.split(`/`);
</script> </script>
{#if showBreadCrumbs} {#if showBreadCrumbs}
@@ -27,8 +24,8 @@
{:then users} {:then users}
{#each users as user} {#each users as user}
<button <button
on:click={() => { onclick={() => {
$activeId = user.id; activeId = user.id;
}}>{user.id}</button }}>{user.id}</button
> >
{/each} {/each}
@@ -41,8 +38,8 @@
{:then user} {:then user}
{#each user.collections as collection} {#each user.collections as collection}
<button <button
on:click={() => { onclick={() => {
$activeId = collection.id; activeId = collection.id;
}} }}
> >
{collection.id.split(`/`)[1]} {collection.id.split(`/`)[1]}

View File

@@ -1,8 +1,12 @@
<script lang="ts"> <script lang="ts">
export let labels: string[] = []; type Props = {
export let values: number[] = []; labels: string[];
values: number[];
};
$: total = values.reduce((acc, v) => acc + v, 0); const { labels, values }: Props = $props();
const total = $derived(values.reduce((acc, v) => acc + v, 0));
let colors = ["red", "green", "blue"]; let colors = ["red", "green", "blue"];
</script> </script>
@@ -10,7 +14,10 @@
<div class="wrapper"> <div class="wrapper">
<div class="bars"> <div class="bars">
{#each values as value, i} {#each values as value, i}
<div class="bar bg-{colors[i]}" style="width: {(value / total) * 100}%;"> <div
class="bar bg-{colors[i]}-400"
style="width: {(value / total) * 100}%;"
>
{Math.round(value)}ms {Math.round(value)}ms
</div> </div>
{/each} {/each}
@@ -18,12 +25,11 @@
<div class="labels mt-2"> <div class="labels mt-2">
{#each values as _label, i} {#each values as _label, i}
<div class="text-{colors[i]}">{labels[i]}</div> <div class="text-{colors[i]}-400">{labels[i]}</div>
{/each} {/each}
</div> </div>
<span <span
class="bg-red bg-green bg-yellow bg-blue text-red text-green text-yellow text-blue" class="bg-red-400 bg-green-400 bg-blue-400 text-red-400 text-green-400 text-blue-400"
></span> ></span>
</div> </div>

View File

@@ -1,52 +1,59 @@
<script lang="ts"> <script lang="ts">
export let points: number[]; type Props = {
points: number[];
type?: string;
title?: string;
max?: number;
min?: number;
};
export let type = "ms"; let {
export let title = "Performance"; points,
export let max: number | undefined = undefined; type = "ms",
export let min: number | undefined = undefined; title = "Performance",
max,
min,
}: Props = $props();
function getMax(m?: number) { let internalMax = $derived(max ?? Math.max(...points));
let internalMin = $derived(min ?? Math.min(...points))!;
const maxText = $derived.by(() => {
if (type === "%") { if (type === "%") {
return 100; return 100;
} }
if (m !== undefined) { if (internalMax !== undefined) {
if (m < 1) { if (internalMax < 1) {
return Math.floor(m * 100) / 100; return Math.floor(internalMax * 100) / 100;
} }
if (m < 10) { if (internalMax < 10) {
return Math.floor(m * 10) / 10; return Math.floor(internalMax * 10) / 10;
} }
return Math.floor(m); return Math.floor(internalMax);
} }
return 1; return 1;
} });
function constructPath() { const path = $derived(
max = max !== undefined ? max : Math.max(...points); points
min = min !== undefined ? min : Math.min(...points);
const mi = min as number;
const ma = max as number;
return points
.map((point, i) => { .map((point, i) => {
const x = (i / (points.length - 1)) * 100; const x = (i / (points.length - 1)) * 100;
const y = 100 - ((point - mi) / (ma - mi)) * 100; const y =
100 - ((point - internalMin) / (internalMax - internalMin)) * 100;
return `${x},${y}`; return `${x},${y}`;
}) })
.join(" "); .join(" "),
} );
</script> </script>
<div class="wrapper"> <div class="wrapper">
<p>{title}</p> <p>{title}</p>
<span class="min">{Math.floor(min || 0)}{type}</span> <span class="min">{Math.floor(internalMin || 0)}{type}</span>
<span class="max">{getMax(max)}{type}</span> <span class="max">{maxText}{type}</span>
<svg preserveAspectRatio="none" viewBox="0 0 100 100"> <svg preserveAspectRatio="none" viewBox="0 0 100 100">
{#key points} <polyline vector-effect="non-scaling-stroke" points={path} />
<polyline vector-effect="non-scaling-stroke" points={constructPath()} />
{/key}
</svg> </svg>
</div> </div>

View File

@@ -2,23 +2,13 @@
import Monitor from "./Monitor.svelte"; import Monitor from "./Monitor.svelte";
import { humanizeNumber } from "$lib/helpers"; import { humanizeNumber } from "$lib/helpers";
import { Checkbox } from "@nodarium/ui"; import { Checkbox } from "@nodarium/ui";
import localStore from "$lib/helpers/localStore"; import type { PerformanceData } from "@nodarium/utils";
import { type PerformanceData } from "@nodarium/utils";
import BarSplit from "./BarSplit.svelte"; import BarSplit from "./BarSplit.svelte";
export let data: PerformanceData; const { data }: { data: PerformanceData } = $props();
let activeType = localStore<string>("nodes.performance.active-type", "total"); let activeType = $state("total");
let showAverage = true; let showAverage = $state(true);
function getAverage(key: string) {
return (
data
.map((run) => run[key]?.[0])
.filter((v) => v !== undefined)
.reduce((acc, run) => acc + run, 0) / data.length
);
}
function round(v: number) { function round(v: number) {
if (v < 1) { if (v < 1) {
@@ -30,45 +20,15 @@
return Math.floor(v); return Math.floor(v);
} }
function getAverages() { function getTitle(t: string) {
let lastRun = data.at(-1); if (t.includes("/")) {
if (!lastRun) return {}; return `Node ${t.split("/").slice(-1).join("/")}`;
return Object.keys(lastRun).reduce(
(acc, key) => {
acc[key] = getAverage(key);
return acc;
},
{} as Record<string, number>,
);
}
function getLast(key: string) {
return data.at(-1)?.[key]?.[0] || 0;
}
function getLasts() {
return data.at(-1) || {};
}
function getTotalPerformance(onlyLast = false) {
if (onlyLast) {
return (
getLast("runtime") +
getLast("update-geometries") +
getLast("worker-transfer")
);
} }
return (
getAverage("runtime") +
getAverage("update-geometries") +
getAverage("worker-transfer")
);
}
function getCacheRatio(onlyLast = false) { return t
let ratio = onlyLast ? getLast("cache-hit") : getAverage("cache-hit"); .split("-")
.map((v) => v[0].toUpperCase() + v.slice(1))
return Math.floor(ratio * 100); .join(" ");
} }
const viewerKeys = [ const viewerKeys = [
@@ -78,10 +38,53 @@
"split-result", "split-result",
]; ];
function getPerformanceData(onlyLast: boolean = false) { // --- Small helpers that query `data` directly ---
let data = onlyLast ? getLasts() : getAverages(); function getAverage(key: string) {
const vals = data
.map((run) => run[key]?.[0])
.filter((v) => v !== undefined) as number[];
return Object.entries(data) if (vals.length === 0) return 0;
return vals.reduce((acc, v) => acc + v, 0) / vals.length;
}
function getLast(key: string) {
return data.at(-1)?.[key]?.[0] || 0;
}
const averages = $derived.by(() => {
const lr = data.at(-1);
if (!lr) return {} as Record<string, number>;
return Object.keys(lr).reduce((acc: Record<string, number>, key) => {
acc[key] = getAverage(key);
return acc;
}, {});
});
const lasts = $derived.by(() => data.at(-1) || {});
const totalPerformance = $derived.by(() => {
const onlyLast =
getLast("runtime") +
getLast("update-geometries") +
getLast("worker-transfer");
const average =
getAverage("runtime") +
getAverage("update-geometries") +
getAverage("worker-transfer");
return { onlyLast, average };
});
const cacheRatio = $derived.by(() => {
return {
onlyLast: Math.floor(getLast("cache-hit") * 100),
average: Math.floor(getAverage("cache-hit") * 100),
};
});
const performanceData = $derived.by(() => {
const source = showAverage ? averages : lasts;
return Object.entries(source)
.filter( .filter(
([key]) => ([key]) =>
!key.startsWith("node/") && !key.startsWith("node/") &&
@@ -90,19 +93,18 @@
!viewerKeys.includes(key), !viewerKeys.includes(key),
) )
.sort((a, b) => b[1] - a[1]); .sort((a, b) => b[1] - a[1]);
} });
function getNodePerformanceData(onlyLast: boolean = false) { const nodePerformanceData = $derived.by(() => {
let data = onlyLast ? getLasts() : getAverages(); const source = showAverage ? averages : lasts;
return Object.entries(source)
return Object.entries(data)
.filter(([key]) => key.startsWith("node/")) .filter(([key]) => key.startsWith("node/"))
.sort((a, b) => b[1] - a[1]); .sort((a, b) => b[1] - a[1]);
} });
function getViewerPerformanceData(onlyLast: boolean = false) { const viewerPerformanceData = $derived.by(() => {
let data = onlyLast ? getLasts() : getAverages(); const source = showAverage ? averages : lasts;
return Object.entries(data) return Object.entries(source)
.filter( .filter(
([key]) => ([key]) =>
key !== "total-vertices" && key !== "total-vertices" &&
@@ -110,14 +112,29 @@
viewerKeys.includes(key), viewerKeys.includes(key),
) )
.sort((a, b) => b[1] - a[1]); .sort((a, b) => b[1] - a[1]);
} });
function getTotalPoints() { const splitValues = $derived.by(() => {
if (showAverage) {
return [
getAverage("worker-transfer"),
getAverage("runtime"),
getAverage("update-geometries"),
];
}
return [
getLast("worker-transfer"),
getLast("runtime"),
getLast("update-geometries"),
];
});
const totalPoints = $derived.by(() => {
if (showAverage) { if (showAverage) {
return data.map((run) => { return data.map((run) => {
return ( return (
run["runtime"].reduce((acc, v) => acc + v, 0) + (run["runtime"]?.reduce((acc, v) => acc + v, 0) || 0) +
run["update-geometries"].reduce((acc, v) => acc + v, 0) + (run["update-geometries"]?.reduce((acc, v) => acc + v, 0) || 0) +
(run["worker-transfer"]?.reduce((acc, v) => acc + v, 0) || 0) (run["worker-transfer"]?.reduce((acc, v) => acc + v, 0) || 0)
); );
}); });
@@ -125,16 +142,16 @@
return data.map((run) => { return data.map((run) => {
return ( return (
run["runtime"][0] + (run["runtime"]?.[0] || 0) +
run["update-geometries"][0] + (run["update-geometries"]?.[0] || 0) +
(run["worker-transfer"]?.[0] || 0) (run["worker-transfer"]?.[0] || 0)
); );
}); });
} });
function constructPoints(key: string) { function constructPoints(key: string) {
if (key === "total") { if (key === "total") {
return getTotalPoints(); return totalPoints;
} }
return data.map((run) => { return data.map((run) => {
if (key in run) { if (key in run) {
@@ -148,47 +165,33 @@
}); });
} }
function getSplitValues(): number[] { const computedTotalDisplay = $derived.by(() =>
if (showAverage) { round(showAverage ? totalPerformance.average : totalPerformance.onlyLast),
return [ );
getAverage("worker-transfer"),
getAverage("runtime"),
getAverage("update-geometries"),
];
}
return [ const computedFps = $derived.by(() =>
getLast("worker-transfer"), Math.floor(
getLast("runtime"), 1000 /
getLast("update-geometries"), (showAverage
]; ? totalPerformance.average || 1
} : totalPerformance.onlyLast || 1),
),
function getTitle(t: string) { );
if (t.includes("/")) {
return `Node ${t.split("/").slice(-1).join("/")}`;
}
return t
.split("-")
.map((v) => v[0].toUpperCase() + v.slice(1))
.join(" ");
}
</script> </script>
{#key $activeType && data} {#if data.length !== 0}
{#if $activeType === "cache-hit"} {#if activeType === "cache-hit"}
<Monitor <Monitor
title="Cache Hits" title="Cache Hits"
points={constructPoints($activeType)} points={constructPoints(activeType)}
min={0} min={0}
max={1} max={1}
type="%" type="%"
/> />
{:else} {:else}
<Monitor <Monitor
title={getTitle($activeType)} title={getTitle(activeType)}
points={constructPoints($activeType)} points={constructPoints(activeType)}
/> />
{/if} {/if}
@@ -198,116 +201,108 @@
<label for="show-total">Show Average</label> <label for="show-total">Show Average</label>
</div> </div>
{#if data.length !== 0} <BarSplit
<BarSplit labels={["worker-transfer", "runtime", "update-geometries"]}
labels={["worker-transfer", "runtime", "update-geometries"]} values={splitValues}
values={getSplitValues()} />
/>
<h3>General</h3> <h3>General</h3>
<table> <table>
<tbody> <tbody>
<tr>
<td>
{computedTotalDisplay}<span>ms</span>
</td>
<td
class:active={activeType === "total"}
onclick={() => (activeType = "total")}
>
total<span>({computedFps}fps)</span>
</td>
</tr>
{#each performanceData as [key, value]}
<tr> <tr>
<td> <td>{round(value)}<span>ms</span></td>
{round(getTotalPerformance(!showAverage))}<span>ms</span>
</td>
<td <td
class:active={$activeType === "total"} class:active={activeType === key}
on:click={() => ($activeType = "total")} onclick={() => (activeType = key)}
> >
total<span {key}
>({Math.floor(
1000 / getTotalPerformance(showAverage),
)}fps)</span
>
</td> </td>
</tr> </tr>
{#each getPerformanceData(!showAverage) as [key, value]} {/each}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key}
</td>
</tr>
{/each}
<tr>
<td>{data.length}</td>
<td>Samples</td>
</tr>
</tbody>
<tbody>
<tr><td><h3>Nodes</h3></td></tr>
</tbody>
<tbody>
<tr>
<td
>{showAverage ? cacheRatio.average : cacheRatio.onlyLast}<span
>%</span
></td
>
<td
class:active={activeType === "cache-hit"}
onclick={() => (activeType = "cache-hit")}
>
cache hits
</td>
</tr>
{#each nodePerformanceData as [key, value]}
<tr> <tr>
<td>{data.length}</td> <td>{round(value)}<span>ms</span></td>
<td>Samples</td>
</tr>
</tbody>
<tbody>
<tr>
<td>
<h3>Nodes</h3>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td> {getCacheRatio(!showAverage)}<span>%</span> </td>
<td <td
class:active={$activeType === "cache-hit"} class:active={activeType === key}
on:click={() => ($activeType = "cache-hit")}>cache hits</td onclick={() => (activeType = key)}
> >
</tr> {key.split("/").slice(-1).join("/")}
{#each getNodePerformanceData(!showAverage) as [key, value]}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key.split("/").slice(-1).join("/")}
</td>
</tr>
{/each}
</tbody>
<tbody>
<tr>
<td>
<h3>Viewer</h3>
</td> </td>
</tr> </tr>
</tbody> {/each}
<tbody> </tbody>
<tbody>
<tr><td><h3>Viewer</h3></td></tr>
</tbody>
<tbody>
<tr>
<td>{humanizeNumber(getLast("total-vertices"))}</td>
<td>Vertices</td>
</tr>
<tr>
<td>{humanizeNumber(getLast("total-faces"))}</td>
<td>Faces</td>
</tr>
{#each viewerPerformanceData as [key, value]}
<tr> <tr>
<td>{humanizeNumber(getLast("total-vertices"))}</td> <td>{round(value)}<span>ms</span></td>
<td>Vertices</td> <td
class:active={activeType === key}
onclick={() => (activeType = key)}
>
{key.split("/").slice(-1).join("/")}
</td>
</tr> </tr>
<tr> {/each}
<td>{humanizeNumber(getLast("total-faces"))}</td> </tbody>
<td>Faces</td> </table>
</tr>
{#each getViewerPerformanceData(!showAverage) as [key, value]}
<tr>
<td>
{round(value)}<span>ms</span>
</td>
<td
class:active={$activeType === key}
on:click={() => ($activeType = key)}
>
{key.split("/").slice(-1).join("/")}
</td>
</tr>
{/each}
</tbody>
</table>
{:else}
<p>No runs available</p>
{/if}
</div> </div>
{/key} {:else}
<p>No runs available</p>
{/if}
<style> <style>
h3 { h3 {

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
export let points: number[]; const { points }: { points: number[] } = $props();
function constructPath() { const path = $derived.by(() => {
const max = Math.max(...points); const max = Math.max(...points);
const min = Math.min(...points); const min = Math.min(...points);
return points return points
@@ -11,13 +11,11 @@
return `${x},${y}`; return `${x},${y}`;
}) })
.join(" "); .join(" ");
} });
</script> </script>
<svg preserveAspectRatio="none" viewBox="0 0 100 100"> <svg preserveAspectRatio="none" viewBox="0 0 100 100">
{#key points} <polyline vector-effect="non-scaling-stroke" points={path} />
<polyline vector-effect="non-scaling-stroke" points={constructPath()} />
{/key}
</svg> </svg>
<style> <style>

View File

@@ -1,25 +1,23 @@
<script lang="ts"> <script lang="ts">
import { humanizeDuration, humanizeNumber } from "$lib/helpers"; import { humanizeDuration, humanizeNumber } from "$lib/helpers";
import localStore from "$lib/helpers/localStore"; import { localState } from "$lib/helpers/localState.svelte";
import SmallGraph from "./SmallGraph.svelte"; import SmallGraph from "./SmallGraph.svelte";
import type { PerformanceData, PerformanceStore } from "@nodarium/utils"; import type { PerformanceData, PerformanceStore } from "@nodarium/utils";
export let store: PerformanceStore; const { store, fps }: { store: PerformanceStore; fps: number[] } = $props();
const open = localStore("node.performance.small.open", { const open = localState("node.performance.small.open", {
runtime: false, runtime: false,
fps: false, fps: false,
}); });
$: vertices = $store?.at(-1)?.["total-vertices"]?.[0] || 0; const vertices = $derived($store?.at(-1)?.["total-vertices"]?.[0] || 0);
$: faces = $store?.at(-1)?.["total-faces"]?.[0] || 0; const faces = $derived($store?.at(-1)?.["total-faces"]?.[0] || 0);
$: runtime = $store?.at(-1)?.["runtime"]?.[0] || 0; const runtime = $derived($store?.at(-1)?.["runtime"]?.[0] || 0);
function getPoints(data: PerformanceData, key: string) { function getPoints(data: PerformanceData, key: string) {
return data?.map((run) => run[key]?.[0] || 0) || []; return data?.map((run) => run[key]?.[0] || 0) || [];
} }
export let fps: number[] = [];
</script> </script>
<div class="wrapper"> <div class="wrapper">
@@ -27,12 +25,12 @@
<tbody> <tbody>
<tr <tr
style="cursor:pointer;" style="cursor:pointer;"
on:click={() => ($open.runtime = !$open.runtime)} onclick={() => (open.value.runtime = !open.value.runtime)}
> >
<td>{$open.runtime ? "-" : "+"} runtime </td> <td>{open.value.runtime ? "-" : "+"} runtime </td>
<td>{humanizeDuration(runtime || 1000)}</td> <td>{humanizeDuration(runtime || 1000)}</td>
</tr> </tr>
{#if $open.runtime} {#if open.value.runtime}
<tr> <tr>
<td colspan="2"> <td colspan="2">
<SmallGraph points={getPoints($store, "runtime")} /> <SmallGraph points={getPoints($store, "runtime")} />
@@ -40,13 +38,16 @@
</tr> </tr>
{/if} {/if}
<tr style="cursor:pointer;" on:click={() => ($open.fps = !$open.fps)}> <tr
<td>{$open.fps ? "-" : "+"} fps </td> style="cursor:pointer;"
onclick={() => (open.value.fps = !open.value.fps)}
>
<td>{open.value.fps ? "-" : "+"} fps </td>
<td> <td>
{Math.floor(fps[fps.length - 1])}fps {Math.floor(fps[fps.length - 1])}fps
</td> </td>
</tr> </tr>
{#if $open.fps} {#if open.value.fps}
<tr> <tr>
<td colspan="2"> <td colspan="2">
<SmallGraph points={fps} /> <SmallGraph points={fps} />

View File

@@ -35,6 +35,9 @@
scene = $bindable(), scene = $bindable(),
}: Props = $props(); }: Props = $props();
let geometries = $state.raw<BufferGeometry[]>([]);
let center = $state(new Vector3(0, 4, 0));
useTask( useTask(
(delta) => { (delta) => {
fps.push(1 / delta); fps.push(1 / delta);
@@ -45,11 +48,13 @@
export const invalidate = function () { export const invalidate = function () {
if (scene) { if (scene) {
geometries = scene.children const geos: BufferGeometry[] = [];
.filter((child) => "geometry" in child && child.isObject3D) scene.traverse(function (child) {
.map((child) => { if (isMesh(child)) {
return (child as Mesh).geometry; geos.push(child.geometry);
}); }
});
geometries = geos;
} }
if (geometries && scene && centerCamera) { if (geometries && scene && centerCamera) {
@@ -62,9 +67,6 @@
_invalidate(); _invalidate();
}; };
let geometries = $state<BufferGeometry[]>();
let center = $state(new Vector3(0, 4, 0));
function isMesh(child: Mesh | any): child is Mesh { function isMesh(child: Mesh | any): child is Mesh {
return child.isObject3D && "material" in child; return child.isObject3D && "material" in child;
} }
@@ -76,7 +78,7 @@
$effect(() => { $effect(() => {
const wireframe = appSettings.value.debug.wireframe; const wireframe = appSettings.value.debug.wireframe;
scene.traverse(function (child) { scene.traverse(function (child) {
if (isMesh(child) && isMatCapMaterial(child.material)) { if (isMesh(child) && isMatCapMaterial(child.material) && child.visible) {
child.material.wireframe = wireframe; child.material.wireframe = wireframe;
} }
}); });
@@ -90,6 +92,13 @@
geo.attributes.position.array[i + 2], geo.attributes.position.array[i + 2],
] as Vector3Tuple; ] as Vector3Tuple;
} }
// $effect(() => {
// console.log({
// geometries: $state.snapshot(geometries),
// indices: appSettings.value.debug.showIndices,
// });
// });
</script> </script>
<Camera {center} {centerCamera} /> <Camera {center} {centerCamera} />

View File

@@ -11,7 +11,7 @@ import {
} from "three"; } from "three";
function fastArrayHash(arr: Int32Array) { function fastArrayHash(arr: Int32Array) {
const sampleDistance = Math.max(Math.floor(arr.length / 100), 1); const sampleDistance = Math.max(Math.floor(arr.length / 1000), 1);
const sampleCount = Math.floor(arr.length / sampleDistance); const sampleCount = Math.floor(arr.length / sampleDistance);
let hash = new Int32Array(sampleCount); let hash = new Int32Array(sampleCount);
@@ -40,6 +40,9 @@ export function createGeometryPool(parentScene: Group, material: Material) {
let hash = fastArrayHash(data); let hash = fastArrayHash(data);
let geometry = existingMesh ? existingMesh.geometry : new BufferGeometry(); let geometry = existingMesh ? existingMesh.geometry : new BufferGeometry();
if (existingMesh) {
existingMesh.visible = true;
}
// Extract data from the encoded array // Extract data from the encoded array
// const geometryType = encodedData[index++]; // const geometryType = encodedData[index++];
@@ -121,7 +124,6 @@ export function createGeometryPool(parentScene: Group, material: Material) {
updateSingleGeometry(input, existingMesh || null); updateSingleGeometry(input, existingMesh || null);
} else if (existingMesh) { } else if (existingMesh) {
existingMesh.visible = false; existingMesh.visible = false;
scene.remove(existingMesh);
} }
} }
return { totalVertices, totalFaces }; return { totalVertices, totalFaces };
@@ -258,7 +260,6 @@ export function createInstancedGeometryPool(
updateSingleInstance(input, existingMesh || null); updateSingleInstance(input, existingMesh || null);
} else if (existingMesh) { } else if (existingMesh) {
existingMesh.visible = false; existingMesh.visible = false;
scene.remove(existingMesh);
} }
} }
return { totalVertices, totalFaces }; return { totalVertices, totalFaces };

View File

@@ -1,19 +1,33 @@
import { type SyncCache } from "@nodarium/types"; import { type SyncCache } from "@nodarium/types";
export class MemoryRuntimeCache implements SyncCache { export class MemoryRuntimeCache implements SyncCache {
private map = new Map<string, unknown>();
size: number;
private cache: [string, unknown][] = []; constructor(size = 50) {
size = 50; this.size = size;
}
get<T>(key: string): T | undefined { get<T>(key: string): T | undefined {
return this.cache.find(([k]) => k === key)?.[1] as T; if (!this.map.has(key)) return undefined;
} const value = this.map.get(key) as T;
set<T>(key: string, value: T): void { this.map.delete(key);
this.cache.push([key, value]); this.map.set(key, value);
this.cache = this.cache.slice(-this.size); return value;
}
clear(): void {
this.cache = [];
} }
set<T>(key: string, value: T): void {
if (this.map.has(key)) {
this.map.delete(key);
}
this.map.set(key, value);
while (this.map.size > this.size) {
const oldestKey = this.map.keys().next().value as string;
this.map.delete(oldestKey);
}
}
clear(): void {
this.map.clear();
}
} }

View File

@@ -244,13 +244,14 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
} }
this.perf?.addPoint("cache-hit", 0); this.perf?.addPoint("cache-hit", 0);
log.group(`executing ${node_type.id || node.id}`); log.group(`executing ${node_type.id}-${node.id}`);
log.log(`Inputs:`, inputs); log.log(`Inputs:`, inputs);
a = performance.now(); a = performance.now();
results[node.id] = node_type.execute(encoded_inputs); results[node.id] = node_type.execute(encoded_inputs);
log.log("Executed", node.type, node.id)
b = performance.now(); b = performance.now();
if (this.cache) { if (this.cache && node.id !== outputNode.id) {
this.cache.set(inputHash, results[node.id]); this.cache.set(inputHash, results[node.id]);
} }

View File

@@ -2,11 +2,13 @@ import { MemoryRuntimeExecutor } from "./runtime-executor";
import { RemoteNodeRegistry, IndexDBCache } from "@nodarium/registry"; import { RemoteNodeRegistry, IndexDBCache } from "@nodarium/registry";
import type { Graph } from "@nodarium/types"; import type { Graph } from "@nodarium/types";
import { createPerformanceStore } from "@nodarium/utils"; import { createPerformanceStore } from "@nodarium/utils";
import { MemoryRuntimeCache } from "./runtime-executor-cache";
const indexDbCache = new IndexDBCache("node-registry"); const indexDbCache = new IndexDBCache("node-registry");
const nodeRegistry = new RemoteNodeRegistry("", indexDbCache); const nodeRegistry = new RemoteNodeRegistry("", indexDbCache);
const executor = new MemoryRuntimeExecutor(nodeRegistry); const cache = new MemoryRuntimeCache()
const executor = new MemoryRuntimeExecutor(nodeRegistry, cache);
const performanceStore = createPerformanceStore(); const performanceStore = createPerformanceStore();
executor.perf = performanceStore; executor.perf = performanceStore;

View File

@@ -54,7 +54,7 @@ export const AppSettingTypes = {
}, },
useWorker: { useWorker: {
type: "boolean", type: "boolean",
label: "Execute runtime in worker", label: "Execute in WebWorker",
value: true, value: true,
}, },
showIndices: { showIndices: {

View File

@@ -1,43 +1,46 @@
<script lang="ts"> <script lang="ts">
import { getContext } from "svelte"; import { getContext, type Snippet } from "svelte";
import type { Readable } from "svelte/store"; import type { PanelState } from "./PanelState.svelte";
export let id: string; const {
export let icon: string = ""; id,
export let title = ""; icon = "",
export let classes = ""; title = "",
export let hidden: boolean | undefined = undefined; classes = "",
hidden,
children,
} = $props<{
id: string;
icon?: string;
title?: string;
classes?: string;
hidden?: boolean;
children?: Snippet;
}>();
const setVisibility = const panelState = getContext<PanelState>("panel-state");
getContext<(id: string, visible: boolean) => void>("setVisibility");
$: if (typeof hidden === "boolean") { const panel = panelState.registerPanel(id, icon, classes, hidden);
setVisibility(id, !hidden); $effect(() => {
} panel.hidden = hidden;
});
const registerPanel =
getContext<
(id: string, icon: string, classes: string) => Readable<boolean>
>("registerPanel");
let visible = registerPanel(id, icon, classes);
</script> </script>
{#if $visible} {#if panelState.activePanel.value === id}
<div class="wrapper" class:hidden> <div class="wrapper" class:hidden>
{#if title} {#if title}
<header> <header>
<h3>{title}</h3> <h3>{title}</h3>
</header> </header>
{/if} {/if}
<slot /> {@render children?.()}
</div> </div>
{/if} {/if}
<style> <style>
header { header {
border-bottom: solid thin var(--outline); border-bottom: solid thin var(--outline);
height: 69px; height: 70px;
display: flex; display: flex;
align-items: center; align-items: center;
padding-left: 1em; padding-left: 1em;

View File

@@ -0,0 +1,35 @@
import { localState } from "$lib/helpers/localState.svelte";
type Panel = {
icon: string;
classes: string;
hidden?: boolean;
}
export class PanelState {
panels = $state<Record<string, Panel>>({});
activePanel = localState<string | boolean>("node.activePanel", "")
get keys() {
return Object.keys(this.panels);
}
public registerPanel(id: string, icon: string, classes: string, hidden: boolean): Panel {
const state = $state({
icon: icon,
classes: classes,
hidden: hidden,
});
this.panels[id] = state;
return state;
}
public toggleOpen() {
if (this.activePanel.value) {
this.activePanel.value = false;
} else {
this.activePanel.value = this.keys[0]
}
}
}

View File

@@ -1,77 +1,35 @@
<script lang="ts"> <script lang="ts">
import localStore from "$lib/helpers/localStore"; import { setContext, type Snippet } from "svelte";
import { setContext } from "svelte"; import { PanelState } from "./PanelState.svelte";
import { derived } from "svelte/store";
let panels: Record< const state = new PanelState();
string, setContext("panel-state", state);
{
icon: string;
id: string;
classes: string;
visible?: boolean;
}
> = {};
const activePanel = localStore<keyof typeof panels | false>( const { children } = $props<{ children?: Snippet }>();
"nodes.settings.activePanel",
false,
);
$: keys = panels
? (Object.keys(panels) as unknown as (keyof typeof panels)[]).filter(
(key) => !!panels[key]?.id,
)
: [];
setContext("setVisibility", (id: string, visible: boolean) => {
panels[id].visible = visible;
panels = { ...panels };
});
setContext("registerPanel", (id: string, icon: string, classes: string) => {
panels[id] = { id, icon, classes };
return derived(activePanel, ($activePanel) => {
return $activePanel === id;
});
});
function setActivePanel(panel: keyof typeof panels | false) {
if (panel === $activePanel) {
$activePanel = false;
} else if (panel) {
$activePanel = panel;
} else {
$activePanel = false;
}
}
</script> </script>
<div class="wrapper" class:visible={$activePanel}> <div class="wrapper" class:visible={state.activePanel.value}>
<div class="tabs"> <div class="tabs">
<button <button aria-label="Close" onclick={() => state.toggleOpen()}>
aria-label="Close" <span class="icon-[tabler--settings]"></span>
on:click={() => { <span class="absolute i-[tabler--chevron-left] w-6 h-6 block"></span>
setActivePanel($activePanel ? false : keys[0]);
}}
>
<span class="absolute i-tabler-chevron-left w-6 h-6 block"></span>
</button> </button>
{#each keys as panel (panels[panel].id)} {#each state.keys as panelId (panelId)}
{#if panels[panel].visible !== false} {#if !state.panels[panelId].hidden}
<button <button
aria-label={panel} aria-label={panelId}
class="tab {panels[panel].classes}" class="tab {state.panels[panelId].classes}"
class:active={panel === $activePanel} class:active={panelId === state.activePanel.value}
on:click={() => setActivePanel(panel)} onclick={() => (state.activePanel.value = panelId)}
> >
<span class={`block w-6 h-6 ${panels[panel].icon}`}></span> <span class={`block w-6 h-6 iconify ${state.panels[panelId].icon}`}
></span>
</button> </button>
{/if} {/if}
{/each} {/each}
</div> </div>
<div class="content"> <div class="content">
<slot /> {@render children?.()}
</div> </div>
</div> </div>

View File

@@ -64,6 +64,7 @@
lastPropsHash = propsHash; lastPropsHash = propsHash;
if (needsUpdate) { if (needsUpdate) {
manager.save();
manager.execute(); manager.execute();
} }
} }

View File

@@ -8,17 +8,17 @@
node: NodeInstance | undefined; node: NodeInstance | undefined;
}; };
const { manager, node }: Props = $props(); let { manager, node = $bindable() }: Props = $props();
</script> </script>
{#if node} {#if node}
{#key node.id} {#key node.id}
{#if node} {#if node}
<ActiveNodeSelected {manager} {node} /> <ActiveNodeSelected {manager} bind:node />
{:else} {:else}
<p class="mx-4">Active Node has no Settings</p> <p class="mx-4">Active Node has no Settings</p>
{/if} {/if}
{/key} {/key}
{:else} {:else}
<p class="mx-4">No active node</p> <p class="mx-4">No node selected</p>
{/if} {/if}

View File

@@ -1,9 +1,15 @@
<script lang="ts" module>
let result:
| { stdev: number; avg: number; duration: number; samples: number[] }
| undefined = $state();
</script>
<script lang="ts"> <script lang="ts">
import localStore from "$lib/helpers/localStore";
import { Integer } from "@nodarium/ui"; import { Integer } from "@nodarium/ui";
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import { humanizeDuration } from "$lib/helpers"; import { humanizeDuration } from "$lib/helpers";
import Monitor from "$lib/performance/Monitor.svelte"; import Monitor from "$lib/performance/Monitor.svelte";
import { localState } from "$lib/helpers/localState.svelte";
function calculateStandardDeviation(array: number[]) { function calculateStandardDeviation(array: number[]) {
const n = array.length; const n = array.length;
@@ -12,18 +18,18 @@
array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n, array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n,
); );
} }
type Props = {
run: () => Promise<any>;
};
export let run: () => Promise<any>; const { run }: Props = $props();
let isRunning = false; let isRunning = $state(false);
let amount = localStore<number>("nodes.benchmark.samples", 500); let amount = localState<number>("nodes.benchmark.samples", 500);
let samples = 0; let samples = $state(0);
let warmUp = writable(0); let warmUp = writable(0);
let warmUpAmount = 10; let warmUpAmount = 10;
let state = ""; let status = "";
let result:
| { stdev: number; avg: number; duration: number; samples: number[] }
| undefined;
const copyContent = async (text?: string | number) => { const copyContent = async (text?: string | number) => {
if (!text) return; if (!text) return;
@@ -56,7 +62,7 @@
let results = []; let results = [];
// perform run // perform run
for (let i = 0; i < $amount; i++) { for (let i = 0; i < amount.value; i++) {
const a = performance.now(); const a = performance.now();
await run(); await run();
samples = i; samples = i;
@@ -73,55 +79,53 @@
} }
</script> </script>
{state} {status}
<div class="wrapper" class:running={isRunning}> <div class="wrapper" class:running={isRunning}>
{#if isRunning} {#if result}
{#if result} <h3>Finished ({humanizeDuration(result.duration)})</h3>
<h3>Finished ({humanizeDuration(result.duration)})</h3> <div class="monitor-wrapper">
<div class="monitor-wrapper"> <Monitor points={result.samples} />
<Monitor points={result.samples} /> </div>
</div> <label for="bench-avg">Average </label>
<label for="bench-avg">Average </label> <button
<button id="bench-avg"
id="bench-avg" onkeydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)}
on:keydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)} onclick={() => copyContent(result?.avg)}
on:click={() => copyContent(result?.avg)} >{Math.floor(result.avg * 100) / 100}</button
>{Math.floor(result.avg * 100) / 100}</button >
> <i
<i role="button"
role="button" tabindex="0"
tabindex="0" onkeydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)}
on:keydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)} onclick={() => copyContent(result?.avg)}>(click to copy)</i
on:click={() => copyContent(result?.avg)}>(click to copy)</i >
> <label for="bench-stdev">Standard Deviation σ</label>
<label for="bench-stdev">Standard Deviation σ</label> <button id="bench-stdev" onclick={() => copyContent(result?.stdev)}
<button id="bench-stdev" on:click={() => copyContent(result?.stdev)} >{Math.floor(result.stdev * 100) / 100}</button
>{Math.floor(result.stdev * 100) / 100}</button >
> <i
<i role="button"
role="button" tabindex="0"
tabindex="0" onkeydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)}
on:keydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)} onclick={() => copyContent(result?.stdev + "")}>(click to copy)</i
on:click={() => copyContent(result?.stdev + "")}>(click to copy)</i >
> <div>
<div> <button onclick={() => (isRunning = false)}>reset</button>
<button on:click={() => (isRunning = false)}>reset</button> </div>
</div> {:else if isRunning}
{:else} <p>WarmUp ({$warmUp}/{warmUpAmount})</p>
<p>WarmUp ({$warmUp}/{warmUpAmount})</p> <progress value={$warmUp} max={warmUpAmount}
<progress value={$warmUp} max={warmUpAmount} >{Math.floor(($warmUp / warmUpAmount) * 100)}%</progress
>{Math.floor(($warmUp / warmUpAmount) * 100)}%</progress >
> <p>Progress ({samples}/{amount.value})</p>
<p>Progress ({samples}/{$amount})</p> <progress value={samples} max={amount.value}
<progress value={samples} max={$amount} >{Math.floor((samples / amount.value) * 100)}%</progress
>{Math.floor((samples / $amount) * 100)}%</progress >
>
{/if}
{:else} {:else}
<label for="bench-samples">Samples</label> <label for="bench-samples">Samples</label>
<Integer id="bench-sample" bind:value={$amount} max={1000} /> <Integer id="bench-sample" bind:value={amount.value} max={1000} />
<button on:click={benchmark} disabled={isRunning}> start </button> <button onclick={benchmark} disabled={isRunning}> start </button>
{/if} {/if}
</div> </div>

View File

@@ -15,7 +15,7 @@
FileSaver.saveAs(blob, name + "." + extension); FileSaver.saveAs(blob, name + "." + extension);
}; };
export let scene: Group; const { scene } = $props<{ scene: Group }>();
let gltfExporter: GLTFExporter; let gltfExporter: GLTFExporter;
async function exportGltf() { async function exportGltf() {
@@ -53,7 +53,7 @@
} }
</script> </script>
<div class="p-2"> <div class="p-4">
<button on:click={exportObj}> export obj </button> <button onclick={exportObj}> export obj </button>
<button on:click={exportGltf}> export gltf </button> <button onclick={exportGltf}> export gltf </button>
</div> </div>

View File

@@ -13,32 +13,34 @@
let { keymaps }: Props = $props(); let { keymaps }: Props = $props();
</script> </script>
<table class="wrapper"> <div class="p-4">
<tbody> <table class="wrapper">
{#each keymaps as keymap} <tbody>
<tr> {#each keymaps as keymap}
<td colspan="2">
<h3>{keymap.title}</h3>
</td>
</tr>
{#each get(keymap.keymap?.keys) as key}
<tr> <tr>
{#if key.description} <td colspan="2">
<td class="command-wrapper"> <h3>{keymap.title}</h3>
<ShortCut </td>
alt={key.alt}
ctrl={key.ctrl}
shift={key.shift}
key={key.key}
/>
</td>
<td>{key.description}</td>
{/if}
</tr> </tr>
{#each get(keymap.keymap?.keys) as key}
<tr>
{#if key.description}
<td class="command-wrapper">
<ShortCut
alt={key.alt}
ctrl={key.ctrl}
shift={key.shift}
key={key.key}
/>
</td>
<td>{key.description}</td>
{/if}
</tr>
{/each}
{/each} {/each}
{/each} </tbody>
</tbody> </table>
</table> </div>
<style> <style>
.wrapper { .wrapper {

View File

@@ -1,7 +1,8 @@
<script lang="ts"> <script lang="ts">
import "@nodarium/ui/app.css"; import "@nodarium/ui/app.css";
import "virtual:uno.css"; import "../app.css";
import "@unocss/reset/normalize.css"; import type { Snippet } from "svelte";
const { children } = $props<{ children?: Snippet }>();
</script> </script>
<slot /> {@render children?.()}

View File

@@ -88,13 +88,10 @@
randomSeed: { type: "boolean", value: false }, randomSeed: { type: "boolean", value: false },
}); });
let runIndex = 0;
async function update( async function update(
g: Graph, g: Graph,
s: Record<string, any> = $state.snapshot(graphSettings), s: Record<string, any> = $state.snapshot(graphSettings),
) { ) {
runIndex++;
performanceStore.startRun(); performanceStore.startRun();
try { try {
let a = performance.now(); let a = performance.now();
@@ -181,7 +178,7 @@
onsave={(graph) => handleSave(graph)} onsave={(graph) => handleSave(graph)}
/> />
<Sidebar> <Sidebar>
<Panel id="general" title="General" icon="i-tabler-settings"> <Panel id="general" title="General" icon="i-[tabler--settings]">
<NestedSettings <NestedSettings
id="general" id="general"
bind:value={appSettings.value} bind:value={appSettings.value}
@@ -191,7 +188,7 @@
<Panel <Panel
id="shortcuts" id="shortcuts"
title="Keyboard Shortcuts" title="Keyboard Shortcuts"
icon="i-tabler-keyboard" icon="i-[tabler--keyboard]"
> >
<Keymap <Keymap
keymaps={[ keymaps={[
@@ -200,23 +197,21 @@
]} ]}
/> />
</Panel> </Panel>
<Panel id="exports" title="Exporter" icon="i-tabler-package-export"> <Panel id="exports" title="Exporter" icon="i-[tabler--package-export]">
<ExportSettings {scene} /> <ExportSettings {scene} />
</Panel> </Panel>
<Panel <Panel
id="node-store" id="node-store"
classes="text-green-400"
title="Node Store" title="Node Store"
icon="i-tabler-database" icon="i-[tabler--database] bg-green-400"
> >
<NodeStore registry={nodeRegistry} /> <NodeStore registry={nodeRegistry} />
</Panel> </Panel>
<Panel <Panel
id="performance" id="performance"
title="Performance" title="Performance"
classes="text-red-400"
hidden={!appSettings.value.debug.showPerformancePanel} hidden={!appSettings.value.debug.showPerformancePanel}
icon="i-tabler-brand-speedtest" icon="i-[tabler--brand-speedtest] bg-red-400"
> >
{#if $performanceStore} {#if $performanceStore}
<PerformanceViewer data={$performanceStore} /> <PerformanceViewer data={$performanceStore} />
@@ -226,24 +221,22 @@
id="graph-source" id="graph-source"
title="Graph Source" title="Graph Source"
hidden={!appSettings.value.debug.showGraphJson} hidden={!appSettings.value.debug.showGraphJson}
icon="i-tabler-code" icon="i-[tabler--code]"
> >
<GraphSource {graph} /> <GraphSource graph={graph && manager.serialize()} />
</Panel> </Panel>
<Panel <Panel
id="benchmark" id="benchmark"
title="Benchmark" title="Benchmark"
classes="text-red-400"
hidden={!appSettings.value.debug.showBenchmarkPanel} hidden={!appSettings.value.debug.showBenchmarkPanel}
icon="i-tabler-graph" icon="i-[tabler--graph] bg-red-400"
> >
<BenchmarkPanel run={randomGenerate} /> <BenchmarkPanel run={randomGenerate} />
</Panel> </Panel>
<Panel <Panel
id="graph-settings" id="graph-settings"
title="Graph Settings" title="Graph Settings"
classes="text-blue-400" icon="i-[custom--graph] bg-blue-400"
icon="i-custom-graph"
> >
<NestedSettings <NestedSettings
id="graph-settings" id="graph-settings"
@@ -254,10 +247,9 @@
<Panel <Panel
id="active-node" id="active-node"
title="Node Settings" title="Node Settings"
classes="text-blue-400" icon="i-[tabler--adjustments] bg-blue-400"
icon="i-tabler-adjustments"
> >
<ActiveNodeSettings {manager} node={activeNode} /> <ActiveNodeSettings {manager} bind:node={activeNode} />
</Panel> </Panel>
</Sidebar> </Sidebar>
</Grid.Cell> </Grid.Cell>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import type { Snippet } from "svelte";
const { children } = $props<{ children?: Snippet }>();
</script>
<main class="w-screen overflow-x-hidden">
{@render children()}
</main>

View File

@@ -0,0 +1,120 @@
<script lang="ts">
import NodeHTML from "$lib/graph-interface/node/NodeHTML.svelte";
import { localState } from "$lib/helpers/localState.svelte";
import Panel from "$lib/sidebar/Panel.svelte";
import Sidebar from "$lib/sidebar/Sidebar.svelte";
import { IndexDBCache, RemoteNodeRegistry } from "@nodarium/registry";
import { type NodeId, type NodeInstance } from "@nodarium/types";
import Code from "./Code.svelte";
import Grid from "$lib/grid";
import {
concatEncodedArrays,
createWasmWrapper,
encodeNestedArray,
} from "@nodarium/utils";
const registryCache = new IndexDBCache("node-registry");
const nodeRegistry = new RemoteNodeRegistry("", registryCache);
let activeNode = localState<NodeId | undefined>(
"node.dev.activeNode",
undefined,
);
let nodeWasm = $state<ArrayBuffer>();
let nodeInstance = $state<NodeInstance>();
let nodeWasmWrapper = $state<ReturnType<typeof createWasmWrapper>>();
async function fetchNodeData(nodeId?: NodeId) {
console.log("FETCHING", { nodeId });
nodeWasm = undefined;
nodeInstance = undefined;
if (!nodeId) return;
const data = await nodeRegistry.fetchNodeDefinition(nodeId);
nodeWasm = await nodeRegistry.fetchArrayBuffer("nodes/" + nodeId + ".wasm");
nodeInstance = {
id: 0,
type: nodeId,
position: [0, 0] as [number, number],
props: {},
state: {
type: data,
},
};
nodeWasmWrapper = createWasmWrapper(nodeWasm);
}
$effect(() => {
fetchNodeData(activeNode.value);
});
$effect(() => {
if (nodeInstance?.props && nodeWasmWrapper) {
const keys = Object.keys(nodeInstance.state.type?.inputs || {});
let ins = Object.values(nodeInstance.props) as number[];
if (keys[0] === "plant") {
ins = [[0, 0, 0, 0, 0, 0, 0, 0], ...ins];
}
const inputs = concatEncodedArrays(encodeNestedArray(ins));
nodeWasmWrapper?.execute(inputs);
}
});
</script>
<div class="node-wrapper absolute bottom-8 left-8">
{#if nodeInstance}
<NodeHTML inView position="relative" z={5} bind:node={nodeInstance} />
{/if}
</div>
<Grid.Row>
<Grid.Cell>
<pre>
<code>
{JSON.stringify(nodeInstance?.props)}
</code>
</pre>
</Grid.Cell>
<Grid.Cell>
<div class="h-screen w-[80vw] overflow-y-auto">
{#if nodeWasm}
<Code wasm={nodeWasm} />
{/if}
</div>
</Grid.Cell>
</Grid.Row>
<Sidebar>
<Panel
id="node-store"
classes="text-green-400"
title="Node Store"
icon="i-[tabler--database]"
>
<div class="p-4 flex flex-col gap-2">
{#await nodeRegistry.fetchCollection("max/plantarium")}
<p>Loading Nodes...</p>
{:then result}
{#each result.nodes as n}
<button
class="cursor-pointer p-2 bg-layer-1 {activeNode.value === n.id
? 'outline outline-offset-1'
: ''}"
onclick={() => (activeNode.value = n.id)}>{n.id}</button
>
{/each}
{/await}
</div>
</Panel>
</Sidebar>
<style>
:global body {
height: 100vh;
width: 100vw;
overflow: hidden;
}
</style>

View File

@@ -0,0 +1,26 @@
<script lang="ts">
import wabtInit from "wabt";
const { wasm } = $props<{ wasm: ArrayBuffer }>();
async function toWat(arrayBuffer: ArrayBuffer) {
const wabt = await wabtInit();
const module = wabt.readWasm(new Uint8Array(arrayBuffer), {
readDebugNames: true,
});
module.generateNames();
module.applyNames();
return module.toText({ foldExprs: false, inlineExport: false });
}
</script>
{#await toWat(wasm)}
<p>Converting to WAT</p>
{:then c}
<pre>
<code class="text-gray-50">{c}</code>
</pre>
{/await}

View File

@@ -1,20 +0,0 @@
// uno.config.ts
import { defineConfig } from 'unocss'
import presetIcons from '@unocss/preset-icons'
import { presetUno } from 'unocss'
import fs from 'fs'
const icons = Object.fromEntries(fs.readdirSync('./src/lib/icons')
.map(name => [name.replace(".svg", ""), fs.readFileSync(`./src/lib/icons/${name}`, 'utf-8')]))
export default defineConfig({
presets: [
presetUno(),
presetIcons({
collections: {
custom: icons
}
}),
]
})

View File

@@ -1,14 +1,14 @@
import { sveltekit } from '@sveltejs/kit/vite'; import { sveltekit } from '@sveltejs/kit/vite';
import UnoCSS from 'unocss/vite';
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite'
import comlink from 'vite-plugin-comlink'; import comlink from 'vite-plugin-comlink';
import glsl from "vite-plugin-glsl"; import glsl from "vite-plugin-glsl";
import wasm from "vite-plugin-wasm"; import wasm from "vite-plugin-wasm";
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
tailwindcss(),
comlink(), comlink(),
UnoCSS(),
sveltekit(), sveltekit(),
glsl(), glsl(),
wasm() wasm()

27
flake.lock generated Normal file
View File

@@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

40
flake.nix Normal file
View File

@@ -0,0 +1,40 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
};
outputs = {nixpkgs, ...}: let
systems = ["aarch64-darwin" "x86_64-linux"];
eachSystem = function:
nixpkgs.lib.genAttrs systems (system:
function {
inherit system;
pkgs = nixpkgs.legacyPackages.${system};
});
in {
devShells = eachSystem ({pkgs, ...}: {
default = pkgs.mkShellNoCC {
packages = [
# general deps
pkgs.nodejs_24
pkgs.pnpm_10
# wasm/rust stuff
pkgs.rustc
pkgs.cargo
pkgs.rust-analyzer
pkgs.rustfmt
pkgs.wasm-bindgen-cli
pkgs.wasm-pack
pkgs.lld
# frontend
pkgs.vscode-langservers-extracted
pkgs.typescript-language-server
pkgs.prettier
pkgs.tailwindcss-language-server
];
};
});
};
}

View File

@@ -11,18 +11,8 @@ crate-type = ["cdylib", "rlib"]
default = ["console_error_panic_hook"] default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
utils = { version = "0.1.0", path = "../../../../packages/utils" } utils = { version = "0.1.0", path = "../../../../packages/utils" }
macros = { version = "0.1.0", path = "../../../../packages/macros" } macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] } web-sys = { version = "0.3.69", features = ["console"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/out.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,22 +7,6 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/box.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,18 +1,15 @@
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_macros::nodarium_execute;
use nodarium_utils::{ use nodarium_utils::{
concat_args, encode_float, evaluate_float, geometry::calculate_normals, log, set_panic_hook, encode_float, evaluate_float, geometry::calculate_normals,log,
split_args, wrap_arg, split_args, wrap_arg,
}; };
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); nodarium_definition_file!("src/input.json");
#[rustfmt::skip] #[nodarium_execute]
#[wasm_bindgen]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook();
let args = split_args(input); let args = split_args(input);
log!("WASM(cube): input: {:?} -> {:?}", input, args); log!("WASM(cube): input: {:?} -> {:?}", input, args);
@@ -22,7 +19,6 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
let p = encode_float(size); let p = encode_float(size);
let n = encode_float(-size); let n = encode_float(-size);
// [[1,3, x, y, z, x, y,z,x,y,z]]; // [[1,3, x, y, z, x, y,z,x,y,z]];
let mut cube_geometry = [ let mut cube_geometry = [

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,23 +7,6 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
glam = "0.27.0"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/branch.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,20 +1,19 @@
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_macros::nodarium_execute;
use nodarium_utils::{ use nodarium_utils::{
concat_arg_vecs, evaluate_float, evaluate_int, concat_arg_vecs, evaluate_float, evaluate_int,
geometry::{ geometry::{
create_path, interpolate_along_path, rotate_vector_by_angle, wrap_path, wrap_path_mut, create_path, interpolate_along_path, rotate_vector_by_angle, wrap_path, wrap_path_mut,
}, },
log, set_panic_hook, split_args, log, split_args,
}; };
use std::f32::consts::PI; use std::f32::consts::PI;
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); nodarium_definition_file!("src/input.json");
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook();
let args = split_args(input); let args = split_args(input);
let paths = split_args(args[0]); let paths = split_args(args[0]);

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,21 +7,6 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/float.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,9 +1,9 @@
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use wasm_bindgen::prelude::*; use nodarium_macros::nodarium_execute;
include_definition_file!("src/input.json"); nodarium_definition_file!("src/input.json");
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(args: &[i32]) -> Vec<i32> { pub fn execute(args: &[i32]) -> Vec<i32> {
args.into() args.into()
} }

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,24 +7,7 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] } glam = "0.30.10"
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
noise = "0.9.0"
glam = "0.27.0"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/gravity.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,22 +1,20 @@
use glam::Vec3; use glam::Vec3;
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_macros::nodarium_execute;
use nodarium_utils::{ use nodarium_utils::{
concat_args, evaluate_float, evaluate_int, concat_args, evaluate_float, evaluate_int,
geometry::{wrap_path, wrap_path_mut}, geometry::{wrap_path, wrap_path_mut},
log, reset_call_count, set_panic_hook, split_args, log, reset_call_count, split_args,
}; };
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); nodarium_definition_file!("src/input.json");
fn lerp_vec3(a: Vec3, b: Vec3, t: f32) -> Vec3 { fn lerp_vec3(a: Vec3, b: Vec3, t: f32) -> Vec3 {
a + (b - a) * t a + (b - a) * t
} }
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook();
reset_call_count(); reset_call_count();
let args = split_args(input); let args = split_args(input);

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -1,5 +1,5 @@
[package] [package]
name = "nodarium_instance" name = "instance"
version = "0.1.0" version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"] authors = ["Max Richter <jim-x@web.de>"]
edition = "2018" edition = "2018"
@@ -7,23 +7,7 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] } glam = "0.30.10"
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
glam = "0.27.0"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/instance.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,20 +1,18 @@
use glam::{Mat4, Quat, Vec3}; use glam::{Mat4, Quat, Vec3};
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_execute;
use nodarium_macros::nodarium_definition_file;
use nodarium_utils::{ use nodarium_utils::{
concat_args, encode_float, evaluate_float, evaluate_int, concat_args, evaluate_float, evaluate_int,
geometry::{ geometry::{
calculate_normals, create_instance_data, wrap_geometry_data, wrap_instance_data, wrap_path, create_instance_data, wrap_geometry_data, wrap_instance_data, wrap_path,
}, },
log, set_panic_hook, split_args, wrap_arg, log, split_args,
}; };
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); nodarium_definition_file!("src/input.json");
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook();
let args = split_args(input); let args = split_args(input);
let mut inputs = split_args(args[0]); let mut inputs = split_args(args[0]);
log!("WASM(instance): inputs: {:?}", inputs); log!("WASM(instance): inputs: {:?}", inputs);

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,17 +7,6 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
web-sys = { version = "0.3.69", features = ["console"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/math.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,12 +1,13 @@
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_utils::{concat_args, set_panic_hook, split_args}; use nodarium_macros::nodarium_execute;
use wasm_bindgen::prelude::*; use nodarium_utils::{
concat_args, split_args
};
include_definition_file!("src/input.json"); #[nodarium_execute]
#[wasm_bindgen]
pub fn execute(args: &[i32]) -> Vec<i32> { pub fn execute(args: &[i32]) -> Vec<i32> {
set_panic_hook();
let args = split_args(args); let args = split_args(args);
concat_args(vec![&[0], args[0], args[1], args[2]]) concat_args(vec![&[0], args[0], args[1], args[2]])
} }
nodarium_definition_file!("src/input.json");

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -1,5 +1,5 @@
[package] [package]
name = "nodes-noise" name = "noise"
version = "0.1.0" version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"] authors = ["Max Richter <jim-x@web.de>"]
edition = "2018" edition = "2018"
@@ -7,24 +7,8 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
noise = "0.9.0" noise = "0.9.0"
glam = "0.27.0"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/noise.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,21 +1,19 @@
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_macros::nodarium_execute;
use nodarium_utils::{ use nodarium_utils::{
concat_args, evaluate_float, evaluate_int, evaluate_vec3, geometry::wrap_path_mut, log, concat_args, evaluate_float, evaluate_int, evaluate_vec3, geometry::wrap_path_mut,
reset_call_count, set_panic_hook, split_args, reset_call_count, split_args,
}; };
use noise::{HybridMulti, MultiFractal, NoiseFn, OpenSimplex}; use noise::{HybridMulti, MultiFractal, NoiseFn, OpenSimplex};
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); nodarium_definition_file!("src/input.json");
fn lerp(a: f32, b: f32, t: f32) -> f32 { fn lerp(a: f32, b: f32, t: f32) -> f32 {
a + t * (b - a) a + t * (b - a)
} }
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook();
reset_call_count(); reset_call_count();
let args = split_args(input); let args = split_args(input);

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,24 +7,6 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
console_error_panic_hook = ["dep:console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
glam = "0.27.0"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/output.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,17 +1,15 @@
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_macros::nodarium_execute;
use nodarium_utils::{ use nodarium_utils::{
concat_args, evaluate_int, concat_args, evaluate_int,
geometry::{extrude_path, wrap_path}, geometry::{extrude_path, wrap_path},
log, set_panic_hook, split_args, log, split_args,
}; };
use wasm_bindgen::prelude::*;
include_definition_file!("src/inputs.json"); nodarium_definition_file!("src/inputs.json");
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook();
log!("WASM(output): input: {:?}", input); log!("WASM(output): input: {:?}", input);
let args = split_args(input); let args = split_args(input);

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,21 +7,7 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/random.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,12 +1,11 @@
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_utils::{concat_args, set_panic_hook, split_args}; use nodarium_macros::nodarium_execute;
use wasm_bindgen::prelude::*; use nodarium_utils::{concat_args, split_args};
include_definition_file!("src/definition.json"); nodarium_definition_file!("src/definition.json");
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(args: &[i32]) -> Vec<i32> { pub fn execute(args: &[i32]) -> Vec<i32> {
set_panic_hook();
let args = split_args(args); let args = split_args(args);
concat_args(vec![&[1], args[0], args[1], args[2]]) concat_args(vec![&[1], args[0], args[1], args[2]])
} }

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,23 +7,8 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4" glam = "0.30.10"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
glam = "0.27.0"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/rotate.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,16 +1,15 @@
use glam::{Mat4, Vec3}; use glam::{Mat4, Vec3};
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_macros::nodarium_execute;
use nodarium_utils::{ use nodarium_utils::{
concat_args, evaluate_float, evaluate_int, geometry::wrap_path_mut, log, set_panic_hook, concat_args, evaluate_float, evaluate_int, geometry::wrap_path_mut, log,
split_args, split_args,
}; };
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); nodarium_definition_file!("src/input.json");
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook();
log!("DEBUG args: {:?}", input); log!("DEBUG args: {:?}", input);

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -7,23 +7,6 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
web-sys = { version = "0.3.69", features = ["console"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"
[package.metadata.wasm-pack.profile.release.wasm-bindgen]
debug-js-glue = true
demangle-name-section = true
dwarf-debug-info = false
omit-default-module-path = true

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/stem.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

View File

@@ -1,17 +1,15 @@
use nodarium_macros::include_definition_file; use nodarium_macros::nodarium_definition_file;
use nodarium_macros::nodarium_execute;
use nodarium_utils::{ use nodarium_utils::{
evaluate_float, evaluate_int, evaluate_vec3, evaluate_float, evaluate_int, evaluate_vec3,
geometry::{create_multiple_paths, wrap_multiple_paths}, geometry::{create_multiple_paths, wrap_multiple_paths},
log, reset_call_count, set_panic_hook, split_args, log, reset_call_count, split_args,
}; };
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); nodarium_definition_file!("src/input.json");
#[wasm_bindgen] #[nodarium_execute]
pub fn execute(input: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
set_panic_hook();
reset_call_count(); reset_call_count();
let args = split_args(input); let args = split_args(input);

View File

@@ -1,13 +0,0 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@@ -1,5 +1,5 @@
[package] [package]
name = "max-plantarium-triangle" name = "triangle"
version = "0.1.0" version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"] authors = ["Max Richter <jim-x@web.de>"]
edition = "2018" edition = "2018"
@@ -7,22 +7,6 @@ edition = "2018"
[lib] [lib]
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies] [dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" } nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" } nodarium_macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features", "build": "cargo build --target wasm32-unknown-unknown --release && mkdir -p pkg && cp ../../../../target/wasm32-unknown-unknown/release/triangle.wasm ./pkg/node.wasm",
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'" "dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
} }
} }

Some files were not shown because too many files have changed in this diff Show More