Compare commits
36 Commits
fbd82bbdfa
...
feat/zig-b
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b94159f8e | |||
| aa4d7f73a8 | |||
| 1efb94b09c | |||
|
|
5570d975f5 | ||
|
|
8c1ba2ee65 | ||
|
|
3e019e4e21 | ||
|
|
a58b19e935 | ||
|
|
6f5c5bb46e
|
||
|
7f2214f15c
|
|||
|
43ef563ae7
|
|||
|
|
714d01da94 | ||
|
|
92308fc43a | ||
|
|
5adf67ed52 | ||
|
|
f54cde734e | ||
| 70d8095869 | |||
|
|
2a90d5de3f | ||
|
d7e9e8b8de
|
|||
|
bdbaab25a4
|
|||
|
|
c7bfb0f05b | ||
|
|
d3a46af4c2 | ||
|
4c76c62a3e
|
|||
|
36cf9211d2
|
|||
|
97a2ffb683
|
|||
|
fffa8c7cdf
|
|||
| de799c2d55 | |||
| 24bef0460c | |||
|
93b64fc7dd
|
|||
|
64ac28f60c
|
|||
|
bd0c2eaacd
|
|||
|
8693c63d16
|
|||
|
1ea7d6629f
|
|||
|
617dfb0c9d
|
|||
|
8e5412c25c
|
|||
| e84c715f4c | |||
|
|
ecbcc814ed
|
||
|
|
be97387252
|
@@ -1,12 +1,14 @@
|
||||
{
|
||||
"$schema": "https://dprint.dev/schemas/v0.json",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 100,
|
||||
"typescript": {
|
||||
// https://dprint.dev/plugins/typescript/config/
|
||||
"quoteStyle": "preferSingle",
|
||||
"trailingCommas": "never"
|
||||
"trailingCommas": "never",
|
||||
},
|
||||
"json": {
|
||||
// https://dprint.dev/plugins/json/config/
|
||||
},
|
||||
"markdown": {
|
||||
},
|
||||
@@ -21,6 +23,9 @@
|
||||
"malva": {
|
||||
},
|
||||
"markup": {
|
||||
// https://dprint.dev/plugins/markup_fmt/config/
|
||||
"scriptIndent": true,
|
||||
"styleIndent": true,
|
||||
},
|
||||
"yaml": {
|
||||
},
|
||||
@@ -28,19 +33,24 @@
|
||||
},
|
||||
"exec": {
|
||||
"cwd": "${configDir}",
|
||||
|
||||
"commands": [{
|
||||
"command": "rustfmt --edition 2024",
|
||||
"command": "rustfmt",
|
||||
"exts": ["rs"],
|
||||
// add the config files for automatic cache invalidation when the rust version or rustfmt config changes
|
||||
"cacheKeyFiles": [
|
||||
"rustfmt.toml",
|
||||
"rust-toolchain.toml"
|
||||
]
|
||||
}]
|
||||
"rust-toolchain.toml",
|
||||
],
|
||||
}],
|
||||
},
|
||||
"excludes": [
|
||||
"**/node_modules",
|
||||
"**/*-lock.yaml"
|
||||
"**/build",
|
||||
"**/.svelte-kit",
|
||||
"**/package",
|
||||
"**/*-lock.yaml",
|
||||
"**/yaml.lock",
|
||||
"**/.DS_Store",
|
||||
],
|
||||
"plugins": [
|
||||
"https://plugins.dprint.dev/typescript-0.95.13.wasm",
|
||||
@@ -54,6 +64,7 @@
|
||||
"https://plugins.dprint.dev/g-plane/markup_fmt-v0.25.3.wasm",
|
||||
"https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.1.wasm",
|
||||
"https://plugins.dprint.dev/g-plane/pretty_graphql-v0.2.3.wasm",
|
||||
"https://plugins.dprint.dev/exec-0.6.0.json@a054130d458f124f9b5c91484833828950723a5af3f8ff2bd1523bd47b83b364"
|
||||
]
|
||||
"https://plugins.dprint.dev/exec-0.6.0.json@a054130d458f124f9b5c91484833828950723a5af3f8ff2bd1523bd47b83b364",
|
||||
"https://plugins.dprint.dev/biome-0.11.10.wasm",
|
||||
],
|
||||
}
|
||||
|
||||
367
Cargo.lock
generated
367
Cargo.lock
generated
@@ -1,176 +1,80 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "box"
|
||||
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 = "branch"
|
||||
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]]
|
||||
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]]
|
||||
name = "float"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"nodarium_macros",
|
||||
"nodarium_utils",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.27.0"
|
||||
version = "0.30.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9"
|
||||
checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9"
|
||||
|
||||
[[package]]
|
||||
name = "gravity"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"glam",
|
||||
"nodarium_macros",
|
||||
"nodarium_utils",
|
||||
"noise",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instance"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"nodarium_macros",
|
||||
"nodarium_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[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"
|
||||
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||
|
||||
[[package]]
|
||||
name = "math"
|
||||
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 = "max-plantarium-triangle"
|
||||
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 = "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",
|
||||
]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "nodarium_macros"
|
||||
@@ -180,7 +84,7 @@ dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 1.0.109",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -195,29 +99,19 @@ dependencies = [
|
||||
name = "nodarium_utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"glam",
|
||||
"noise",
|
||||
"noise 0.9.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodes-noise"
|
||||
name = "noise"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"glam",
|
||||
"nodarium_macros",
|
||||
"nodarium_utils",
|
||||
"noise",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
"web-sys",
|
||||
"noise 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -233,48 +127,35 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.18"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "output"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"glam",
|
||||
"nodarium_macros",
|
||||
"nodarium_utils",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.81"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
||||
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -307,103 +188,76 @@ dependencies = [
|
||||
name = "random"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"nodarium_macros",
|
||||
"nodarium_utils",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rotate"
|
||||
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]]
|
||||
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]]
|
||||
name = "serde"
|
||||
version = "1.0.198"
|
||||
version = "1.0.228"
|
||||
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 = [
|
||||
"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]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.198"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.116"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stem"
|
||||
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 = "syn"
|
||||
version = "1.0.109"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -411,119 +265,30 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
||||
name = "triangle"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
"nodarium_macros",
|
||||
"nodarium_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
name = "vec3"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
"nodarium_macros",
|
||||
"nodarium_utils",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.92"
|
||||
name = "zmij"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
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",
|
||||
]
|
||||
checksum = "94f63c051f4fe3c1509da62131a678643c5b6fbdc9273b2b79d4378ebda003d2"
|
||||
|
||||
@@ -6,7 +6,10 @@ members = [
|
||||
"packages/types",
|
||||
"packages/utils",
|
||||
]
|
||||
exclude = ["nodes/max/plantarium/.template"]
|
||||
exclude = [
|
||||
"nodes/max/plantarium/.template",
|
||||
"nodes/max/plantarium/zig"
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
@@ -2,10 +2,6 @@ FROM node:24-alpine
|
||||
|
||||
RUN apk add --no-cache --update curl rclone g++
|
||||
|
||||
RUN RUSTUP_URL="https://sh.rustup.rs" \
|
||||
&& curl --silent --show-error --location --fail --retry 3 --proto '=https' --tlsv1.2 --output /tmp/rustup-linux-install.sh $RUSTUP_URL \
|
||||
&& sh /tmp/rustup-linux-install.sh -y
|
||||
|
||||
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||
CARGO_HOME=/usr/local/cargo \
|
||||
PATH=/usr/local/cargo/bin:$PATH
|
||||
@@ -15,7 +11,5 @@ RUN curl --silent --show-error --location --fail --retry 3 \
|
||||
--output /tmp/rustup-init.sh https://sh.rustup.rs \
|
||||
&& sh /tmp/rustup-init.sh -y --no-modify-path --profile minimal \
|
||||
&& rm /tmp/rustup-init.sh \
|
||||
&& rustup default stable \
|
||||
&& rustup target add wasm32-unknown-unknown \
|
||||
&& cargo install wasm-pack \
|
||||
&& npm i -g pnpm
|
||||
|
||||
43
app/Dockerfile
Normal file
43
app/Dockerfile
Normal file
@@ -0,0 +1,43 @@
|
||||
FROM jimfx/nodes:latest AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json Cargo.lock Cargo.toml ./
|
||||
|
||||
COPY packages/ ./packages/
|
||||
COPY nodes/ ./nodes/
|
||||
COPY app/package.json ./app/
|
||||
|
||||
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store \
|
||||
--mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=/app/target \
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store \
|
||||
--mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=/app/target \
|
||||
pnpm build:nodes && \
|
||||
pnpm --filter @nodarium/app... build
|
||||
|
||||
FROM nginx:alpine AS runner
|
||||
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
|
||||
COPY <<EOF /etc/nginx/conf.d/app.conf
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /app;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files \$uri \$uri/ /index.html;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
COPY --from=builder /app/app/build /app
|
||||
|
||||
EXPOSE 80
|
||||
@@ -10,9 +10,9 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nodarium/registry": "link:../packages/registry",
|
||||
"@nodarium/ui": "link:../packages/ui",
|
||||
"@nodarium/utils": "link:../packages/utils",
|
||||
"@nodarium/registry": "workspace:*",
|
||||
"@nodarium/ui": "workspace:*",
|
||||
"@nodarium/utils": "workspace:*",
|
||||
"@sveltejs/kit": "^2.50.0",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@threlte/core": "8.3.1",
|
||||
@@ -22,12 +22,13 @@
|
||||
"idb": "^8.0.3",
|
||||
"jsondiffpatch": "^0.7.3",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"three": "^0.182.0"
|
||||
"three": "^0.182.0",
|
||||
"wabt": "^1.0.39"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/tabler": "^1.2.26",
|
||||
"@iconify/tailwind4": "^1.2.1",
|
||||
"@nodarium/types": "link:../packages/types",
|
||||
"@nodarium/types": "workspace:",
|
||||
"@sveltejs/adapter-static": "^3.0.10",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||
"@tsconfig/svelte": "^5.0.6",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { HTML } from "@threlte/extras";
|
||||
import { onMount } from "svelte";
|
||||
import type { NodeInstance, NodeId } from "@nodarium/types";
|
||||
import { getGraphManager, getGraphState } from "../graph-state.svelte";
|
||||
import type { NodeId, NodeInstance } from '@nodarium/types';
|
||||
import { HTML } from '@threlte/extras';
|
||||
import { onMount } from 'svelte';
|
||||
import { getGraphManager, getGraphState } from '../graph-state.svelte';
|
||||
|
||||
type Props = {
|
||||
onnode: (n: NodeInstance) => void;
|
||||
@@ -14,6 +14,7 @@
|
||||
const graphState = getGraphState();
|
||||
|
||||
let input: HTMLInputElement;
|
||||
let wrapper: HTMLDivElement;
|
||||
let value = $state<string>();
|
||||
let activeNodeId = $state<NodeId>();
|
||||
|
||||
@@ -22,10 +23,10 @@
|
||||
: graph.getNodeDefinitions();
|
||||
|
||||
function filterNodes() {
|
||||
return allNodes.filter((node) => node.id.includes(value ?? ""));
|
||||
return allNodes.filter((node) => node.id.includes(value ?? ''));
|
||||
}
|
||||
|
||||
const nodes = $derived(value === "" ? allNodes : filterNodes());
|
||||
const nodes = $derived(value === '' ? allNodes : filterNodes());
|
||||
$effect(() => {
|
||||
if (nodes) {
|
||||
if (activeNodeId === undefined) {
|
||||
@@ -39,38 +40,38 @@
|
||||
}
|
||||
});
|
||||
|
||||
function handleNodeCreation(nodeType: NodeInstance["type"]) {
|
||||
function handleNodeCreation(nodeType: NodeInstance['type']) {
|
||||
if (!graphState.addMenuPosition) return;
|
||||
onnode?.({
|
||||
id: -1,
|
||||
type: nodeType,
|
||||
position: [...graphState.addMenuPosition],
|
||||
props: {},
|
||||
state: {},
|
||||
state: {}
|
||||
});
|
||||
}
|
||||
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
event.stopImmediatePropagation();
|
||||
|
||||
if (event.key === "Escape") {
|
||||
if (event.key === 'Escape') {
|
||||
graphState.addMenuPosition = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowDown") {
|
||||
if (event.key === 'ArrowDown') {
|
||||
const index = nodes.findIndex((node) => node.id === activeNodeId);
|
||||
activeNodeId = nodes[(index + 1) % nodes.length].id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowUp") {
|
||||
if (event.key === 'ArrowUp') {
|
||||
const index = nodes.findIndex((node) => node.id === activeNodeId);
|
||||
activeNodeId = nodes[(index - 1 + nodes.length) % nodes.length].id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === "Enter") {
|
||||
if (event.key === 'Enter') {
|
||||
if (activeNodeId && graphState.addMenuPosition) {
|
||||
handleNodeCreation(activeNodeId);
|
||||
}
|
||||
@@ -81,6 +82,16 @@
|
||||
onMount(() => {
|
||||
input.disabled = false;
|
||||
setTimeout(() => input.focus(), 50);
|
||||
|
||||
const rect = wrapper.getBoundingClientRect();
|
||||
const deltaY = rect.bottom - window.innerHeight;
|
||||
const deltaX = rect.right - window.innerWidth;
|
||||
if (deltaY > 0) {
|
||||
wrapper.style.marginTop = `-${deltaY + 30}px`;
|
||||
}
|
||||
if (deltaX > 0) {
|
||||
wrapper.style.marginLeft = `-${deltaX + 30}px`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -89,7 +100,7 @@
|
||||
position.z={graphState.addMenuPosition?.[1]}
|
||||
transform={false}
|
||||
>
|
||||
<div class="add-menu-wrapper">
|
||||
<div class="add-menu-wrapper" bind:this={wrapper}>
|
||||
<div class="header">
|
||||
<input
|
||||
id="add-menu"
|
||||
@@ -112,7 +123,7 @@
|
||||
tabindex="0"
|
||||
aria-selected={node.id === activeNodeId}
|
||||
onkeydown={(event) => {
|
||||
if (event.key === "Enter") {
|
||||
if (event.key === 'Enter') {
|
||||
handleNodeCreation(node.id);
|
||||
}
|
||||
}}
|
||||
@@ -125,7 +136,7 @@
|
||||
activeNodeId = node.id;
|
||||
}}
|
||||
>
|
||||
{node.id.split("/").at(-1)}
|
||||
{node.id.split('/').at(-1)}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -167,6 +178,8 @@
|
||||
min-height: none;
|
||||
width: 100%;
|
||||
color: var(--text-color);
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.result {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Box } from '@nodarium/types';
|
||||
import type { Color } from 'three';
|
||||
import { Vector3 } from 'three/src/math/Vector3.js';
|
||||
import Component from './Debug.svelte';
|
||||
import { lines, points, rects } from './store';
|
||||
@@ -11,7 +12,6 @@ export function debugPosition(x: number, y: number) {
|
||||
}
|
||||
|
||||
export function debugRect(rect: Box) {
|
||||
console.log(rect);
|
||||
rects.update((r) => {
|
||||
r.push(rect);
|
||||
return r;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import throttle from '$lib/helpers/throttle';
|
||||
import { RemoteNodeRegistry } from '@nodarium/registry';
|
||||
import type {
|
||||
Edge,
|
||||
Graph,
|
||||
@@ -18,6 +19,8 @@ import { HistoryManager } from './history-manager';
|
||||
const logger = createLogger('graph-manager');
|
||||
logger.mute();
|
||||
|
||||
const remoteRegistry = new RemoteNodeRegistry('');
|
||||
|
||||
const clone = 'structuredClone' in self
|
||||
? self.structuredClone
|
||||
: (args: any) => JSON.parse(JSON.stringify(args));
|
||||
@@ -109,6 +112,7 @@ export class GraphManager extends EventEmitter<{
|
||||
const serialized = {
|
||||
id: this.graph.id,
|
||||
settings: $state.snapshot(this.settings),
|
||||
meta: $state.snapshot(this.graph.meta),
|
||||
nodes,
|
||||
edges
|
||||
};
|
||||
@@ -172,7 +176,9 @@ export class GraphManager extends EventEmitter<{
|
||||
return areSocketsCompatible(edgeOutputSocketType, accepted);
|
||||
});
|
||||
|
||||
const bestOutputIdx = draggedOutputs.findIndex(outputType => areSocketsCompatible(outputType, targetAcceptedTypes));
|
||||
const bestOutputIdx = draggedOutputs.findIndex(outputType =>
|
||||
areSocketsCompatible(outputType, targetAcceptedTypes)
|
||||
);
|
||||
|
||||
if (!bestInputEntry || bestOutputIdx === -1) {
|
||||
logger.error('Could not find compatible sockets for drop');
|
||||
@@ -273,7 +279,7 @@ export class GraphManager extends EventEmitter<{
|
||||
})
|
||||
);
|
||||
|
||||
const edges = graph.edges.map((edge) => {
|
||||
this.edges = graph.edges.map((edge) => {
|
||||
const from = nodes.get(edge[0]);
|
||||
const to = nodes.get(edge[2]);
|
||||
if (!from || !to) {
|
||||
@@ -286,8 +292,6 @@ export class GraphManager extends EventEmitter<{
|
||||
return [from, edge[1], to, edge[3]] as Edge;
|
||||
});
|
||||
|
||||
this.edges = [...edges];
|
||||
|
||||
this.nodes.clear();
|
||||
for (const [id, node] of nodes) {
|
||||
this.nodes.set(id, node);
|
||||
@@ -304,11 +308,26 @@ export class GraphManager extends EventEmitter<{
|
||||
this.status = 'loading';
|
||||
this.id = graph.id;
|
||||
|
||||
logger.info('loading graph', $state.snapshot(graph));
|
||||
logger.info('loading graph', { nodes: graph.nodes, edges: graph.edges, id: graph.id });
|
||||
|
||||
const nodeIds = Array.from(new Set([...graph.nodes.map((n) => n.type)]));
|
||||
await this.registry.load(nodeIds);
|
||||
|
||||
// Fetch all nodes from all collections of the loaded nodes
|
||||
const allCollections = new Set<`${string}/${string}`>();
|
||||
for (const id of nodeIds) {
|
||||
const [user, collection] = id.split('/');
|
||||
allCollections.add(`${user}/${collection}`);
|
||||
}
|
||||
for (const collection of allCollections) {
|
||||
remoteRegistry
|
||||
.fetchCollection(collection)
|
||||
.then((collection: { nodes: { id: NodeId }[] }) => {
|
||||
const ids = collection.nodes.map((n) => n.id);
|
||||
return this.registry.load(ids);
|
||||
});
|
||||
}
|
||||
|
||||
logger.info('loaded node types', this.registry.getAllNodes());
|
||||
|
||||
for (const node of this.graph.nodes) {
|
||||
@@ -644,6 +663,13 @@ export class GraphManager extends EventEmitter<{
|
||||
if (this.currentUndoGroup) return;
|
||||
const state = this.serialize();
|
||||
this.history.save(state);
|
||||
|
||||
// This is some stupid race condition where the graph-manager emits a save event
|
||||
// when the graph is not fully loaded
|
||||
if (this.nodes.size === 0 && this.edges.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('save', state);
|
||||
logger.log('saving graphs', state);
|
||||
}
|
||||
|
||||
@@ -58,11 +58,13 @@ export class GraphState {
|
||||
|
||||
wrapper = $state<HTMLDivElement>(null!);
|
||||
rect: DOMRect = $derived(
|
||||
(this.wrapper && this.width && this.height) ? this.wrapper.getBoundingClientRect() : new DOMRect(0, 0, 0, 0)
|
||||
(this.wrapper && this.width && this.height)
|
||||
? this.wrapper.getBoundingClientRect()
|
||||
: new DOMRect(0, 0, 0, 0)
|
||||
);
|
||||
|
||||
camera = $state<OrthographicCamera>(null!);
|
||||
cameraPosition: [number, number, number] = $state([0, 0, 100]);
|
||||
cameraPosition: [number, number, number] = $state([140, 100, 3.5]);
|
||||
|
||||
clipboard: null | {
|
||||
nodes: NodeInstance[];
|
||||
@@ -333,4 +335,8 @@ export class GraphState {
|
||||
&& node.position[1] < this.cameraBounds[3]
|
||||
);
|
||||
}
|
||||
|
||||
openNodePalette() {
|
||||
this.addMenuPosition = [this.mousePosition[0], this.mousePosition[1]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<script lang="ts">
|
||||
import type { Edge, NodeInstance } from "@nodarium/types";
|
||||
import { createKeyMap } from "../../helpers/createKeyMap";
|
||||
import AddMenu from "../components/AddMenu.svelte";
|
||||
import Background from "../background/Background.svelte";
|
||||
import BoxSelection from "../components/BoxSelection.svelte";
|
||||
import EdgeEl from "../edges/Edge.svelte";
|
||||
import NodeEl from "../node/Node.svelte";
|
||||
import Camera from "../components/Camera.svelte";
|
||||
import { Canvas } from "@threlte/core";
|
||||
import HelpView from "../components/HelpView.svelte";
|
||||
import { getGraphManager, getGraphState } from "../graph-state.svelte";
|
||||
import { HTML } from "@threlte/extras";
|
||||
import { maxZoom, minZoom } from "./constants";
|
||||
import Debug from "../debug/Debug.svelte";
|
||||
import { FileDropEventManager } from "./drop.events";
|
||||
import { MouseEventManager } from "./mouse.events";
|
||||
import type { Edge, NodeInstance } from '@nodarium/types';
|
||||
import { Canvas } from '@threlte/core';
|
||||
import { HTML } from '@threlte/extras';
|
||||
import { createKeyMap } from '../../helpers/createKeyMap';
|
||||
import Background from '../background/Background.svelte';
|
||||
import AddMenu from '../components/AddMenu.svelte';
|
||||
import BoxSelection from '../components/BoxSelection.svelte';
|
||||
import Camera from '../components/Camera.svelte';
|
||||
import HelpView from '../components/HelpView.svelte';
|
||||
import Debug from '../debug/Debug.svelte';
|
||||
import EdgeEl from '../edges/Edge.svelte';
|
||||
import { getGraphManager, getGraphState } from '../graph-state.svelte';
|
||||
import NodeEl from '../node/Node.svelte';
|
||||
import { maxZoom, minZoom } from './constants';
|
||||
import { FileDropEventManager } from './drop.events';
|
||||
import { MouseEventManager } from './mouse.events';
|
||||
|
||||
const {
|
||||
keymap,
|
||||
keymap
|
||||
}: {
|
||||
keymap: ReturnType<typeof createKeyMap>;
|
||||
} = $props();
|
||||
@@ -45,19 +45,18 @@
|
||||
const newNode = graph.createNode({
|
||||
type: node.type,
|
||||
position: node.position,
|
||||
props: node.props,
|
||||
props: node.props
|
||||
});
|
||||
if (!newNode) return;
|
||||
|
||||
if (graphState.activeSocket) {
|
||||
if (typeof graphState.activeSocket.index === "number") {
|
||||
const socketType =
|
||||
graphState.activeSocket.node.state?.type?.outputs?.[
|
||||
if (typeof graphState.activeSocket.index === 'number') {
|
||||
const socketType = graphState.activeSocket.node.state?.type?.outputs?.[
|
||||
graphState.activeSocket.index
|
||||
];
|
||||
|
||||
const input = Object.entries(newNode?.state?.type?.inputs || {}).find(
|
||||
(inp) => inp[1].type === socketType,
|
||||
(inp) => inp[1].type === socketType
|
||||
);
|
||||
|
||||
if (input) {
|
||||
@@ -65,12 +64,11 @@
|
||||
graphState.activeSocket.node,
|
||||
graphState.activeSocket.index,
|
||||
newNode,
|
||||
input[0],
|
||||
input[0]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const socketType =
|
||||
graphState.activeSocket.node.state?.type?.inputs?.[
|
||||
const socketType = graphState.activeSocket.node.state?.type?.inputs?.[
|
||||
graphState.activeSocket.index
|
||||
];
|
||||
|
||||
@@ -85,7 +83,7 @@
|
||||
newNode,
|
||||
output.indexOf(output),
|
||||
graphState.activeSocket.node,
|
||||
graphState.activeSocket.index,
|
||||
graphState.activeSocket.index
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -97,14 +95,15 @@
|
||||
</script>
|
||||
|
||||
<svelte:window
|
||||
onmousemove={(ev) => mouseEvents.handleMouseMove(ev)}
|
||||
onmouseup={(ev) => mouseEvents.handleMouseUp(ev)}
|
||||
onmousemove={(ev) => mouseEvents.handleWindowMouseMove(ev)}
|
||||
onmouseup={(ev) => mouseEvents.handleWindowMouseUp(ev)}
|
||||
/>
|
||||
|
||||
<div
|
||||
onwheel={(ev) => mouseEvents.handleMouseScroll(ev)}
|
||||
bind:this={graphState.wrapper}
|
||||
class="graph-wrapper"
|
||||
style="height: 100%"
|
||||
class:is-panning={graphState.isPanning}
|
||||
class:is-hovering={graphState.hoveredNodeId !== -1}
|
||||
aria-label="Graph"
|
||||
@@ -114,6 +113,7 @@
|
||||
bind:clientHeight={graphState.height}
|
||||
onkeydown={(ev) => keymap.handleKeyboardEvent(ev)}
|
||||
onmousedown={(ev) => mouseEvents.handleMouseDown(ev)}
|
||||
oncontextmenu={(ev) => mouseEvents.handleContextMenu(ev)}
|
||||
{...fileDropEvents.getEventListenerProps()}
|
||||
>
|
||||
<input
|
||||
@@ -146,20 +146,18 @@
|
||||
<BoxSelection
|
||||
cameraPosition={graphState.cameraPosition}
|
||||
p1={{
|
||||
x:
|
||||
graphState.cameraPosition[0] +
|
||||
(graphState.mouseDown[0] - graphState.width / 2) /
|
||||
graphState.cameraPosition[2],
|
||||
y:
|
||||
graphState.cameraPosition[1] +
|
||||
(graphState.mouseDown[1] - graphState.height / 2) /
|
||||
graphState.cameraPosition[2],
|
||||
x: graphState.cameraPosition[0]
|
||||
+ (graphState.mouseDown[0] - graphState.width / 2)
|
||||
/ graphState.cameraPosition[2],
|
||||
y: graphState.cameraPosition[1]
|
||||
+ (graphState.mouseDown[1] - graphState.height / 2)
|
||||
/ graphState.cameraPosition[2]
|
||||
}}
|
||||
p2={{ x: graphState.mousePosition[0], y: graphState.mousePosition[1] }}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if graph.status === "idle"}
|
||||
{#if graph.status === 'idle'}
|
||||
{#if graphState.addMenuPosition}
|
||||
<AddMenu onnode={handleNodeCreation} />
|
||||
{/if}
|
||||
@@ -206,9 +204,9 @@
|
||||
{/each}
|
||||
</div>
|
||||
</HTML>
|
||||
{:else if graph.status === "loading"}
|
||||
{:else if graph.status === 'loading'}
|
||||
<span>Loading</span>
|
||||
{:else if graph.status === "error"}
|
||||
{:else if graph.status === 'error'}
|
||||
<span>Error</span>
|
||||
{/if}
|
||||
</Canvas>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
import { setupKeymaps } from "../keymaps";
|
||||
|
||||
type Props = {
|
||||
graph: Graph;
|
||||
graph?: Graph;
|
||||
registry: NodeRegistry;
|
||||
|
||||
settings?: Record<string, any>;
|
||||
@@ -70,12 +70,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (settingTypes && settings) {
|
||||
manager.setSettings(settings);
|
||||
}
|
||||
});
|
||||
|
||||
manager.on("settings", (_settings) => {
|
||||
settingTypes = { ...settingTypes, ..._settings.types };
|
||||
settings = _settings.values;
|
||||
@@ -85,7 +79,11 @@
|
||||
|
||||
manager.on("save", (save) => onsave?.(save));
|
||||
|
||||
$effect(() => {
|
||||
if (graph) {
|
||||
manager.load(graph);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<GraphEl {keymap} />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { animate, lerp } from '$lib/helpers';
|
||||
import { type NodeInstance } from '@nodarium/types';
|
||||
import type { GraphManager } from '../graph-manager.svelte';
|
||||
import type { GraphState } from '../graph-state.svelte';
|
||||
import { type GraphState } from '../graph-state.svelte';
|
||||
import { snapToGrid as snapPointToGrid } from '../helpers';
|
||||
import { maxZoom, minZoom, zoomSpeed } from './constants';
|
||||
import { EdgeInteractionManager } from './edge.events';
|
||||
@@ -16,7 +16,7 @@ export class MouseEventManager {
|
||||
this.edgeInteractionManager = new EdgeInteractionManager(graph, state);
|
||||
}
|
||||
|
||||
handleMouseUp(event: MouseEvent) {
|
||||
handleWindowMouseUp(event: MouseEvent) {
|
||||
this.edgeInteractionManager.handleMouseUp();
|
||||
this.state.isPanning = false;
|
||||
if (!this.state.mouseDown) return;
|
||||
@@ -151,7 +151,19 @@ export class MouseEventManager {
|
||||
this.state.addMenuPosition = null;
|
||||
}
|
||||
|
||||
handleContextMenu(event: MouseEvent) {
|
||||
if (!this.state.addMenuPosition) {
|
||||
event.preventDefault();
|
||||
this.state.openNodePalette();
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseDown(event: MouseEvent) {
|
||||
// Right click
|
||||
if (event.button === 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.state.mouseDown) return;
|
||||
this.state.edgeEndPosition = null;
|
||||
|
||||
@@ -229,7 +241,7 @@ export class MouseEventManager {
|
||||
this.state.edgeEndPosition = null;
|
||||
}
|
||||
|
||||
handleMouseMove(event: MouseEvent) {
|
||||
handleWindowMouseMove(event: MouseEvent) {
|
||||
let mx = event.clientX - this.state.rect.x;
|
||||
let my = event.clientY - this.state.rect.y;
|
||||
|
||||
|
||||
@@ -59,9 +59,7 @@ export function setupKeymaps(keymap: Keymap, graph: GraphManager, graphState: Gr
|
||||
key: 'A',
|
||||
shift: true,
|
||||
description: 'Add new Node',
|
||||
callback: () => {
|
||||
graphState.addMenuPosition = [graphState.mousePosition[0], graphState.mousePosition[1]];
|
||||
}
|
||||
callback: () => graphState.openNodePalette()
|
||||
});
|
||||
|
||||
keymap.addShortcut({
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { createWasmWrapper } from "@nodarium/utils";
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
import { createWasmWrapper } from '@nodarium/utils';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
export async function getWasm(id: `${string}/${string}/${string}`) {
|
||||
const filePath = path.resolve(`../nodes/${id}/pkg/index_bg.wasm`);
|
||||
const filePath = path.resolve(`./static/nodes/${id}`);
|
||||
|
||||
try {
|
||||
await fs.access(filePath);
|
||||
@@ -36,12 +36,12 @@ export async function getNode(id: `${string}/${string}/${string}`) {
|
||||
}
|
||||
|
||||
export async function getCollectionNodes(userId: `${string}/${string}`) {
|
||||
const nodes = await fs.readdir(path.resolve(`../nodes/${userId}`));
|
||||
const nodes = await fs.readdir(path.resolve(`./static/nodes/${userId}`));
|
||||
return nodes
|
||||
.filter((n) => n !== "pkg" && n !== ".template")
|
||||
.filter((n) => n !== 'pkg' && n !== '.template')
|
||||
.map((n) => {
|
||||
return {
|
||||
id: `${userId}/${n}`,
|
||||
id: `${userId}/${n}`
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -50,20 +50,20 @@ export async function getCollection(userId: `${string}/${string}`) {
|
||||
const nodes = await getCollectionNodes(userId);
|
||||
return {
|
||||
id: userId,
|
||||
nodes,
|
||||
nodes
|
||||
};
|
||||
}
|
||||
|
||||
export async function getUserCollections(userId: string) {
|
||||
const collections = await fs.readdir(path.resolve(`../nodes/${userId}`));
|
||||
const collections = await fs.readdir(path.resolve(`./static/nodes/${userId}`));
|
||||
return Promise.all(
|
||||
collections.map(async (n) => {
|
||||
const nodes = await getCollectionNodes(`${userId}/${n}`);
|
||||
return {
|
||||
id: `${userId}/${n}`,
|
||||
nodes,
|
||||
nodes
|
||||
};
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -71,20 +71,20 @@ export async function getUser(userId: string) {
|
||||
const collections = await getUserCollections(userId);
|
||||
return {
|
||||
id: userId,
|
||||
collections,
|
||||
collections
|
||||
};
|
||||
}
|
||||
|
||||
export async function getUsers() {
|
||||
const nodes = await fs.readdir(path.resolve("../nodes"));
|
||||
const nodes = await fs.readdir(path.resolve('./static/nodes'));
|
||||
const users = await Promise.all(
|
||||
nodes.map(async (n) => {
|
||||
const collections = await getUserCollections(n);
|
||||
return {
|
||||
id: n,
|
||||
collections,
|
||||
collections
|
||||
};
|
||||
}),
|
||||
})
|
||||
);
|
||||
return users;
|
||||
}
|
||||
|
||||
108
app/src/lib/project-manager/ProjectManager.svelte
Normal file
108
app/src/lib/project-manager/ProjectManager.svelte
Normal file
@@ -0,0 +1,108 @@
|
||||
<script lang="ts">
|
||||
import type { Graph } from "$lib/types";
|
||||
import { defaultPlant, plant, lottaFaces } from "$lib/graph-templates";
|
||||
import type { ProjectManager } from "./project-manager.svelte";
|
||||
|
||||
const { projectManager } = $props<{ projectManager: ProjectManager }>();
|
||||
|
||||
let showNewProject = $state(false);
|
||||
let newProjectName = $state("");
|
||||
let selectedTemplate = $state("defaultPlant");
|
||||
|
||||
const templates = [
|
||||
{
|
||||
name: "Default Plant",
|
||||
value: "defaultPlant",
|
||||
graph: defaultPlant as unknown as Graph,
|
||||
},
|
||||
{ name: "Plant", value: "plant", graph: plant as unknown as Graph },
|
||||
{
|
||||
name: "Lotta Faces",
|
||||
value: "lottaFaces",
|
||||
graph: lottaFaces as unknown as Graph,
|
||||
},
|
||||
];
|
||||
|
||||
function handleCreate() {
|
||||
const template =
|
||||
templates.find((t) => t.value === selectedTemplate) || templates[0];
|
||||
projectManager.handleCreateProject(template.graph, newProjectName);
|
||||
newProjectName = "";
|
||||
showNewProject = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<header
|
||||
class="flex justify-between px-4 h-[70px] border-b-1 border-[var(--outline)] items-center"
|
||||
>
|
||||
<h3>Project</h3>
|
||||
<button
|
||||
class="px-3 py-1 bg-[var(--layer-0)] rounded"
|
||||
onclick={() => (showNewProject = !showNewProject)}
|
||||
>
|
||||
New
|
||||
</button>
|
||||
</header>
|
||||
|
||||
{#if showNewProject}
|
||||
<div class="flex flex-col px-4 py-3 border-b-1 border-[var(--outline)] gap-2">
|
||||
<input
|
||||
type="text"
|
||||
bind:value={newProjectName}
|
||||
placeholder="Project name"
|
||||
class="w-full px-2 py-2 bg-gray-800 border border-gray-700 rounded"
|
||||
onkeydown={(e) => e.key === "Enter" && handleCreate()}
|
||||
/>
|
||||
<select
|
||||
bind:value={selectedTemplate}
|
||||
class="w-full px-2 py-2 bg-gray-800 border border-gray-700 rounded"
|
||||
>
|
||||
{#each templates as template}
|
||||
<option value={template.value}>{template.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<button
|
||||
class="cursor-pointer self-end px-3 py-1 bg-blue-600 rounded"
|
||||
onclick={() => handleCreate()}
|
||||
>
|
||||
Create
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="p-4 text-white min-h-screen">
|
||||
{#if projectManager.loading}
|
||||
<p>Loading...</p>
|
||||
{/if}
|
||||
|
||||
<ul class="space-y-2">
|
||||
{#each projectManager.projects as project (project.id)}
|
||||
<li>
|
||||
<div
|
||||
class="w-full text-left px-3 py-2 rounded cursor-pointer {projectManager
|
||||
.activeProjectId.value === project.id
|
||||
? 'bg-blue-600'
|
||||
: 'bg-gray-800 hover:bg-gray-700'}"
|
||||
onclick={() => projectManager.handleSelectProject(project.id!)}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onkeydown={(e) =>
|
||||
e.key === "Enter" &&
|
||||
projectManager.handleSelectProject(project.id!)}
|
||||
>
|
||||
<div class="flex justify-between items-center">
|
||||
<span>{project.meta?.title || "Untitled"}</span>
|
||||
<button
|
||||
class="text-red-400 hover:text-red-300"
|
||||
onclick={() => {
|
||||
projectManager.handleDeleteProject(project.id!);
|
||||
}}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
52
app/src/lib/project-manager/project-database.svelte.ts
Normal file
52
app/src/lib/project-manager/project-database.svelte.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { Graph } from '@nodarium/types';
|
||||
import { type IDBPDatabase, openDB } from 'idb';
|
||||
|
||||
export interface GraphDatabase {
|
||||
projects: Graph;
|
||||
}
|
||||
|
||||
const DB_NAME = 'nodarium-graphs';
|
||||
const DB_VERSION = 1;
|
||||
const STORE_NAME = 'graphs';
|
||||
|
||||
let dbPromise: Promise<IDBPDatabase<GraphDatabase>> | null = null;
|
||||
|
||||
export function getDB() {
|
||||
if (!dbPromise) {
|
||||
dbPromise = openDB<GraphDatabase>(DB_NAME, DB_VERSION, {
|
||||
upgrade(db) {
|
||||
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
||||
db.createObjectStore(STORE_NAME, { keyPath: 'id' });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return dbPromise;
|
||||
}
|
||||
|
||||
export async function getGraph(id: number): Promise<Graph | undefined> {
|
||||
const db = await getDB();
|
||||
return db.get(STORE_NAME, id);
|
||||
}
|
||||
|
||||
export async function saveGraph(graph: Graph): Promise<Graph> {
|
||||
const db = await getDB();
|
||||
graph.meta = { ...graph.meta, lastModified: new Date().toISOString() };
|
||||
await db.put(STORE_NAME, graph);
|
||||
return graph;
|
||||
}
|
||||
|
||||
export async function deleteGraph(id: number): Promise<void> {
|
||||
const db = await getDB();
|
||||
await db.delete(STORE_NAME, id);
|
||||
}
|
||||
|
||||
export async function getGraphs(): Promise<Graph[]> {
|
||||
const db = await getDB();
|
||||
return db.getAll(STORE_NAME);
|
||||
}
|
||||
|
||||
export async function clear(): Promise<void> {
|
||||
const db = await getDB();
|
||||
return db.clear(STORE_NAME);
|
||||
}
|
||||
85
app/src/lib/project-manager/project-manager.svelte.ts
Normal file
85
app/src/lib/project-manager/project-manager.svelte.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import * as templates from '$lib/graph-templates';
|
||||
import { localState } from '$lib/helpers/localState.svelte';
|
||||
import type { Graph } from '@nodarium/types';
|
||||
import * as db from './project-database.svelte';
|
||||
|
||||
export class ProjectManager {
|
||||
public graph = $state<Graph>();
|
||||
private projects = $state<Graph[]>([]);
|
||||
private activeProjectId = localState<number | undefined>(
|
||||
'node.activeProjectId',
|
||||
undefined
|
||||
);
|
||||
public readonly loading = $derived(this.graph?.id !== this.activeProjectId.value);
|
||||
|
||||
constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
async saveGraph(g: Graph) {
|
||||
db.saveGraph(g);
|
||||
}
|
||||
|
||||
private async init() {
|
||||
await db.getDB();
|
||||
this.projects = await db.getGraphs();
|
||||
|
||||
if (this.activeProjectId.value !== undefined) {
|
||||
let loadedGraph = await db.getGraph(this.activeProjectId.value);
|
||||
if (loadedGraph) {
|
||||
this.graph = loadedGraph;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.graph) {
|
||||
if (this.projects?.length && this.projects[0]?.id !== undefined) {
|
||||
this.graph = this.projects[0];
|
||||
this.activeProjectId.value = this.graph.id;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.graph) {
|
||||
this.handleCreateProject();
|
||||
}
|
||||
}
|
||||
|
||||
public handleCreateProject(
|
||||
g: Graph = templates.defaultPlant as unknown as Graph,
|
||||
title: string = 'New Project'
|
||||
) {
|
||||
let id = g?.id || 0;
|
||||
while (this.projects.find((p) => p.id === id)) {
|
||||
id++;
|
||||
}
|
||||
|
||||
g.id = id;
|
||||
if (!g.meta) g.meta = {};
|
||||
if (!g.meta.title) g.meta.title = title;
|
||||
|
||||
db.saveGraph(g);
|
||||
this.projects = [...this.projects, g];
|
||||
this.handleSelectProject(id);
|
||||
}
|
||||
|
||||
public async handleDeleteProject(projectId: number) {
|
||||
await db.deleteGraph(projectId);
|
||||
if (this.projects.length === 1) {
|
||||
this.graph = undefined;
|
||||
this.projects = [];
|
||||
} else {
|
||||
this.projects = this.projects.filter((p) => p.id !== projectId);
|
||||
const id = this.projects[0].id;
|
||||
if (id !== undefined) {
|
||||
this.handleSelectProject(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async handleSelectProject(id: number) {
|
||||
if (this.activeProjectId.value !== id) {
|
||||
const project = await db.getGraph(id);
|
||||
this.graph = project;
|
||||
this.activeProjectId.value = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,13 +92,6 @@
|
||||
geo.attributes.position.array[i + 2],
|
||||
] as Vector3Tuple;
|
||||
}
|
||||
|
||||
// $effect(() => {
|
||||
// console.log({
|
||||
// geometries: $state.snapshot(geometries),
|
||||
// indices: appSettings.value.debug.showIndices,
|
||||
// });
|
||||
// });
|
||||
</script>
|
||||
|
||||
<Camera {center} {centerCamera} />
|
||||
|
||||
@@ -95,7 +95,8 @@
|
||||
<SmallPerformanceViewer {fps} store={perf} />
|
||||
{/if}
|
||||
|
||||
<Canvas>
|
||||
<div style="height: 100%">
|
||||
<Canvas>
|
||||
<Scene
|
||||
bind:this={sceneComponent}
|
||||
{lines}
|
||||
@@ -103,4 +104,5 @@
|
||||
bind:scene
|
||||
bind:fps
|
||||
/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</div>
|
||||
|
||||
@@ -244,13 +244,14 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
|
||||
}
|
||||
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);
|
||||
a = performance.now();
|
||||
results[node.id] = node_type.execute(encoded_inputs);
|
||||
log.log("Executed", node.type, node.id)
|
||||
b = performance.now();
|
||||
|
||||
if (this.cache) {
|
||||
if (this.cache && node.id !== outputNode.id) {
|
||||
this.cache.set(inputHash, results[node.id]);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,4 @@
|
||||
align-items: center;
|
||||
padding-left: 1em;
|
||||
}
|
||||
h3 {
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { Integer } from "@nodarium/ui";
|
||||
import { writable } from "svelte/store";
|
||||
import { humanizeDuration } from "$lib/helpers";
|
||||
import Monitor from "$lib/performance/Monitor.svelte";
|
||||
import { localState } from "$lib/helpers/localState.svelte";
|
||||
import { humanizeDuration } from '$lib/helpers';
|
||||
import { localState } from '$lib/helpers/localState.svelte';
|
||||
import Monitor from '$lib/performance/Monitor.svelte';
|
||||
import { Number } from '@nodarium/ui';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
function calculateStandardDeviation(array: number[]) {
|
||||
const n = array.length;
|
||||
const mean = array.reduce((a, b) => a + b) / n;
|
||||
return Math.sqrt(
|
||||
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 = {
|
||||
@@ -25,21 +25,21 @@
|
||||
const { run }: Props = $props();
|
||||
|
||||
let isRunning = $state(false);
|
||||
let amount = localState<number>("nodes.benchmark.samples", 500);
|
||||
let amount = localState<number>('nodes.benchmark.samples', 500);
|
||||
let samples = $state(0);
|
||||
let warmUp = writable(0);
|
||||
let warmUpAmount = 10;
|
||||
let status = "";
|
||||
let status = '';
|
||||
|
||||
const copyContent = async (text?: string | number) => {
|
||||
if (!text) return;
|
||||
if (typeof text !== "string") {
|
||||
if (typeof text !== 'string') {
|
||||
text = (Math.floor(text * 100) / 100).toString();
|
||||
}
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (err) {
|
||||
console.error("Failed to copy: ", err);
|
||||
console.error('Failed to copy: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
stdev: calculateStandardDeviation(results),
|
||||
samples: results,
|
||||
duration: performance.now() - a,
|
||||
avg: results.reduce((a, b) => a + b) / results.length,
|
||||
avg: results.reduce((a, b) => a + b) / results.length
|
||||
};
|
||||
}
|
||||
</script>
|
||||
@@ -90,42 +90,43 @@
|
||||
<label for="bench-avg">Average </label>
|
||||
<button
|
||||
id="bench-avg"
|
||||
onkeydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)}
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.avg)}
|
||||
>{Math.floor(result.avg * 100) / 100}</button
|
||||
>
|
||||
{Math.floor(result.avg * 100) / 100}
|
||||
</button>
|
||||
<i
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onkeydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.avg)}>(click to copy)</i
|
||||
>
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.avg)}
|
||||
>(click to copy)</i>
|
||||
<label for="bench-stdev">Standard Deviation σ</label>
|
||||
<button id="bench-stdev" onclick={() => copyContent(result?.stdev)}
|
||||
>{Math.floor(result.stdev * 100) / 100}</button
|
||||
>
|
||||
<button id="bench-stdev" onclick={() => copyContent(result?.stdev)}>
|
||||
{Math.floor(result.stdev * 100) / 100}
|
||||
</button>
|
||||
<i
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onkeydown={(ev) => ev.key === "Enter" && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.stdev + "")}>(click to copy)</i
|
||||
>
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.stdev + '')}
|
||||
>(click to copy)</i>
|
||||
<div>
|
||||
<button onclick={() => (isRunning = false)}>reset</button>
|
||||
</div>
|
||||
{:else if isRunning}
|
||||
<p>WarmUp ({$warmUp}/{warmUpAmount})</p>
|
||||
<progress value={$warmUp} max={warmUpAmount}
|
||||
>{Math.floor(($warmUp / warmUpAmount) * 100)}%</progress
|
||||
>
|
||||
<progress value={$warmUp} max={warmUpAmount}>
|
||||
{Math.floor(($warmUp / warmUpAmount) * 100)}%
|
||||
</progress>
|
||||
<p>Progress ({samples}/{amount.value})</p>
|
||||
<progress value={samples} max={amount.value}
|
||||
>{Math.floor((samples / amount.value) * 100)}%</progress
|
||||
>
|
||||
<progress value={samples} max={amount.value}>
|
||||
{Math.floor((samples / amount.value) * 100)}%
|
||||
</progress>
|
||||
{:else}
|
||||
<label for="bench-samples">Samples</label>
|
||||
<Integer id="bench-sample" bind:value={amount.value} max={1000} />
|
||||
<button onclick={benchmark} disabled={isRunning}> start </button>
|
||||
<Number id="bench-sample" bind:value={amount.value} max={1000} />
|
||||
<button onclick={benchmark} disabled={isRunning}>start</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Graph } from "$lib/types";
|
||||
|
||||
const { graph }: { graph: Graph } = $props();
|
||||
const { graph }: { graph?: Graph } = $props();
|
||||
|
||||
function convert(g: Graph): string {
|
||||
return JSON.stringify(
|
||||
@@ -16,5 +16,5 @@
|
||||
</script>
|
||||
|
||||
<pre>
|
||||
{convert(graph)}
|
||||
{graph ? convert(graph) : 'No graph loaded'}
|
||||
</pre>
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
import BenchmarkPanel from "$lib/sidebar/panels/BenchmarkPanel.svelte";
|
||||
import { debounceAsyncFunction } from "$lib/helpers";
|
||||
import GraphSource from "$lib/sidebar/panels/GraphSource.svelte";
|
||||
import { ProjectManager } from "$lib/project-manager/project-manager.svelte";
|
||||
import ProjectManagerEl from "$lib/project-manager/ProjectManager.svelte";
|
||||
|
||||
let performanceStore = createPerformanceStore();
|
||||
|
||||
@@ -37,6 +39,7 @@
|
||||
const runtimeCache = new MemoryRuntimeCache();
|
||||
const memoryRuntime = new MemoryRuntimeExecutor(nodeRegistry, runtimeCache);
|
||||
memoryRuntime.perf = performanceStore;
|
||||
const pm = new ProjectManager();
|
||||
|
||||
const runtime = $derived(
|
||||
appSettings.value.debug.useWorker ? workerRuntime : memoryRuntime,
|
||||
@@ -64,15 +67,6 @@
|
||||
let activeNode = $state<NodeInstance | undefined>(undefined);
|
||||
let scene = $state<Group>(null!);
|
||||
|
||||
let graph = $state(
|
||||
localStorage.getItem("graph")
|
||||
? JSON.parse(localStorage.getItem("graph")!)
|
||||
: templates.defaultPlant,
|
||||
);
|
||||
function handleSave(graph: Graph) {
|
||||
localStorage.setItem("graph", JSON.stringify(graph));
|
||||
}
|
||||
|
||||
let graphInterface = $state<ReturnType<typeof GraphInterface>>(null!);
|
||||
let viewerComponent = $state<ReturnType<typeof Viewer>>();
|
||||
const manager = $derived(graphInterface?.manager);
|
||||
@@ -91,21 +85,16 @@
|
||||
callback: () => randomGenerate(),
|
||||
},
|
||||
]);
|
||||
|
||||
let graphSettings = $state<Record<string, any>>({});
|
||||
let graphSettingTypes = $state({
|
||||
randomSeed: { type: "boolean", value: false },
|
||||
});
|
||||
$effect(() => {
|
||||
if (graphSettings) {
|
||||
if (graphSettings && graphSettingTypes) {
|
||||
manager?.setSettings($state.snapshot(graphSettings));
|
||||
}
|
||||
});
|
||||
type BooleanSchema = {
|
||||
[key: string]: {
|
||||
type: "boolean";
|
||||
value: false;
|
||||
};
|
||||
};
|
||||
let graphSettingTypes = $state<BooleanSchema>({
|
||||
randomSeed: { type: "boolean", value: false },
|
||||
});
|
||||
|
||||
async function update(
|
||||
g: Graph,
|
||||
@@ -183,8 +172,9 @@
|
||||
/>
|
||||
</Grid.Cell>
|
||||
<Grid.Cell>
|
||||
{#if pm.graph}
|
||||
<GraphInterface
|
||||
{graph}
|
||||
graph={pm.graph}
|
||||
bind:this={graphInterface}
|
||||
registry={nodeRegistry}
|
||||
showGrid={appSettings.value.nodeInterface.showNodeGrid}
|
||||
@@ -193,9 +183,10 @@
|
||||
bind:showHelp={appSettings.value.nodeInterface.showHelp}
|
||||
bind:settings={graphSettings}
|
||||
bind:settingTypes={graphSettingTypes}
|
||||
onsave={(g) => pm.saveGraph(g)}
|
||||
onresult={(result) => handleUpdate(result)}
|
||||
onsave={(graph) => handleSave(graph)}
|
||||
/>
|
||||
{/if}
|
||||
<Sidebar>
|
||||
<Panel id="general" title="General" icon="i-[tabler--settings]">
|
||||
<NestedSettings
|
||||
@@ -236,13 +227,16 @@
|
||||
<PerformanceViewer data={$performanceStore} />
|
||||
{/if}
|
||||
</Panel>
|
||||
<Panel id="projects" icon="i-[tabler--folder-open]">
|
||||
<ProjectManagerEl projectManager={pm} />
|
||||
</Panel>
|
||||
<Panel
|
||||
id="graph-source"
|
||||
title="Graph Source"
|
||||
hidden={!appSettings.value.debug.showGraphJson}
|
||||
icon="i-[tabler--code]"
|
||||
>
|
||||
<GraphSource graph={graph && manager.serialize()} />
|
||||
<GraphSource graph={pm.graph ?? manager?.serialize()} />
|
||||
</Panel>
|
||||
<Panel
|
||||
id="benchmark"
|
||||
|
||||
8
app/src/routes/dev/+layout.svelte
Normal file
8
app/src/routes/dev/+layout.svelte
Normal 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>
|
||||
@@ -1,29 +1,119 @@
|
||||
<script lang="ts">
|
||||
import Grid from "$lib/grid";
|
||||
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) {
|
||||
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></Grid.Cell>
|
||||
<Grid.Cell>
|
||||
<Sidebar>
|
||||
<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">
|
||||
<input type="text" class="bg-red rounded-sm p-2" />
|
||||
<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>
|
||||
</Grid.Cell>
|
||||
</Grid.Row>
|
||||
</Sidebar>
|
||||
|
||||
<style>
|
||||
:global body {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
26
app/src/routes/dev/Code.svelte
Normal file
26
app/src/routes/dev/Code.svelte
Normal 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}
|
||||
1
app/static/.gitignore
vendored
Normal file
1
app/static/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
nodes/
|
||||
13
flake.nix
13
flake.nix
@@ -4,7 +4,7 @@
|
||||
};
|
||||
|
||||
outputs = {nixpkgs, ...}: let
|
||||
systems = ["aarch64-darwin" "x86_64-linux"];
|
||||
systems = ["aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux"];
|
||||
eachSystem = function:
|
||||
nixpkgs.lib.genAttrs systems (system:
|
||||
function {
|
||||
@@ -19,14 +19,15 @@
|
||||
pkgs.nodejs_24
|
||||
pkgs.pnpm_10
|
||||
|
||||
# wasm/rust stuff
|
||||
# wasm stuff
|
||||
pkgs.rustc
|
||||
pkgs.cargo
|
||||
pkgs.rust-analyzer
|
||||
pkgs.rustfmt
|
||||
pkgs.wasm-bindgen-cli
|
||||
pkgs.wasm-pack
|
||||
pkgs.binaryen
|
||||
pkgs.lld
|
||||
pkgs.zig
|
||||
pkgs.zls
|
||||
|
||||
# frontend
|
||||
pkgs.vscode-langservers-extracted
|
||||
@@ -35,6 +36,10 @@
|
||||
pkgs.tailwindcss-language-server
|
||||
pkgs.svelte-language-server
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
unset ZIG_GLOBAL_CACHE_DIR
|
||||
'';
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
@@ -11,18 +11,8 @@ crate-type = ["cdylib", "rlib"]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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" }
|
||||
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"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,22 +7,6 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
nodarium_utils = { version = "0.1.0", path = "../../../../packages/utils" }
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,15 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
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,
|
||||
};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
include_definition_file!("src/input.json");
|
||||
nodarium_definition_file!("src/input.json");
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[wasm_bindgen]
|
||||
#[nodarium_execute]
|
||||
pub fn execute(input: &[i32]) -> Vec<i32> {
|
||||
|
||||
set_panic_hook();
|
||||
|
||||
let args = split_args(input);
|
||||
|
||||
log!("WASM(cube): input: {:?} -> {:?}", input, args);
|
||||
@@ -22,7 +19,6 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
|
||||
let p = encode_float(size);
|
||||
let n = encode_float(-size);
|
||||
|
||||
|
||||
// [[1,3, x, y, z, x, y,z,x,y,z]];
|
||||
let mut cube_geometry = [
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,23 +7,6 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
use nodarium_utils::{
|
||||
concat_arg_vecs, evaluate_float, evaluate_int,
|
||||
geometry::{
|
||||
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 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> {
|
||||
set_panic_hook();
|
||||
|
||||
let args = split_args(input);
|
||||
|
||||
let paths = split_args(args[0]);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,21 +7,6 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
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> {
|
||||
args.into()
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,24 +7,7 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
glam = "0.27.0"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.34"
|
||||
glam = "0.30.10"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,20 @@
|
||||
use glam::Vec3;
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
use nodarium_utils::{
|
||||
concat_args, evaluate_float, evaluate_int,
|
||||
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 {
|
||||
a + (b - a) * t
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[nodarium_execute]
|
||||
pub fn execute(input: &[i32]) -> Vec<i32> {
|
||||
set_panic_hook();
|
||||
|
||||
reset_call_count();
|
||||
|
||||
let args = split_args(input);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "nodarium_instance"
|
||||
name = "instance"
|
||||
version = "0.1.0"
|
||||
authors = ["Max Richter <jim-x@web.de>"]
|
||||
edition = "2018"
|
||||
@@ -7,23 +7,7 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
glam = "0.30.10"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
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::{
|
||||
concat_args, encode_float, evaluate_float, evaluate_int,
|
||||
concat_args, evaluate_float, evaluate_int,
|
||||
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> {
|
||||
set_panic_hook();
|
||||
|
||||
let args = split_args(input);
|
||||
let mut inputs = split_args(args[0]);
|
||||
log!("WASM(instance): inputs: {:?}", inputs);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,17 +7,6 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_macros = { version = "0.1.0", path = "../../../../packages/macros" }
|
||||
web-sys = { version = "0.3.69", features = ["console"] }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.34"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_utils::{concat_args, set_panic_hook, split_args};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
use nodarium_utils::{
|
||||
concat_args, split_args
|
||||
};
|
||||
|
||||
include_definition_file!("src/input.json");
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[nodarium_execute]
|
||||
pub fn execute(args: &[i32]) -> Vec<i32> {
|
||||
set_panic_hook();
|
||||
let args = split_args(args);
|
||||
concat_args(vec![&[0], args[0], args[1], args[2]])
|
||||
}
|
||||
|
||||
nodarium_definition_file!("src/input.json");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "nodes-noise"
|
||||
name = "noise"
|
||||
version = "0.1.0"
|
||||
authors = ["Max Richter <jim-x@web.de>"]
|
||||
edition = "2018"
|
||||
@@ -7,24 +7,8 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
glam = "0.27.0"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.34"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,19 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
use nodarium_utils::{
|
||||
concat_args, evaluate_float, evaluate_int, evaluate_vec3, geometry::wrap_path_mut, log,
|
||||
reset_call_count, set_panic_hook, split_args,
|
||||
concat_args, evaluate_float, evaluate_int, evaluate_vec3, geometry::wrap_path_mut,
|
||||
reset_call_count, split_args,
|
||||
};
|
||||
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 {
|
||||
a + t * (b - a)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[nodarium_execute]
|
||||
pub fn execute(input: &[i32]) -> Vec<i32> {
|
||||
set_panic_hook();
|
||||
|
||||
reset_call_count();
|
||||
|
||||
let args = split_args(input);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,24 +7,6 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
console_error_panic_hook = ["dep:console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
use nodarium_utils::{
|
||||
concat_args, evaluate_int,
|
||||
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> {
|
||||
set_panic_hook();
|
||||
|
||||
log!("WASM(output): input: {:?}", input);
|
||||
|
||||
let args = split_args(input);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,21 +7,7 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_utils::{concat_args, set_panic_hook, split_args};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
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> {
|
||||
set_panic_hook();
|
||||
let args = split_args(args);
|
||||
concat_args(vec![&[1], args[0], args[1], args[2]])
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,23 +7,8 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
glam = "0.30.10"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
use glam::{Mat4, Vec3};
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
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,
|
||||
};
|
||||
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> {
|
||||
set_panic_hook();
|
||||
|
||||
log!("DEBUG args: {:?}", input);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,23 +7,6 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
use nodarium_utils::{
|
||||
evaluate_float, evaluate_int, evaluate_vec3,
|
||||
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> {
|
||||
set_panic_hook();
|
||||
|
||||
reset_call_count();
|
||||
|
||||
let args = split_args(input);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "max-plantarium-triangle"
|
||||
name = "triangle"
|
||||
version = "0.1.0"
|
||||
authors = ["Max Richter <jim-x@web.de>"]
|
||||
edition = "2018"
|
||||
@@ -7,22 +7,6 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,21 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
use nodarium_utils::{
|
||||
decode_float, encode_float, evaluate_int, set_panic_hook, split_args, wrap_arg,
|
||||
decode_float, encode_float, evaluate_int, split_args, wrap_arg, log
|
||||
};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::console;
|
||||
|
||||
include_definition_file!("src/input.json");
|
||||
nodarium_definition_file!("src/input.json");
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[wasm_bindgen]
|
||||
#[nodarium_execute]
|
||||
pub fn execute(input: &[i32]) -> Vec<i32> {
|
||||
|
||||
set_panic_hook();
|
||||
|
||||
let args = split_args(input);
|
||||
|
||||
let size = evaluate_int(args[0]);
|
||||
let decoded = decode_float(size);
|
||||
let negative_size = encode_float(-decoded);
|
||||
|
||||
console::log_1(&format!("WASM(triangle): input: {:?} -> {}", args[0],decoded).into());
|
||||
log!("WASM(triangle): input: {:?} -> {}", args[0],decoded);
|
||||
|
||||
// [[1,3, x, y, z, x, y,z,x,y,z]];
|
||||
wrap_arg(&[
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "max-plantarium-vec3"
|
||||
name = "vec3"
|
||||
version = "0.1.0"
|
||||
authors = ["Max Richter <jim-x@web.de>"]
|
||||
edition = "2018"
|
||||
@@ -7,22 +7,8 @@ edition = "2018"
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[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_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"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "wasm-pack build --release --out-name index --no-default-features",
|
||||
"dev": "cargo watch -s 'wasm-pack build --dev --out-name index --no-default-features'"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
use nodarium_macros::include_definition_file;
|
||||
use nodarium_macros::nodarium_definition_file;
|
||||
use nodarium_macros::nodarium_execute;
|
||||
use nodarium_utils::{concat_args, 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> {
|
||||
let args = split_args(input);
|
||||
log!("vec3 input: {:?}", input);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
2
nodes/max/plantarium/zig/.gitignore
vendored
Normal file
2
nodes/max/plantarium/zig/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.zig-cache/
|
||||
zig-out/
|
||||
19
nodes/max/plantarium/zig/build.zig
Normal file
19
nodes/max/plantarium/zig/build.zig
Normal file
@@ -0,0 +1,19 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.resolveTargetQuery(.{ .os_tag = .freestanding, .abi = .none, .cpu_arch = .wasm32 });
|
||||
const release = b.option(bool, "release", "To build a wasm release") orelse false;
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "zig",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("src/main.zig"),
|
||||
.target = target,
|
||||
.optimize = if (release) .ReleaseSmall else .Debug,
|
||||
}),
|
||||
});
|
||||
exe.rdynamic = true;
|
||||
exe.entry = .disabled;
|
||||
|
||||
b.installArtifact(exe);
|
||||
}
|
||||
81
nodes/max/plantarium/zig/build.zig.zon
Normal file
81
nodes/max/plantarium/zig/build.zig.zon
Normal file
@@ -0,0 +1,81 @@
|
||||
.{
|
||||
// This is the default name used by packages depending on this one. For
|
||||
// example, when a user runs `zig fetch --save <url>`, this field is used
|
||||
// as the key in the `dependencies` table. Although the user can choose a
|
||||
// different name, most users will stick with this provided value.
|
||||
//
|
||||
// It is redundant to include "zig" in this name because it is already
|
||||
// within the Zig package namespace.
|
||||
.name = .math,
|
||||
// This is a [Semantic Version](https://semver.org/).
|
||||
// In a future version of Zig it will be used for package deduplication.
|
||||
.version = "0.0.0",
|
||||
// Together with name, this represents a globally unique package
|
||||
// identifier. This field is generated by the Zig toolchain when the
|
||||
// package is first created, and then *never changes*. This allows
|
||||
// unambiguous detection of one package being an updated version of
|
||||
// another.
|
||||
//
|
||||
// When forking a Zig project, this id should be regenerated (delete the
|
||||
// field and run `zig build`) if the upstream project is still maintained.
|
||||
// Otherwise, the fork is *hostile*, attempting to take control over the
|
||||
// original project's identity. Thus it is recommended to leave the comment
|
||||
// on the following line intact, so that it shows up in code reviews that
|
||||
// modify the field.
|
||||
.fingerprint = 0xa927044d8d610b01, // Changing this has security and trust implications.
|
||||
// Tracks the earliest Zig version that the package considers to be a
|
||||
// supported use case.
|
||||
.minimum_zig_version = "0.15.2",
|
||||
// This field is optional.
|
||||
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
||||
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
|
||||
// Once all dependencies are fetched, `zig build` no longer requires
|
||||
// internet connectivity.
|
||||
.dependencies = .{
|
||||
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
|
||||
//.example = .{
|
||||
// // When updating this field to a new URL, be sure to delete the corresponding
|
||||
// // `hash`, otherwise you are communicating that you expect to find the old hash at
|
||||
// // the new URL. If the contents of a URL change this will result in a hash mismatch
|
||||
// // which will prevent zig from using it.
|
||||
// .url = "https://example.com/foo.tar.gz",
|
||||
//
|
||||
// // This is computed from the file contents of the directory of files that is
|
||||
// // obtained after fetching `url` and applying the inclusion rules given by
|
||||
// // `paths`.
|
||||
// //
|
||||
// // This field is the source of truth; packages do not come from a `url`; they
|
||||
// // come from a `hash`. `url` is just one of many possible mirrors for how to
|
||||
// // obtain a package matching this `hash`.
|
||||
// //
|
||||
// // Uses the [multihash](https://multiformats.io/multihash/) format.
|
||||
// .hash = "...",
|
||||
//
|
||||
// // When this is provided, the package is found in a directory relative to the
|
||||
// // build root. In this case the package's hash is irrelevant and therefore not
|
||||
// // computed. This field and `url` are mutually exclusive.
|
||||
// .path = "foo",
|
||||
//
|
||||
// // When this is set to `true`, a package is declared to be lazily
|
||||
// // fetched. This makes the dependency only get fetched if it is
|
||||
// // actually used.
|
||||
// .lazy = false,
|
||||
//},
|
||||
},
|
||||
// Specifies the set of files and directories that are included in this package.
|
||||
// Only files and directories listed here are included in the `hash` that
|
||||
// is computed for this package. Only files listed here will remain on disk
|
||||
// when using the zig package manager. As a rule of thumb, one should list
|
||||
// files required for compilation plus any license(s).
|
||||
// Paths are relative to the build root. Use the empty string (`""`) to refer to
|
||||
// the build root itself.
|
||||
// A directory listed here means that all files within, recursively, are included.
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
// For example...
|
||||
//"LICENSE",
|
||||
//"README.md",
|
||||
},
|
||||
}
|
||||
27
nodes/max/plantarium/zig/src/input.json
Normal file
27
nodes/max/plantarium/zig/src/input.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"id": "max/nodarium/zig",
|
||||
"outputs": [
|
||||
"float"
|
||||
],
|
||||
"inputs": {
|
||||
"op_type": {
|
||||
"label": "type",
|
||||
"type": "select",
|
||||
"options": [
|
||||
"add",
|
||||
"subtract",
|
||||
"multiply",
|
||||
"divide"
|
||||
],
|
||||
"internal": true
|
||||
},
|
||||
"a": {
|
||||
"type": "float",
|
||||
"value": 2
|
||||
},
|
||||
"b": {
|
||||
"type": "float",
|
||||
"value": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
29
nodes/max/plantarium/zig/src/main.zig
Normal file
29
nodes/max/plantarium/zig/src/main.zig
Normal file
@@ -0,0 +1,29 @@
|
||||
const std = @import("std");
|
||||
|
||||
const def = @embedFile("input.json");
|
||||
|
||||
export fn execute(ptr: *anyopaque, len: c_int) c_int {
|
||||
_ = ptr; // autofix
|
||||
_ = len; // autofix
|
||||
return 0;
|
||||
}
|
||||
|
||||
export fn __alloc(len: c_int) ?*anyopaque {
|
||||
if (len < 0) return null;
|
||||
const mem = std.heap.wasm_allocator.alloc(u8, @intCast(len)) catch return null;
|
||||
return mem.ptr;
|
||||
}
|
||||
|
||||
export fn __free(ptr: *anyopaque, len: c_int) void {
|
||||
if (len < 1) return;
|
||||
const mem: [*]u8 = @ptrCast(@alignCast(ptr));
|
||||
std.heap.wasm_allocator.free(mem[0..@intCast(len)]);
|
||||
}
|
||||
|
||||
export fn getDefinitionPtr() *const anyopaque {
|
||||
return def.ptr;
|
||||
}
|
||||
|
||||
export fn getDefinitionLen() usize {
|
||||
return def.len;
|
||||
}
|
||||
15
package.json
15
package.json
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"scripts": {
|
||||
"postinstall": "pnpm run -r --filter 'ui' build",
|
||||
"build": "pnpm build:nodes && pnpm build:app",
|
||||
"build:story": "pnpm -r --filter 'ui' story:build",
|
||||
"build:app": "BASE_PATH=/ui pnpm -r --filter 'ui' build && pnpm -r --filter 'app' build",
|
||||
"build:nodes": "pnpm -r --filter './nodes/**' build",
|
||||
"build:nodes": "cargo build --workspace --target wasm32-unknown-unknown --release && rm -rf ./app/static/nodes/max/plantarium/ && mkdir -p ./app/static/nodes/max/plantarium/ && cp -R ./target/wasm32-unknown-unknown/release/*.wasm ./app/static/nodes/max/plantarium/",
|
||||
"build:deploy": "pnpm build",
|
||||
"dev:all": "pnpm -r dev",
|
||||
"dev:nodes": "pnpm -r --parallel --filter './nodes/**' dev",
|
||||
"dev": "pnpm -r --filter 'app' --filter './packages/ui' dev"
|
||||
"dev:nodes": "chokidar './nodes/**' --initial -i '/pkg/' -c 'pnpm build:nodes'",
|
||||
"dev:app_ui": "pnpm -r --parallel --filter 'app' --filter './packages/ui' dev",
|
||||
"dev_ui": "pnpm -r --filter 'ui' dev:ui",
|
||||
"dev": "pnpm run \"/^dev:.*/\""
|
||||
},
|
||||
"packageManager": "pnpm@10.24.0"
|
||||
"packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316",
|
||||
"devDependencies": {
|
||||
"chokidar-cli": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ repository = "https://github.com/jim-fx/nodes"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "1.0", features = ["full"] }
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
|
||||
quote = "1.0"
|
||||
|
||||
@@ -5,32 +5,7 @@ use quote::quote;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use syn::{parse_macro_input, LitStr};
|
||||
|
||||
#[proc_macro]
|
||||
pub fn node_definition(input: TokenStream) -> TokenStream {
|
||||
let input_string = parse_macro_input!(input as LitStr).value();
|
||||
|
||||
// Validate JSON format
|
||||
let json: NodeDefinition = match serde_json::from_str(&input_string) {
|
||||
Ok(json) => json,
|
||||
Err(e) => panic!("Invalid JSON input: {}", e),
|
||||
};
|
||||
|
||||
// Convert the validated JSON back to a pretty-printed string
|
||||
let formatted_json = serde_json::to_string_pretty(&json).expect("Failed to serialize JSON");
|
||||
|
||||
// Generate the output function
|
||||
let expanded = quote! {
|
||||
#[wasm_bindgen]
|
||||
pub fn get_definition() -> String {
|
||||
String::from(#formatted_json)
|
||||
}
|
||||
};
|
||||
|
||||
// Convert the generated code back to a TokenStream
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
use syn::parse_macro_input;
|
||||
|
||||
fn add_line_numbers(input: String) -> String {
|
||||
return input
|
||||
@@ -41,39 +16,120 @@ fn add_line_numbers(input: String) -> String {
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn include_definition_file(input: TokenStream) -> TokenStream {
|
||||
let file_path = syn::parse_macro_input!(input as syn::LitStr).value();
|
||||
#[proc_macro_attribute]
|
||||
pub fn nodarium_execute(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let input_fn = parse_macro_input!(item as syn::ItemFn);
|
||||
let _fn_name = &input_fn.sig.ident;
|
||||
let _fn_vis = &input_fn.vis;
|
||||
let fn_body = &input_fn.block;
|
||||
|
||||
// Retrieve the directory containing the Cargo.toml file
|
||||
let project_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
let full_path = Path::new(&project_dir).join(&file_path);
|
||||
let first_arg_ident = if let Some(syn::FnArg::Typed(pat_type)) = input_fn.sig.inputs.first() {
|
||||
if let syn::Pat::Ident(pat_ident) = &*pat_type.pat {
|
||||
&pat_ident.ident
|
||||
} else {
|
||||
panic!("Expected a simple identifier for the first argument");
|
||||
}
|
||||
} else {
|
||||
panic!("The execute function must have at least one argument (the input slice)");
|
||||
};
|
||||
|
||||
// Read the JSON file content
|
||||
let json_content = fs::read_to_string(full_path).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Failed to read JSON file at '{}/{}': {}",
|
||||
project_dir, file_path, err
|
||||
)
|
||||
});
|
||||
|
||||
// Optionally, validate that the content is valid JSON
|
||||
let _: NodeDefinition = serde_json::from_str(&json_content).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"JSON file contains invalid JSON: \n{} \n{}",
|
||||
err,
|
||||
add_line_numbers(json_content.clone())
|
||||
)
|
||||
});
|
||||
|
||||
// Generate the function that returns the JSON string
|
||||
// We create a wrapper that handles the C ABI and pointer math
|
||||
let expanded = quote! {
|
||||
#[wasm_bindgen]
|
||||
pub fn get_definition() -> String {
|
||||
String::from(#json_content)
|
||||
extern "C" {
|
||||
fn host_log_panic(ptr: *const u8, len: usize);
|
||||
fn host_log(ptr: *const u8, len: usize);
|
||||
}
|
||||
|
||||
fn setup_panic_hook() {
|
||||
static SET_HOOK: std::sync::Once = std::sync::Once::new();
|
||||
SET_HOOK.call_once(|| {
|
||||
std::panic::set_hook(Box::new(|info| {
|
||||
let msg = info.to_string();
|
||||
unsafe { host_log_panic(msg.as_ptr(), msg.len()); }
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __alloc(len: usize) -> *mut i32 {
|
||||
let mut buf = Vec::with_capacity(len);
|
||||
let ptr = buf.as_mut_ptr();
|
||||
std::mem::forget(buf);
|
||||
ptr
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __free(ptr: *mut i32, len: usize) {
|
||||
unsafe {
|
||||
let _ = Vec::from_raw_parts(ptr, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
static mut OUTPUT_BUFFER: Vec<i32> = Vec::new();
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn execute(ptr: *const i32, len: usize) -> *mut i32 {
|
||||
setup_panic_hook();
|
||||
// 1. Convert raw pointer to slice
|
||||
let input = unsafe { core::slice::from_raw_parts(ptr, len) };
|
||||
|
||||
// 2. Call the logic (which we define below)
|
||||
let result_data: Vec<i32> = internal_logic(input);
|
||||
|
||||
// 3. Use the static buffer for the result
|
||||
let result_len = result_data.len();
|
||||
unsafe {
|
||||
OUTPUT_BUFFER.clear();
|
||||
OUTPUT_BUFFER.reserve(result_len + 1);
|
||||
OUTPUT_BUFFER.push(result_len as i32);
|
||||
OUTPUT_BUFFER.extend(result_data);
|
||||
|
||||
OUTPUT_BUFFER.as_mut_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
fn internal_logic(#first_arg_ident: &[i32]) -> Vec<i32> {
|
||||
#fn_body
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn nodarium_definition_file(input: TokenStream) -> TokenStream {
|
||||
let path_lit = syn::parse_macro_input!(input as syn::LitStr);
|
||||
let file_path = path_lit.value();
|
||||
|
||||
let project_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
let full_path = Path::new(&project_dir).join(&file_path);
|
||||
|
||||
let json_content = fs::read_to_string(&full_path).unwrap_or_else(|err| {
|
||||
panic!("Failed to read JSON file at '{}/{}': {}", project_dir, file_path, err)
|
||||
});
|
||||
|
||||
let _: NodeDefinition = serde_json::from_str(&json_content).unwrap_or_else(|err| {
|
||||
panic!("JSON file contains invalid JSON: \n{} \n{}", err, add_line_numbers(json_content.clone()))
|
||||
});
|
||||
|
||||
// We use the span from the input path literal
|
||||
let bytes = syn::LitByteStr::new(json_content.as_bytes(), path_lit.span());
|
||||
let len = json_content.len();
|
||||
|
||||
let expanded = quote! {
|
||||
#[link_section = "nodarium_definition"]
|
||||
static DEFINITION_DATA: [u8; #len] = *#bytes;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn get_definition_ptr() -> *const u8 {
|
||||
DEFINITION_DATA.as_ptr()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn get_definition_len() -> usize {
|
||||
DEFINITION_DATA.len()
|
||||
}
|
||||
};
|
||||
|
||||
// Convert the generated code back to a TokenStream
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@nodarium/types": "link:../types",
|
||||
"@nodarium/utils": "link:../utils",
|
||||
"@nodarium/types": "workspace:",
|
||||
"@nodarium/utils": "workspace:",
|
||||
"idb": "^8.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
import {
|
||||
NodeDefinitionSchema,
|
||||
type AsyncCache,
|
||||
type NodeDefinition,
|
||||
type NodeRegistry,
|
||||
} from "@nodarium/types";
|
||||
import { createLogger, createWasmWrapper } from "@nodarium/utils";
|
||||
NodeDefinitionSchema,
|
||||
type NodeRegistry
|
||||
} from '@nodarium/types';
|
||||
import { createLogger, createWasmWrapper } from '@nodarium/utils';
|
||||
|
||||
const log = createLogger("node-registry");
|
||||
const log = createLogger('node-registry');
|
||||
log.mute();
|
||||
|
||||
export class RemoteNodeRegistry implements NodeRegistry {
|
||||
status: "loading" | "ready" | "error" = "loading";
|
||||
status: 'loading' | 'ready' | 'error' = 'loading';
|
||||
private nodes: Map<string, NodeDefinition> = new Map();
|
||||
|
||||
|
||||
constructor(
|
||||
private url: string,
|
||||
public cache?: AsyncCache<ArrayBuffer | string>,
|
||||
public cache?: AsyncCache<ArrayBuffer | string>
|
||||
) { }
|
||||
|
||||
async fetchJson(url: string, skipCache = false) {
|
||||
|
||||
const finalUrl = `${this.url}/${url}`;
|
||||
|
||||
if (!skipCache && this.cache) {
|
||||
const cachedValue = await this.cache?.get<string>(finalUrl);
|
||||
if (cachedValue) {
|
||||
// fetch again in the background, maybe implement that only refetch after a certain time
|
||||
this.fetchJson(url, true)
|
||||
this.fetchJson(url, true);
|
||||
return JSON.parse(cachedValue);
|
||||
}
|
||||
}
|
||||
@@ -47,14 +45,13 @@ export class RemoteNodeRegistry implements NodeRegistry {
|
||||
}
|
||||
|
||||
async fetchArrayBuffer(url: string, skipCache = false) {
|
||||
|
||||
const finalUrl = `${this.url}/${url}`;
|
||||
|
||||
if (!skipCache && this.cache) {
|
||||
const cachedNode = await this.cache?.get<ArrayBuffer>(finalUrl);
|
||||
if (cachedNode) {
|
||||
// fetch again in the background, maybe implement that only refetch after a certain time
|
||||
this.fetchArrayBuffer(url, true)
|
||||
this.fetchArrayBuffer(url, true);
|
||||
return cachedNode;
|
||||
}
|
||||
}
|
||||
@@ -80,7 +77,7 @@ export class RemoteNodeRegistry implements NodeRegistry {
|
||||
|
||||
async fetchCollection(userCollectionId: `${string}/${string}`) {
|
||||
const col = await this.fetchJson(`nodes/${userCollectionId}.json`);
|
||||
return col
|
||||
return col;
|
||||
}
|
||||
|
||||
async fetchNodeDefinition(nodeId: `${string}/${string}/${string}`) {
|
||||
@@ -88,7 +85,6 @@ export class RemoteNodeRegistry implements NodeRegistry {
|
||||
}
|
||||
|
||||
private async fetchNodeWasm(nodeId: `${string}/${string}/${string}`) {
|
||||
|
||||
const node = await this.fetchArrayBuffer(`nodes/${nodeId}.wasm`);
|
||||
if (!node) {
|
||||
throw new Error(`Failed to load node wasm ${nodeId}`);
|
||||
@@ -100,7 +96,7 @@ export class RemoteNodeRegistry implements NodeRegistry {
|
||||
async load(nodeIds: `${string}/${string}/${string}`[]) {
|
||||
const a = performance.now();
|
||||
|
||||
const nodes = await Promise.all(
|
||||
const nodes = (await Promise.all(
|
||||
[...new Set(nodeIds).values()].map(async (id) => {
|
||||
if (this.nodes.has(id)) {
|
||||
return this.nodes.get(id)!;
|
||||
@@ -108,17 +104,23 @@ export class RemoteNodeRegistry implements NodeRegistry {
|
||||
|
||||
const wasmBuffer = await this.fetchNodeWasm(id);
|
||||
|
||||
return this.register(wasmBuffer);
|
||||
}),
|
||||
);
|
||||
try {
|
||||
return await this.register(wasmBuffer);
|
||||
} catch (e) {
|
||||
console.log('Failed to register: ', id);
|
||||
console.error(e);
|
||||
return;
|
||||
}
|
||||
})
|
||||
)).filter(Boolean) as NodeDefinition[];
|
||||
|
||||
const duration = performance.now() - a;
|
||||
|
||||
log.group("loaded nodes in", duration, "ms");
|
||||
log.group('loaded nodes in', duration, 'ms');
|
||||
log.info(nodeIds);
|
||||
log.info(nodes);
|
||||
log.groupEnd();
|
||||
this.status = "ready";
|
||||
this.status = 'ready';
|
||||
|
||||
return nodes;
|
||||
}
|
||||
@@ -129,17 +131,16 @@ export class RemoteNodeRegistry implements NodeRegistry {
|
||||
const definition = NodeDefinitionSchema.safeParse(wrapper.get_definition());
|
||||
|
||||
if (definition.error) {
|
||||
console.error(definition.error);
|
||||
throw definition.error;
|
||||
}
|
||||
|
||||
if (this.cache) {
|
||||
await this.cache.set(definition.data.id, wasmBuffer);
|
||||
this.cache.set(definition.data.id, wasmBuffer);
|
||||
}
|
||||
|
||||
let node = {
|
||||
...definition.data,
|
||||
execute: wrapper.execute,
|
||||
execute: wrapper.execute
|
||||
};
|
||||
|
||||
this.nodes.set(definition.data.id, node);
|
||||
|
||||
@@ -4,7 +4,6 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "Types for Nodarium"
|
||||
website = "https://nodes.max-richter.dev"
|
||||
repository = "https://github.com/jim-fx/nodes"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "chokidar './src/**' --initial -c 'pnpm build'",
|
||||
"dev:ui": "vite",
|
||||
"build": "vite build && npm run package",
|
||||
"preview": "vite preview",
|
||||
"package": "svelte-kit sync && svelte-package && publint",
|
||||
@@ -10,6 +11,7 @@
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"test": "vitest",
|
||||
"lint-dprint": "dprint check -c '../../.dprint.jsonc' .",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"exports": {
|
||||
@@ -28,7 +30,7 @@
|
||||
"svelte": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nodarium/types": "link:../types",
|
||||
"@nodarium/types": "workspace:",
|
||||
"@sveltejs/adapter-static": "^3.0.10",
|
||||
"@sveltejs/kit": "^2.50.0",
|
||||
"@sveltejs/package": "^2.5.7",
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { NodeInput } from '@nodarium/types';
|
||||
|
||||
import Checkbox from './inputs/Checkbox.svelte';
|
||||
import Number from './inputs/Number.svelte';
|
||||
import Select from './inputs/Select.svelte';
|
||||
import Vec3 from './inputs/Vec3.svelte';
|
||||
import { Checkbox, Number, Select, Vec3 } from './index.js';
|
||||
|
||||
interface Props {
|
||||
input: NodeInput;
|
||||
@@ -16,7 +13,7 @@
|
||||
</script>
|
||||
|
||||
{#if input.type === 'float'}
|
||||
<Number bind:value min={input?.min} max={input?.max} step={0.01} />
|
||||
<Number bind:value min={input?.min} max={input?.max} step={input?.step} />
|
||||
{:else if input.type === 'integer'}
|
||||
<Number bind:value min={input?.min} max={input?.max} />
|
||||
{:else if input.type === 'boolean'}
|
||||
|
||||
@@ -40,6 +40,30 @@
|
||||
|
||||
}
|
||||
|
||||
@theme {
|
||||
--color-neutral-100: #E7E7E7;
|
||||
--color-neutral-200: #CECECE;
|
||||
--color-neutral-300: #7C7C7C;
|
||||
--color-neutral-400: #2D2D2D;
|
||||
--color-neutral-500: #171717;
|
||||
--color-neutral-800: #111111;
|
||||
--color-neutral-900: #060606;
|
||||
|
||||
--color-layer-0: var(--neutral-900);
|
||||
--color-layer-1: var(--neutral-500);
|
||||
--color-layer-2: var(--neutral-400);
|
||||
--color-layer-3: var(--neutral-200);
|
||||
|
||||
--color-active: #ffffff;
|
||||
--color-selected: #c65a19;
|
||||
|
||||
--color-outline: var(--neutral-400);
|
||||
--color-connection: #333333;
|
||||
--color-edge: var(--connection, var(--outline));
|
||||
|
||||
--color-text-color: var(--neutral-200);
|
||||
}
|
||||
|
||||
html {
|
||||
--neutral-100: #E7E7E7;
|
||||
--neutral-200: #CECECE;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
export { default as Input } from "./Input.svelte"
|
||||
export { default as Float } from "./inputs/Float.svelte"
|
||||
export { default as Integer } from "./inputs/Integer.svelte"
|
||||
export { default as Select } from "./inputs/Select.svelte"
|
||||
export { default as Checkbox } from "./inputs/Checkbox.svelte"
|
||||
export { default as Vec3 } from "./inputs/Vec3.svelte";
|
||||
export { default as Input } from './Input.svelte';
|
||||
export { default as Checkbox } from './inputs/Checkbox.svelte';
|
||||
export { default as Float, default as Number } from './inputs/Float.svelte';
|
||||
export { default as Integer } from './inputs/Integer.svelte';
|
||||
export { default as Select } from './inputs/Select.svelte';
|
||||
export { default as Vec3 } from './inputs/Vec3.svelte';
|
||||
|
||||
export { default as Details } from "./Details.svelte"
|
||||
export { default as ShortCut } from "./ShortCut.svelte";
|
||||
export { default as Details } from './Details.svelte';
|
||||
export { default as ShortCut } from './ShortCut.svelte';
|
||||
|
||||
import Input from './Input.svelte';
|
||||
export default Input;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user