feat: add snapToGrid and showGrid settings

This commit is contained in:
max_richter 2024-04-22 16:52:52 +02:00
parent ad197db873
commit 1de0094c85
25 changed files with 290 additions and 99 deletions

28
Cargo.lock generated
View File

@ -159,6 +159,20 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "noise"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"macros",
"serde",
"serde-wasm-bindgen",
"utils",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.19.0"
@ -301,20 +315,6 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "template"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"macros",
"serde",
"serde-wasm-bindgen",
"utils",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]] [[package]]
name = "types" name = "types"
version = "0.1.0" version = "0.1.0"

View File

@ -1,7 +1,12 @@
[workspace] [workspace]
resolver = "2" resolver = "2"
members = ["nodes/max/plantarium/*", "packages/macros", "packages/types", "packages/utils"] members = [
"nodes/max/plantarium/*",
"packages/macros",
"packages/types",
"packages/utils",
]
exclude = ["nodes/max/plantarium/.template"]
[profile.release] [profile.release]
lto = true lto = true

View File

@ -67,27 +67,27 @@ void main(void) {
//extra small grid //extra small grid
float m1 = grid(ux, uy, divisions*4.0, thickness*4.0) * 0.1; float m1 = grid(ux, uy, divisions*4.0, thickness*4.0) * 0.9;
float m2 = grid(ux, uy, divisions*16.0, thickness*16.0) * 0.03; float m2 = grid(ux, uy, divisions*16.0, thickness*16.0) * 0.5;
float xsmall = max(m1, m2); float xsmall = max(m1, m2);
float s3 = circle_grid(ux, uy, cz/1.6, 1.0) * 0.2; float s3 = circle_grid(ux, uy, cz/1.6, 1.0) * 0.5;
xsmall = max(xsmall, s3); xsmall = max(xsmall, s3);
// small grid // small grid
float c1 = grid(ux, uy, divisions, thickness) * 0.2; float c1 = grid(ux, uy, divisions, thickness) * 0.6;
float c2 = grid(ux, uy, divisions*2.0, thickness) * 0.1; float c2 = grid(ux, uy, divisions*2.0, thickness) * 0.5;
float small = max(c1, c2); float small = max(c1, c2);
float s1 = circle_grid(ux, uy, cz*10.0, 2.0) * 0.2; float s1 = circle_grid(ux, uy, cz*10.0, 2.0) * 0.5;
small = max(small, s1); small = max(small, s1);
// large grid // large grid
float c3 = grid(ux, uy, divisions/8.0, thickness/8.0) * 0.1; float c3 = grid(ux, uy, divisions/8.0, thickness/8.0) * 0.5;
float c4 = grid(ux, uy, divisions/2.0, thickness/4.0) * 0.05; float c4 = grid(ux, uy, divisions/2.0, thickness/4.0) * 0.4;
float large = max(c3, c4); float large = max(c3, c4);
float s2 = circle_grid(ux, uy, cz*20.0, 1.0) * 0.2; float s2 = circle_grid(ux, uy, cz*20.0, 1.0) * 0.4;
large = max(large, s2); large = max(large, s2);
float c = mix(large, small, min(nz*2.0+0.05, 1.0)); float c = mix(large, small, min(nz*2.0+0.05, 1.0));

View File

@ -53,7 +53,7 @@
}} }}
uniforms.camPos.value={cameraPosition} uniforms.camPos.value={cameraPosition}
uniforms.backgroundColor.value={$colors.layer0} uniforms.backgroundColor.value={$colors.layer0}
uniforms.lineColor.value={$colors.layer2} uniforms.lineColor.value={$colors.outline}
uniforms.zoomLimits.value={[minZoom, maxZoom]} uniforms.zoomLimits.value={[minZoom, maxZoom]}
uniforms.dimensions.value={[width, height]} uniforms.dimensions.value={[width, height]}
/> />

View File

