feat: testing on how to flatten tree structures

This commit is contained in:
2024-04-05 16:45:57 +02:00
parent 473f696626
commit 68d1bac572
23 changed files with 348 additions and 307 deletions

View File

@ -24,7 +24,7 @@
"input-elements": "link:../packages/input-elements",
"jsondiffpatch": "^0.6.0",
"meshline": "^3.2.0",
"plantarium-nodes-math": "link:../nodes/math/pkg",
"plantarium-nodes-math": "link:../nodes/max/plantarium/math/pkg",
"three": "^0.159.0",
"three.meshline": "^1.4.0"
},

View File

@ -53,7 +53,7 @@
<div class="wrapper" data-node-id={node.id}>
<div class="content">
{node.type} / {node.id}
{node.type.split("/").pop()}
</div>
<div
class="click-target"

View File

@ -5,17 +5,17 @@
export let node: Node;
export let input: NodeInput;
export let id: string;
export let label: string;
const graph = getGraphManager();
let value = node?.props?.[id] ?? input.value;
let value = node?.props?.[label] ?? input.value;
$: if (node?.props?.[id] !== value) {
node.props = { ...node.props, [id]: value };
$: if (node?.props?.[label] !== value) {
node.props = { ...node.props, [label]: value };
graph.execute();
}
</script>
<label for="asd">{id}</label>
<label for="asd">{label}</label>
<Input {input} bind:value />

View File

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

View File

@ -1,5 +1,5 @@
import { writable, type Writable } from "svelte/store";
import type { Graph, Node, Edge, Socket, NodeRegistry, RuntimeExecutor, } from "@nodes/s";
import type { Graph, Node, Edge, Socket, NodeRegistry, RuntimeExecutor, } from "@nodes/s";
import { HistoryManager } from "./history-manager";
import * as templates from "./graphs";
import EventEmitter from "./helpers/EventEmitter";
@ -145,6 +145,8 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> {
this.status.set("loading");
this.id.set(graph.id);
this.nodeRegistry.load();
for (const node of this.graph.nodes) {
const nodeType = this.nodeRegistry.getNode(node.type);
if (!nodeType) {
@ -165,6 +167,7 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> {
this.loaded = true;
logger.log(`Graph loaded in ${performance.now() - a}ms`);
setTimeout(() => this.execute(), 100);
}

View File

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

View File

@ -10,7 +10,7 @@ export function tree(depth: number): Graph {
},
{
id: 1,
type: "math",
type: "max/plantarium/math",
position: [-40, -10]
}
]
@ -33,13 +33,13 @@ export function tree(depth: number): Graph {
nodes.push({
id: id0,
type: "math",
type: "max/plantarium/math",
position: [x, y],
});
edges.push([id0, 0, parent, "a"]);
nodes.push({
id: id1,
type: "math",
type: "max/plantarium/math",
position: [x, y + 35],
});
edges.push([id1, 0, parent, "b"]);

View File

@ -1,22 +1,58 @@
import type { NodeRegistry, NodeType } from "@nodes/types";
import * as d from "plantarium-nodes-math";
function binaryArrayToNumber(binaryArray: number[]): number {
let result = 0;
for (let i = 0; i < binaryArray.length; i++) {
result = (result << 1) + binaryArray[i];
}
return result;
}
const nodeTypes: NodeType[] = [
{
id: "input/float",
id: "max/plantarium/input-float",
inputs: {
"value": { type: "float", value: 0.1, internal: true },
},
outputs: ["float"],
execute: ({ value }) => { return value }
execute: ({ value }) => { return [0, 1, 0, value] }
},
{
id: d.get_id(),
inputs: JSON.parse(d.get_input_types()),
outputs: d.get_outputs(),
execute: ({ op_type, a, b }) => {
return d.execute(op_type, a, b);
id: "max/plantarium/math",
inputs: {
"op_type": { title: "type", type: "select", labels: ["add", "subtract", "multiply", "divide"], value: 0 },
"a": { type: "float" },
"b": { type: "float" },
},
outputs: ["float"],
execute: ({ op_type, a, b }: { op_type: number, a: number, b: number }) => {
const res = [1, 3, -1, op_type, 0, 0];
const bitmask = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
console.log({ a, b });
if (Array.isArray(a)) {
res[4] = res.length;
res.push(...a);
bitmask[1] = 1;
console.log("A", res.length, a.length);
} else {
res[4] = a;
}
if (Array.isArray(b)) {
res[5] = res.length;
res.push(...b);
bitmask[2] = 1;
} else {
res[5] = b;
}
res[2] = binaryArrayToNumber(bitmask);
return res
}
},
{
@ -28,11 +64,41 @@ const nodeTypes: NodeType[] = [
}
]
export class RemoteNodeRegistry implements NodeRegistry {
private nodes: Map<string, NodeType> = new Map();
constructor(private url: string) { }
async load(nodeIds: string[]) {
for (const id of nodeIds) {
const response = await fetch(`${this.url}/nodes/${id}`);
const node = this.getNode(id);
if (node) {
this.nodes.set(id, node);
}
}
}
getNode(id: string) {
return this.nodes.get(id);
}
getAllNodes() {
return [...this.nodes.values()];
}
}
export class MemoryNodeRegistry implements NodeRegistry {
getNode(id: string): NodeType | undefined {
async load(nodeIds: string[]) {
// Do nothing
}
getNode(id: string) {
return nodeTypes.find((nodeType) => nodeType.id === id);
}
getAllNodes(): NodeType[] {
getAllNodes() {
return [...nodeTypes];
}
}

View File

@ -1,5 +1,93 @@
import type { Graph, NodeRegistry, NodeType, RuntimeExecutor } from "@nodes/types";
function numberToBinaryArray(number: number): number[] {
const binaryArray: number[] = [];
for (let i = 31; i >= 0; i--) {
const bit = (number >> i) & 1;
binaryArray.push(bit);
}
return binaryArray;
}
function evaluate_node([node_type, ...args]: number[]) {
// Float node
if (node_type === 0) {
return args[0];
}
console.log(args);
// Math node
if (node_type === 1) {
if (args[0] === 0) {
return args[1] + args[2];
} else if (args[0] === 1) {
return args[1] - args[2];
} else if (args[0] === 2) {
return args[1] * args[1];
} else {
return args[1] / args[2];
}
}
}
function read_node(index: number, params: number[], depth = 0) {
if (depth > 20) {
throw new Error("Max depth reached");
}
const node_type = params[index];
const amount_of_args = params[index + 1];
const bitmask = params[index + 2];
console.log("READ_NODE", index, { node_type, bitmask, amount_of_args });
const mask = numberToBinaryArray(bitmask);
// there are not nodes connected to this node, lets evaluate
if (bitmask === 0) {
console.log("EVALUATE", index, params);
}
const args = [];
for (let i = 0; i < amount_of_args; i++) {
const isNode = mask[i] === 1;
if (isNode) {
console.log("NODE", index + 3 + i, params.slice(index + 3 + i, index + 3 + i + 5));
args[i] = read_node(params[index + 3 + i], params, depth + 1);
} else {
args[i] = params[index + 3 + i];
}
}
console.log({ node_type, amount_of_args, args, bitmask });
return evaluate_node([node_type, ...args]);
}
function split_params(params: number[]) {
const result = [];
let index = 0;
while (index < params.length) {
const amount_of_args = params[index + 1];
const node_size = 3 + amount_of_args;
result.push(params.slice(index, index + node_size));
index += node_size;
}
return result;
}
function evaluate(params: number[]) {
console.log("PARAMS", split_params(params));
const node = read_node(0, params);
console.log("RESULT: ", node);
}
export class MemoryRuntimeExecutor implements RuntimeExecutor {
constructor(private registry: NodeRegistry) { }
@ -130,7 +218,12 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
}
// return the result of the parent of the output node
return results[outputNode.tmp?.parents?.[0].id as number] as string
const res = results[outputNode.tmp?.parents?.[0].id as number] as string
evaluate(res);
return res;
}