feat: some stuff

This commit is contained in:
max_richter 2024-04-05 19:38:10 +02:00
parent b3780fdf96
commit 0ecf9798c4
22 changed files with 157 additions and 66 deletions

27
Cargo.lock generated
View File

@ -950,6 +950,18 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "float"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"plantarium",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -1626,18 +1638,6 @@ dependencies = [
"cfb", "cfb",
] ]
[[package]]
name = "input-float"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"plantarium",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-test",
]
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -2234,6 +2234,7 @@ dependencies = [
"plantarium", "plantarium",
"serde", "serde",
"serde-wasm-bindgen", "serde-wasm-bindgen",
"serde_json",
"wasm-bindgen", "wasm-bindgen",
"wasm-bindgen-test", "wasm-bindgen-test",
] ]
@ -2486,6 +2487,8 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
name = "plantarium" name = "plantarium"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"serde",
"serde_json",
"wasm-bindgen", "wasm-bindgen",
] ]

View File

@ -111,7 +111,8 @@
if (!node?.inputs) { if (!node?.inputs) {
return 5; return 5;
} }
const height = 5 + 10 * Object.keys(node.inputs).length; const height =
5 + 10 * Object.keys(node.inputs).filter((i) => i !== "seed").length;
nodeHeightCache[nodeTypeId] = height; nodeHeightCache[nodeTypeId] = height;
return height; return height;
} }
@ -385,6 +386,17 @@
function handleMouseDown(event: MouseEvent) { function handleMouseDown(event: MouseEvent) {
if (mouseDown) return; if (mouseDown) return;
if (event.target instanceof HTMLElement) {
if (
event.target.nodeName !== "CANVAS" &&
!event.target.classList.contains("node") &&
!event.target.classList.contains("content")
) {
return;
}
}
mouseDown = [event.clientX, event.clientY]; mouseDown = [event.clientX, event.clientY];
cameraDown[0] = cameraPosition[0]; cameraDown[0] = cameraPosition[0];
cameraDown[1] = cameraPosition[1]; cameraDown[1] = cameraPosition[1];

View File

@ -23,7 +23,9 @@
const type = node?.tmp?.type; const type = node?.tmp?.type;
const parameters = Object.entries(type?.inputs || {}); const parameters = Object.entries(type?.inputs || {}).filter(
(p) => p[1].type !== "seed",
);
let ref: HTMLDivElement; let ref: HTMLDivElement;
let meshRef: Mesh; let meshRef: Mesh;

View File

@ -71,7 +71,7 @@
{#key id && graphId} {#key id && graphId}
{#if node?.tmp?.type?.inputs?.[id]?.external !== true} {#if node?.tmp?.type?.inputs?.[id]?.external !== true}
<div class="content" class:disabled={$inputSockets.has(socketId)}> <div class="content" class:disabled={$inputSockets.has(socketId)}>
<NodeInput {node} {input} {id} label={input.title} /> <NodeInput {node} {input} {id} label={input.label} />
</div> </div>
{/if} {/if}

View File

@ -20,8 +20,8 @@ export function grid(width: number, height: number) {
visible: false, visible: false,
}, },
position: [x * 30, y * 40], position: [x * 30, y * 40],
props: i == 0 ? { value: 0 } : { op_type: 1, a: 2, b: i }, props: i == 0 ? { value: 0 } : { op_type: 2, a: 2, b: 2 },
type: i == 0 ? "max/plantarium/input-float" : "max/plantarium/math", type: i == 0 ? "max/plantarium/float" : "max/plantarium/math",
}); });
graph.edges.push([i, 0, i + 1, i === amount - 1 ? "input" : "a",]); graph.edges.push([i, 0, i + 1, i === amount - 1 ? "input" : "a",]);

View File