@ -25,6 +25,11 @@
export let graph: GraphManager; export let graph: GraphManager;
export let settings = {
snapToGrid: true,
showGrid: true,
};
let keymap = let keymap =
getContext<ReturnType<typeof createKeyMap>>("keymap") || createKeyMap([]); getContext<ReturnType<typeof createKeyMap>>("keymap") || createKeyMap([]);
@ -320,8 +325,10 @@
if (event.ctrlKey) { if (event.ctrlKey) {
const snapLevel = getSnapLevel(); const snapLevel = getSnapLevel();
newX = snapToGrid(newX, 5 / snapLevel); if (settings.snapToGrid) {
newY = snapToGrid(newY, 5 / snapLevel); newX = snapToGrid(newX, 5 / snapLevel);
newY = snapToGrid(newY, 5 / snapLevel);
}
} }
if (!node.tmp.isMoving) { if (!node.tmp.isMoving) {
@ -667,15 +674,20 @@
if (activeNode?.tmp?.isMoving) { if (activeNode?.tmp?.isMoving) {
activeNode.tmp = activeNode.tmp || {}; activeNode.tmp = activeNode.tmp || {};
activeNode.tmp.isMoving = false; activeNode.tmp.isMoving = false;
const snapLevel = getSnapLevel(); if (settings.snapToGrid) {
activeNode.position[0] = snapToGrid( const snapLevel = getSnapLevel();
activeNode?.tmp?.x ?? activeNode.position[0], activeNode.position[0] = snapToGrid(
5 / snapLevel, activeNode?.tmp?.x ?? activeNode.position[0],
); 5 / snapLevel,
activeNode.position[1] = snapToGrid( );
activeNode?.tmp?.y ?? activeNode.position[1], activeNode.position[1] = snapToGrid(
5 / snapLevel, activeNode?.tmp?.y ?? activeNode.position[1],
); 5 / snapLevel,
);
} else {
activeNode.position[0] = activeNode?.tmp?.x ?? activeNode.position[0];
activeNode.position[1] = activeNode?.tmp?.y ?? activeNode.position[1];
}
const nodes = [ const nodes = [
...[...($selectedNodes?.values() || [])].map((id) => graph.getNode(id)), ...[...($selectedNodes?.values() || [])].map((id) => graph.getNode(id)),
] as NodeType[]; ] as NodeType[];
@ -796,11 +808,9 @@
const wrapper = createWasmWrapper(buffer); const wrapper = createWasmWrapper(buffer);
const definition = wrapper.get_definition(); const definition = wrapper.get_definition();
const res = NodeDefinitionSchema.parse(definition); const res = NodeDefinitionSchema.parse(definition);
console.log(wrapper, res);
} }
}; };
reader.readAsArrayBuffer(files[0]); reader.readAsArrayBuffer(files[0]);
console.log({ files });
} }
} }
@ -858,7 +868,9 @@
<Canvas shadows={false} renderMode="on-demand" colorManagementEnabled={false}> <Canvas shadows={false} renderMode="on-demand" colorManagementEnabled={false}>
<Camera bind:camera position={cameraPosition} /> <Camera bind:camera position={cameraPosition} />
<Background {cameraPosition} {maxZoom} {minZoom} {width} {height} /> {#if settings?.showGrid !== false}
<Background {cameraPosition} {maxZoom} {minZoom} {width} {height} />
{/if}
{#if boxSelection && mouseDown} {#if boxSelection && mouseDown}
<BoxSelection <BoxSelection

View File

@ -18,6 +18,9 @@
export const keymap = createKeyMap([]); export const keymap = createKeyMap([]);
setContext("keymap", keymap); setContext("keymap", keymap);
export let showGrid = false;
export let snapToGrid = false;
const updateSettings = debounce((s) => { const updateSettings = debounce((s) => {
manager.setSettings(s); manager.setSettings(s);
}, 200); }, 200);
@ -43,4 +46,4 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
</script> </script>
<GraphEl graph={manager} /> <GraphEl graph={manager} settings={{ showGrid, snapToGrid }} />

View File

@ -1,5 +1,5 @@
import type { Graph, NodeRegistry, NodeDefinition, RuntimeExecutor } from "@nodes/types"; import type { Graph, NodeRegistry, NodeDefinition, RuntimeExecutor } from "@nodes/types";
import { fastHash, concat_encoded, encodeFloat, encode } from "@nodes/utils" import { fastHash, concatEncodedArrays, encodeFloat, encodeNestedArray, decodeNestedArray } from "@nodes/utils"
export class MemoryRuntimeExecutor implements RuntimeExecutor { export class MemoryRuntimeExecutor implements RuntimeExecutor {
@ -109,7 +109,7 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
const sortedNodes = nodes.sort((a, b) => (b.tmp?.depth || 0) - (a.tmp?.depth || 0)); const sortedNodes = nodes.sort((a, b) => (b.tmp?.depth || 0) - (a.tmp?.depth || 0));
// here we store the intermediate results of the nodes // here we store the intermediate results of the nodes
const results: Record<string, string | boolean | number> = {}; const results: Record<string, Int32Array> = {};
const runSeed = settings["randomSeed"] === true ? Math.floor(Math.random() * 100000000) : 5120983; const runSeed = settings["randomSeed"] === true ? Math.floor(Math.random() * 100000000) : 5120983;
@ -192,7 +192,7 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
} }
if (Array.isArray(value)) { if (Array.isArray(value)) {
return encode(value); return encodeNestedArray(value);
} }
return value; return value;
@ -204,10 +204,14 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
// console.log(`${a2 - a1}ms TRANSFORMED_INPUTS`); // console.log(`${a2 - a1}ms TRANSFORMED_INPUTS`);
const _inputs = concat_encoded(transformed_inputs); const encoded_inputs = concatEncodedArrays(transformed_inputs);
const a3 = performance.now(); const a3 = performance.now();
// console.log(`executing ${node_type.id || node.id}`, _inputs); console.groupCollapsed(`executing ${node_type.id || node.id}`);
results[node.id] = node_type.execute(_inputs) as number; console.log(`Inputs:`, transformed_inputs);
console.log(`Encoded Inputs:`, encoded_inputs);
results[node.id] = node_type.execute(encoded_inputs);
console.log("Result:", decodeNestedArray(results[node.id]));
console.groupEnd();
const duration = performance.now() - a3; const duration = performance.now() - a3;
if (duration > 5) { if (duration > 5) {
this.cache[cacheKey] = { eol: Date.now() + 10_000, value: results[node.id] }; this.cache[cacheKey] = { eol: Date.now() + 10_000, value: results[node.id] };
@ -217,6 +221,7 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
const a4 = performance.now(); const a4 = performance.now();
// console.log(`${a4 - a0}ms e2e duration`); // console.log(`${a4 - a0}ms e2e duration`);
} catch (e) { } catch (e) {
console.groupEnd();
console.error(`Error executing node ${node_type.id || node.id}`, e); console.error(`Error executing node ${node_type.id || node.id}`, e);
} }

View File

@ -1,9 +1,10 @@
import localStore from "$lib/helpers/localStore"; import localStore from "$lib/helpers/localStore";
import { label } from "three/examples/jsm/nodes/Nodes.js";
export const AppSettings = localStore("node-settings", { export const AppSettings = localStore("node-settings", {
theme: 0, theme: 0,
showGrid: true, showGrid: true,
showNodeGrid: true,
snapToGrid: true,
wireframes: false, wireframes: false,
showIndices: false, showIndices: false,
}); });
@ -33,6 +34,16 @@ export const AppSettingTypes = {
label: "Show Grid", label: "Show Grid",
value: true, value: true,
}, },
nodeInterface: {
showNodeGrid: {
type: "boolean",
value: true
},
snapToGrid: {
type: "boolean",
value: true
}
},
stressTest: { stressTest: {
amount: { amount: {
type: "integer", type: "integer",

View File

@ -14,10 +14,13 @@
import NodeStore from "$lib/node-store/NodeStore.svelte"; import NodeStore from "$lib/node-store/NodeStore.svelte";
import type { GraphManager } from "$lib/graph-interface/graph-manager"; import type { GraphManager } from "$lib/graph-interface/graph-manager";
import { setContext } from "svelte"; import { setContext } from "svelte";
import { decodeNestedArray } from "@nodes/utils";
const nodeRegistry = new RemoteNodeRegistry(""); const nodeRegistry = new RemoteNodeRegistry("");
const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry); const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry);
globalThis.decode = decodeNestedArray;
let res: Int32Array; let res: Int32Array;
let graph = localStorage.getItem("graph") let graph = localStorage.getItem("graph")
@ -120,6 +123,8 @@
registry={nodeRegistry} registry={nodeRegistry}
{graph} {graph}
bind:keymap bind:keymap
showGrid={$AppSettings?.showNodeGrid}
snapToGrid={$AppSettings?.snapToGrid}
settings={settings?.graph?.settings} settings={settings?.graph?.settings}
on:settings={handleSettings} on:settings={handleSettings}
on:result={handleResult} on:result={handleResult}

View File

@ -1,5 +1,5 @@
use macros::include_definition_file; use macros::include_definition_file;
use utils::{evaluate_arg, get_args}; use utils::{evaluate_int, get_args};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use web_sys::console; use web_sys::console;
@ -11,8 +11,8 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
let args = get_args(input); let args = get_args(input);
let value_encoded = evaluate_arg(args[0]); let value_encoded = evaluate_int(args[0]);
let length = evaluate_arg(args[1]) as usize; let length = evaluate_int(args[1]) as usize;
console::log_1(&format!("WASM(array): input: {:?} -> {:?}", args, value_encoded).into()); console::log_1(&format!("WASM(array): input: {:?} -> {:?}", args, value_encoded).into());

View File

@ -5,17 +5,13 @@ include_definition_file!("src/input.json");
#[wasm_bindgen] #[wasm_bindgen]
pub fn execute(args: &[i32]) -> Vec<i32> { pub fn execute(args: &[i32]) -> Vec<i32> {
let mut result = Vec::with_capacity(args.len() + 7); let mut result = Vec::with_capacity(args.len() + 3);
result.push(0);
result.push(1);
result.push(0); // encoding the [ bracket result.push(0); // encoding the [ bracket
result.push(args[1] + 1); result.push(args[1] + 1);
result.push(0); // adding the node-type, math: 0 result.push(0); // adding the node-type, math: 0
result.extend_from_slice(&args[2..]); result.extend_from_slice(&args[2..]);
result.push(1);
result.push(1); // closing bracket
result.push(1); result.push(1);
result.push(1); // closing bracket result.push(1); // closing bracket
result result

6
nodes/max/plantarium/noise/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/target
**/*.rs.bk
Cargo.lock
bin/
pkg/
wasm-pack.log

View File

@ -0,0 +1,28 @@
[package]
name = "noise"
version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"]
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.
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"

View File

@ -0,0 +1,6 @@
{
"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'"
}
}

View File

@ -0,0 +1,21 @@
{
"id": "max/plantarium/noise",
"outputs": [
"plant"
],
"inputs": {
"plant": {
"type": "plant"
},
"scale": {
"type": "float",
"min": 0.1,
"max": 100
},
"strength": {
"type": "float",
"min": 0.1,
"max": 100
}
}
}

View File

@ -0,0 +1,14 @@
use macros::include_definition_file;
use utils::{concat_args, get_args, log};
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json");
#[rustfmt::skip]
#[wasm_bindgen]
pub fn execute(input: &[i32]) -> Vec<i32> {
let args = get_args(input);
let plants = get_args(args[0]);
log!("noise plants: {:?}", plants);
concat_args(vec![plants[0].to_vec()])
}

View File

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

View File

@ -1,7 +1,7 @@
use glam::{Mat4, Vec3}; use glam::{Mat4, Vec3};
use macros::include_definition_file; use macros::include_definition_file;
use utils::{ use utils::{
concat_args, evaluate_arg, concat_args, evaluate_int,
geometry::{extrude_path, transform_geometry}, geometry::{extrude_path, transform_geometry},
get_args, log, get_args, log,
}; };
@ -10,13 +10,17 @@ use wasm_bindgen::prelude::*;
include_definition_file!("src/inputs.json"); include_definition_file!("src/inputs.json");
#[wasm_bindgen] #[wasm_bindgen]
pub fn execute(input: Vec<i32>) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
utils::set_panic_hook(); utils::set_panic_hook();
let args = get_args(input.as_slice()); log!("output input: {:?}", input);
let args = get_args(input);
log!("output args: {:?}", args);
let inputs = get_args(args[0]); let inputs = get_args(args[0]);
let resolution = evaluate_arg(args[1]) as usize; let resolution = evaluate_int(args[1]) as usize;
log!("inputs: {}, resolution: {}", inputs.len(), resolution); log!("inputs: {}, resolution: {}", inputs.len(), resolution);
@ -26,13 +30,19 @@ pub fn execute(input: Vec<i32>) -> Vec<i32> {
continue; continue;
} }
if arg[2] == 0 { let arg_type = arg[0];
log!("arg: {:?}", arg);
if arg_type == 0 {
// this is stem
let _arg = &arg[3..]; let _arg = &arg[3..];
let mut geometry = extrude_path(_arg, resolution); let mut geometry = extrude_path(_arg, resolution);
let matrix = Mat4::from_translation(Vec3::new(0.0, 0.0, 0.0)); let matrix = Mat4::from_translation(Vec3::new(0.0, 0.0, 0.0));
geometry = transform_geometry(geometry, matrix); geometry = transform_geometry(geometry, matrix);
output.push(geometry); output.push(geometry);
} else if arg[2] == 1 { } else if arg_type == 1 {
// this is geometry
output.push(arg.to_vec()); output.push(arg.to_vec());
} }
} }

View File

@ -1,5 +1,5 @@
use macros::include_definition_file; use macros::include_definition_file;
use utils::{evaluate_arg, evaluate_float, evaluate_vec3, get_args, set_panic_hook, wrap_arg}; use utils::{evaluate_float, evaluate_int, evaluate_vec3, get_args, log, set_panic_hook, wrap_arg};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); include_definition_file!("src/input.json");
@ -10,22 +10,30 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
let args = get_args(input); let args = get_args(input);
log!("node-stem: {:?}", args);
let origin = evaluate_vec3(args[0]); let origin = evaluate_vec3(args[0]);
let length = evaluate_float(args[1]); let length = evaluate_float(args[1]);
let thickness = evaluate_float(args[2]); let thickness = evaluate_float(args[2]);
let res_curve = evaluate_arg(args[3]) as usize; let res_curve = evaluate_int(args[3]) as usize;
let mut path: Vec<i32> = vec![0; res_curve * 4 + 1]; log!("origin: {:?}", origin);
path.resize(res_curve * 4 + 1, 0);
let slice = &mut path[1..]; let amount_points = res_curve * 4;
// +4 for opening and closing brackets and +1 node-type
let output_size = amount_points + 5;
let mut path: Vec<i32> = vec![0; output_size];
path[0] = 0; // encode opening bracket
path[1] = res_curve as i32 * 4 + 4; // encode opening bracket
path[2] = 0; // encode node-type, stem: 0
path[output_size - 2] = 1; // encode closing bracket
path[output_size - 1] = 1; // encode closing bracket
let slice = &mut path[3..output_size - 2];
// Unsafe code to transmute the i32 slice to an f32 slice
let path_p: &mut [f32] = unsafe { let path_p: &mut [f32] = unsafe {
// Ensure that the length of the slice is a multiple of 4
assert_eq!(slice.len() % 4, 0); assert_eq!(slice.len() % 4, 0);
// Transmute the i32 slice to an f32 slice
std::slice::from_raw_parts_mut(slice.as_ptr() as *mut f32, slice.len()) std::slice::from_raw_parts_mut(slice.as_ptr() as *mut f32, slice.len())
}; };
@ -37,5 +45,7 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
path_p[i * 4 + 3] = thickness * (1.0 - a); path_p[i * 4 + 3] = thickness * (1.0 - a);
} }
wrap_arg(&path) log!("res: {:?}", path);
path
} }

View File

@ -1,5 +1,5 @@
use macros::include_definition_file; use macros::include_definition_file;
use utils::{decode_float, encode_float, evaluate_arg, get_args, wrap_arg}; use utils::{decode_float, encode_float, evaluate_int, get_args, wrap_arg};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use web_sys::console; use web_sys::console;
@ -13,7 +13,7 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
let args = get_args(input); let args = get_args(input);
let size = evaluate_arg(args[0]); let size = evaluate_int(args[0]);
let decoded = decode_float(size); let decoded = decode_float(size);
let negative_size = encode_float(-decoded); let negative_size = encode_float(-decoded);

View File

@ -1,20 +1,9 @@
use macros::include_definition_file; use macros::include_definition_file;
use utils::log;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); include_definition_file!("src/input.json");
#[wasm_bindgen] #[wasm_bindgen]
pub fn execute(args: &[i32]) -> Vec<i32> { pub fn execute(input: &[i32]) -> Vec<i32> {
let mut result = Vec::with_capacity(args.len() + 2); input.to_vec()
result.push(0); // encoding the [ bracket
result.push(args[1]);
result.extend_from_slice(&args[2..]);
result.push(1);
result.push(1); // closing bracket
log!("WASM(vec3): res {:?}", result);
result
} }

View File

@ -1,6 +1,6 @@
type SparseArray<T = number> = (T | T[] | SparseArray<T>)[]; type SparseArray<T = number> = (T | T[] | SparseArray<T>)[];
export function concat_encoded(input: (number | number[])[]): number[] { export function concatEncodedArrays(input: (number | number[])[]): number[] {
if (input.length === 1 && Array.isArray(input[0])) { if (input.length === 1 && Array.isArray(input[0])) {
return input[0] return input[0]
@ -26,11 +26,13 @@ export function concat_encoded(input: (number | number[])[]): number[] {
} }
} }
result.push(1, 1); // closing bracket
return result return result
} }
// Encodes a nested array into a flat array with bracket and distance notation // Encodes a nested array into a flat array with bracket and distance notation
export function encode(array: SparseArray): number[] { export function encodeNestedArray(array: SparseArray): number[] {
const encoded = [0, 0]; // Initialize encoded array with root bracket notation const encoded = [0, 0]; // Initialize encoded array with root bracket notation
let missingBracketIndex = 1; // Track where to insert the distance to the next bracket let missingBracketIndex = 1; // Track where to insert the distance to the next bracket
@ -44,7 +46,7 @@ export function encode(array: SparseArray): number[] {
encoded.push(0, 1, 1, 1); encoded.push(0, 1, 1, 1);
} else { } else {
// Recursively encode non-empty arrays // Recursively encode non-empty arrays
const child = encode(item); const child = encodeNestedArray(item);
encoded.push(...child, 1, 0); encoded.push(...child, 1, 0);
} }
// Update missingBracketIndex to the position of the newly added bracket // Update missingBracketIndex to the position of the newly added bracket
@ -59,7 +61,12 @@ export function encode(array: SparseArray): number[] {
return encoded; return encoded;
}; };
function decode_recursive(dense: number[], index = 0) { function decode_recursive(dense: number[] | Int32Array, index = 0) {
if (dense instanceof Int32Array) {
dense = Array.from(dense)
}
const decoded: (number | number[])[] = []; const decoded: (number | number[])[] = [];
let nextBracketIndex = dense[index + 1] + index + 1; // Calculate the index of the next bracket let nextBracketIndex = dense[index + 1] + index + 1; // Calculate the index of the next bracket
@ -83,6 +90,6 @@ function decode_recursive(dense: number[], index = 0) {
return [decoded, index, nextBracketIndex] as const; return [decoded, index, nextBracketIndex] as const;
} }
export function decode(dense: number[]) { export function decodeNestedArray(dense: number[] | Int32Array) {
return decode_recursive(dense, 0)[0]; return decode_recursive(dense, 0)[0];
} }

View File

@ -67,7 +67,7 @@ pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
let i_index_offset = index_offset + j * 6; let i_index_offset = index_offset + j * 6;
let i_position_offset = position_offset + j; let i_position_offset = position_offset + j;
log!("i: {}, j: {}, i_index_offset: {}, i_position_offset: {} res_x: {}", i, j, i_index_offset, i_position_offset,res_x); //log!("i: {}, j: {}, i_index_offset: {}, i_position_offset: {} res_x: {}", i, j, i_index_offset, i_position_offset,res_x);
if j == res_x - 1 { if j == res_x - 1 {
indices[i_index_offset ] = (i_position_offset + 1) as i32; indices[i_index_offset ] = (i_position_offset + 1) as i32;

View File

@ -39,9 +39,13 @@ pub fn get_args(args: &[i32]) -> Vec<&[i32]> {
// skip over the bracket encoding // skip over the bracket encoding
idx += 2; idx += 2;
} else { } else {
if depth == 1 {
arg_start_index = idx + 2;
}
// skip to the next bracket if we are at depth > 0 // skip to the next bracket if we are at depth > 0
idx = next_bracket_index; idx = next_bracket_index;
} }
continue; continue;
} }
@ -56,6 +60,12 @@ pub fn get_args(args: &[i32]) -> Vec<&[i32]> {
idx += 1; idx += 1;
} }
println!("idx: {}, length: {}, asi: {}", idx, length, arg_start_index);
if arg_start_index < length {
out_args.push(&args[arg_start_index..]);
}
out_args out_args
} }
@ -101,6 +111,8 @@ pub fn wrap_arg(arg: &[i32]) -> Vec<i32> {
pub fn evaluate_node(input_args: &[i32]) -> i32 { pub fn evaluate_node(input_args: &[i32]) -> i32 {
let node_type = input_args[0]; let node_type = input_args[0];
println!("node_type: {} -> {:?}", node_type, input_args);
match node_type { match node_type {
0 => crate::nodes::math_node(&input_args[1..]), 0 => crate::nodes::math_node(&input_args[1..]),
1 => crate::nodes::random_node(&input_args[1..]), 1 => crate::nodes::random_node(&input_args[1..]),
@ -109,12 +121,21 @@ pub fn evaluate_node(input_args: &[i32]) -> i32 {
} }
pub fn evaluate_vec3(input_args: &[i32]) -> Vec<f32> { pub fn evaluate_vec3(input_args: &[i32]) -> Vec<f32> {
if input_args.len() == 3 {
return vec![
decode_float(input_args[0]),
decode_float(input_args[1]),
decode_float(input_args[2]),
];
}
let args = get_args(input_args); let args = get_args(input_args);
assert!( assert!(
args.len() == 3, args.len() == 3,
"Failed to evaluate Vec3 - Expected 3 arguments, got {}", "Failed to evaluate Vec3 - Expected 3 arguments, got {} \n {:?}",
args.len() args.len(),
args
); );
let x = evaluate_float(args[0]); let x = evaluate_float(args[0]);
@ -125,16 +146,18 @@ pub fn evaluate_vec3(input_args: &[i32]) -> Vec<f32> {
} }
pub fn evaluate_float(arg: &[i32]) -> f32 { pub fn evaluate_float(arg: &[i32]) -> f32 {
decode_float(evaluate_arg(arg)) decode_float(evaluate_int(arg))
} }
pub fn evaluate_arg(input_args: &[i32]) -> i32 { pub fn evaluate_int(input_args: &[i32]) -> i32 {
if input_args.len() == 1 { if input_args.len() == 1 {
return input_args.to_vec()[0]; return input_args[0];
} }
let args = get_args(input_args); let args = get_args(input_args);
println!("args: {:?}", args);
let mut resolved: Vec<i32> = Vec::new(); let mut resolved: Vec<i32> = Vec::new();
for arg in args { for arg in args {
@ -144,7 +167,7 @@ pub fn evaluate_arg(input_args: &[i32]) -> i32 {
resolved.push(arg[2]); resolved.push(arg[2]);
resolved.push(arg[3]); resolved.push(arg[3]);
} else { } else {
resolved.push(evaluate_arg(arg)); resolved.push(evaluate_int(arg));
} }
} }
@ -160,6 +183,32 @@ mod tests {
use super::*; use super::*;
#[rustfmt::skip]
#[test]
fn test_split_args() {
let input = [
0, 1, 0, 28, 0, 2, 1048576000, 0, 20, 0, 4, 0, 0, 1073741824, 0, 9, 0, 5, 0, 0,
1073741824, 1073741824, 1, 1, 1, 0, 1, 1, 1, 4, 1041865114, 1, 5, 1086324736,
1053609165, 54,
];
// this should be the output
/* [
[ 0, 2, 1048576000, 0, 20, 0, 4, 0, 0, 1073741824, 0, 9, 0, 5, 0, 0, 1073741824, 1073741824, 1, 1, 1, 0, 1, 1, 1, 4, 1041865114 ],
1086324736,
1053609165,
54
] */
let args = get_args(&input);
println!("{:?}", args[0]);
assert_eq!(args[0].len(), 27);
assert_eq!(args[1][0], 1086324736);
assert_eq!(args[2][0], 1053609165);
}
#[test] #[test]
fn test_recursive_evaluation() { fn test_recursive_evaluation() {
let input = vec![ let input = vec![

View File

@ -2,3 +2,4 @@ packages:
- app - app
- packages/* - packages/*
- nodes/**/**/**/* - nodes/**/**/**/*
- '!**/.template'