@ -1,11 +1,10 @@
import type { NodeRegistry, NodeType } from "@nodes/types"; import type { NodeRegistry, NodeType } from "@nodes/types";
import * as d from "plantarium-nodes-math";
import { createLogger } from "./helpers"; import { createLogger } from "./helpers";
const nodeTypes: NodeType[] = [ const nodeTypes: NodeType[] = [
{ {
id: "max/plantarium/input-float", id: "max/plantarium/float",
inputs: { inputs: {
"value": { type: "float", value: 0.1, internal: true }, "value": { type: "float", value: 0.1, internal: true },
}, },
@ -48,6 +47,8 @@ export class RemoteNodeRegistry implements NodeRegistry {
async load(nodeIds: string[]) { async load(nodeIds: string[]) {
const a = performance.now(); const a = performance.now();
nodeIds.push("max/plantarium/random");
nodeIds.push("max/plantarium/float");
for (const id of nodeIds) { for (const id of nodeIds) {
const nodeUrl = `${this.url}/n/${id}`; const nodeUrl = `${this.url}/n/${id}`;
const response = await fetch(nodeUrl); const response = await fetch(nodeUrl);
@ -70,10 +71,7 @@ wasm = val;`);
throw new Error(`Failed to load node ${id}`); throw new Error(`Failed to load node ${id}`);
} }
const node = await response.json(); const node = await response.json();
node.execute = (...args) => { node.execute = wasmWrapper.execute;
console.log("Executing", id, args);
return wasmWrapper.execute(...args)
};
this.nodes.set(id, node); this.nodes.set(id, node);
} }

View File

@ -101,7 +101,6 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
// we execute the nodes from the bottom up // we execute the nodes from the bottom up
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, string | boolean | number> = {};
@ -110,6 +109,11 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
const inputs: Record<string, string | number | boolean> = {}; const inputs: Record<string, string | number | boolean> = {};
for (const [key, input] of Object.entries(node.tmp.type.inputs || {})) { for (const [key, input] of Object.entries(node.tmp.type.inputs || {})) {
if (input.type === "seed") {
inputs[key] = Math.floor(Math.random() * 100000000);
continue;
}
// check if the input is connected to another node // check if the input is connected to another node
const inputNode = node.tmp.inputNodes?.[key]; const inputNode = node.tmp.inputNodes?.[key];
if (inputNode) { if (inputNode) {
@ -122,6 +126,7 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
// if the input is not connected to another node, we use the value from the node itself // if the input is not connected to another node, we use the value from the node itself
inputs[key] = node.props?.[key] ?? input?.value; inputs[key] = node.props?.[key] ?? input?.value;
} }
// execute the node and store the result // execute the node and store the result

View File

@ -39,9 +39,14 @@
<br /> <br />
<button <button
on:click={() => on:click={() =>
graphManager.load(graphManager.createTemplate("grid", 3, 3))} graphManager.load(graphManager.createTemplate("grid", 10, 10))}
>load grid</button >load grid</button
> >
<button
on:click={() =>
graphManager.load(graphManager.createTemplate("grid", 2, 2))}
>load small grid</button
>
<br /> <br />
<br /> <br />
<JsonView json={debug} /> <JsonView json={debug} />

View File

@ -1,5 +1,5 @@
[package] [package]
name = "input-float" name = "float"
version = "0.1.0" version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"] authors = ["Max Richter <jim-x@web.de>"]
edition = "2018" edition = "2018"

View File

@ -7,11 +7,6 @@ pub fn get_outputs() -> Vec<String> {
vec!["float".to_string()] vec!["float".to_string()]
} }
#[wasm_bindgen]
pub fn get_id() -> String {
"float".to_string()
}
#[wasm_bindgen] #[wasm_bindgen]
pub fn get_input_types() -> String { pub fn get_input_types() -> String {
utils::set_panic_hook(); utils::set_panic_hook();

View File

@ -8,16 +8,11 @@ pub fn get_outputs() -> Vec<String> {
vec!["float".to_string()] vec!["float".to_string()]
} }
#[wasm_bindgen]
pub fn get_id() -> String {
"math".to_string()
}
#[wasm_bindgen] #[wasm_bindgen]
pub fn get_input_types() -> String { pub fn get_input_types() -> String {
utils::set_panic_hook(); utils::set_panic_hook();
r#"{ r#"{
"op_type": { "type": "select", "labels": ["add", "subtract", "multiply", "divide"], "internal": true, "value": 0 }, "op_type": { "label": "type", "type": "select", "labels": ["add", "subtract", "multiply", "divide"], "internal": true, "value": 0 },
"a": { "type": "float", "value": 2 }, "a": { "type": "float", "value": 2 },
"b": { "type": "float", "value": 2 } "b": { "type": "float", "value": 2 }
}"#.to_string() }"#.to_string()
@ -44,7 +39,7 @@ pub fn execute(var_op_type: u8, var_a: JsValue, var_b: JsValue) -> String {
// Interpolate strings into JSON format // Interpolate strings into JSON format
let json_string = format!( let json_string = format!(
r#"{{"parameter": "math", "op_type": {}, "a": {}, "b": {}}}"#, r#"{{"__type": "math", "op_type": {}, "a": {}, "b": {}}}"#,
var_op_type, a, b var_op_type, a, b
); );

View File

@ -19,6 +19,7 @@ wasm-bindgen = "0.2.84"
# code size when deploying. # code size when deploying.
plantarium = { version = "0.1.0", path = "../../../../packages/plantarium" } plantarium = { version = "0.1.0", path = "../../../../packages/plantarium" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
serde-wasm-bindgen = "0.4" serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true }

View File

@ -1,5 +1,5 @@
mod utils; mod utils;
use plantarium::unwrap_string; use plantarium::evaluate_parameters;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
// lifted from the `console_log` example // lifted from the `console_log` example
@ -14,11 +14,6 @@ pub fn get_outputs() -> Vec<String> {
vec![] vec![]
} }
#[wasm_bindgen]
pub fn get_id() -> String {
"float".to_string()
}
#[wasm_bindgen] #[wasm_bindgen]
pub fn get_input_types() -> String { pub fn get_input_types() -> String {
utils::set_panic_hook(); utils::set_panic_hook();
@ -27,14 +22,11 @@ pub fn get_input_types() -> String {
}"# }"#
.to_string() .to_string()
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn execute(var_value: JsValue) -> String { pub fn execute(var_value: JsValue) -> f64 {
utils::set_panic_hook(); utils::set_panic_hook();
let str = unwrap_string(var_value); let res = evaluate_parameters(var_value);
log(&format!("str: {}", str)); return res;
return str;
} }

View File

@ -1,16 +1,19 @@
mod utils; mod utils;
use plantarium::{unwrap_int, unwrap_string};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
// lifted from the `console_log` example
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[wasm_bindgen] #[wasm_bindgen]
pub fn get_outputs() -> Vec<String> { pub fn get_outputs() -> Vec<String> {
vec!["float".to_string()] vec!["float".to_string()]
} }
#[wasm_bindgen]
pub fn get_id() -> String {
"random".to_string()
}
#[wasm_bindgen] #[wasm_bindgen]
pub fn get_input_types() -> String { pub fn get_input_types() -> String {
utils::set_panic_hook(); utils::set_panic_hook();
@ -23,13 +26,36 @@ pub fn get_input_types() -> String {
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn execute(var_min: String, var_max: String, var_seed: i32) -> String { pub fn execute(var_min: JsValue, var_max: JsValue, var_seed: JsValue) -> String {
utils::set_panic_hook(); utils::set_panic_hook();
let min: String;
if var_min.is_string() {
min = unwrap_string(var_min);
} else {
min = unwrap_int(var_min).to_string();
}
let max: String;
if var_max.is_string() {
max = unwrap_string(var_max);
} else {
max = unwrap_int(var_max).to_string();
}
let seed: String;
if var_seed.is_string() {
seed = unwrap_string(var_seed);
} else {
seed = unwrap_int(var_seed).to_string();
}
log(&format!("min: {}, max: {}, seed: {}", min, max, seed));
// Interpolate strings into JSON format // Interpolate strings into JSON format
let json_string = format!( let json_string = format!(
r#"{{"parameter": "random", "min": {}, "max": {}, "seed": {}}}"#, r#"{{"__type": "random", "min": {}, "max": {}, "seed": {}}}"#,
var_min, var_max, var_seed min, max, seed
); );
json_string json_string

View File

@ -35,10 +35,9 @@ export async function getNode(id: `${string}/${string}/${string}`) {
const wrapper = await getNodeWasm(id); const wrapper = await getNodeWasm(id);
const node_id = wrapper.get_id();
const outputs = wrapper.get_outputs(); const outputs = wrapper.get_outputs();
const inputTypes = JSON.parse(wrapper.get_input_types()); const inputTypes = JSON.parse(wrapper.get_input_types());
return { id: node_id, outputs, inputs: inputTypes } return { id, outputs, inputs: inputTypes }
} }

View File

@ -5,3 +5,5 @@ edition = "2021"
[dependencies] [dependencies]
wasm-bindgen = "0.2.92" wasm-bindgen = "0.2.92"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }

View File

@ -1,10 +1,13 @@
use std::cell::RefCell;
use serde_json::Value;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
pub fn unwrap_int(val: JsValue) -> u8 { pub fn unwrap_int(val: JsValue) -> i32 {
if val.is_undefined() || val.is_null() { if val.is_undefined() || val.is_null() {
panic!("Value is undefined"); panic!("Value is undefined");
} }
return val.as_f64().unwrap() as u8; return val.as_f64().unwrap() as i32;
} }
pub fn unwrap_float(val: JsValue) -> f64 { pub fn unwrap_float(val: JsValue) -> f64 {
@ -21,6 +24,55 @@ pub fn unwrap_string(val: JsValue) -> String {
return val.as_string().unwrap(); return val.as_string().unwrap();
} }
pub fn evaluate_parameter(_val: String) -> i32 { pub fn evaluate_parameters(val: JsValue) -> f64 {
return 2; let str = unwrap_string(val);
let v: Value = serde_json::from_str(&str).unwrap();
let index = RefCell::new(0.0);
return walk_json(&v, &index);
}
fn walk_json(value: &Value, depth: &RefCell<f64>) -> f64 {
*depth.borrow_mut() += 1.0;
match value {
// If it's an object, recursively walk through its fields
Value::Object(obj) => {
let obj_type = obj.get("__type").unwrap();
if obj_type == "random" {
let min = walk_json(obj.get("min").unwrap(), depth);
let max = walk_json(obj.get("max").unwrap(), depth);
let seed = (obj.get("seed").unwrap().as_f64().unwrap() + *depth.borrow() * 2000.0)
/ 1000000.0;
let range = max - min;
let seed = seed % range;
return seed - min;
} else if obj_type == "math" {
let a = walk_json(obj.get("a").unwrap(), depth);
let b = walk_json(obj.get("b").unwrap(), depth);
let op_type = obj.get("op_type").unwrap();
if op_type == 0 {
return a + b;
} else if op_type == 1 {
return a - b;
} else if op_type == 2 {
return a * b;
} else if op_type == 3 {
return a / b;
}
}
return 0.0;
}
Value::Array(arr) => {
for val in arr {
walk_json(val, depth);
}
return 0.0;
}
Value::Number(num) => {
return num.as_f64().unwrap();
}
// If it's a primitive value, print it
_ => {
return 0.0;
}
}
} }

View File

@ -24,13 +24,17 @@ type NodeInputSelect = {
value?: number; value?: number;
} }
type NodeInputSeed = {
type: "seed"
}
type DefaultOptions = { type DefaultOptions = {
internal?: boolean; internal?: boolean;
external?: boolean; external?: boolean;
title?: string; label?: string;
} }
export type NodeInput = (NodeInputBoolean | NodeInputFloat | NodeInputInteger | NodeInputSelect) & DefaultOptions; export type NodeInput = (NodeInputSeed | NodeInputBoolean | NodeInputFloat | NodeInputInteger | NodeInputSelect) & DefaultOptions;
export type NodeInputType<T extends Record<string, NodeInput>> = { export type NodeInputType<T extends Record<string, NodeInput>> = {