feat: load props from node store
This commit is contained in:
parent
f1e537d596
commit
f0ccbf808e
@ -384,8 +384,6 @@ export class GraphManager extends EventEmitter<{ "save": Graph, "result": any, "
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const node: Node = { id: this.createNodeId(), type, position, tmp: { type: nodeType }, props };
|
||||
|
||||
this.nodes.update((nodes) => {
|
||||
|
@ -796,11 +796,19 @@
|
||||
my += parseInt(nodeOffsetY);
|
||||
}
|
||||
|
||||
let props = {};
|
||||
let rawNodeProps = event.dataTransfer.getData("data/node-props");
|
||||
if (rawNodeProps) {
|
||||
try {
|
||||
props = JSON.parse(rawNodeProps);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
const pos = projectScreenToWorld(mx, my);
|
||||
graph.loadNode(nodeId).then(() => {
|
||||
graph.createNode({
|
||||
type: nodeId,
|
||||
props: {},
|
||||
props,
|
||||
position: pos,
|
||||
});
|
||||
});
|
||||
|
@ -15,6 +15,7 @@ const diff = create({
|
||||
})
|
||||
|
||||
const log = createLogger("history")
|
||||
log.mute();
|
||||
|
||||
export class HistoryManager {
|
||||
|
||||
|
@ -6,12 +6,25 @@
|
||||
|
||||
let dragging = false;
|
||||
|
||||
let nodeData = {
|
||||
id: 0,
|
||||
type: node.id,
|
||||
position: [0, 0] as [number, number],
|
||||
props: {},
|
||||
tmp: {
|
||||
type: node,
|
||||
},
|
||||
};
|
||||
|
||||
function handleDragStart(e: DragEvent) {
|
||||
dragging = true;
|
||||
const box = (e?.target as HTMLElement)?.getBoundingClientRect();
|
||||
if (e.dataTransfer === null) return;
|
||||
e.dataTransfer.effectAllowed = "move";
|
||||
e.dataTransfer.setData("data/node-id", node.id);
|
||||
if (nodeData.props) {
|
||||
e.dataTransfer.setData("data/node-props", JSON.stringify(nodeData.props));
|
||||
}
|
||||
e.dataTransfer.setData(
|
||||
"data/node-offset-x",
|
||||
Math.round(box.left - e.clientX).toString(),
|
||||
@ -33,19 +46,7 @@
|
||||
tabindex="0"
|
||||
on:dragstart={handleDragStart}
|
||||
>
|
||||
<NodeHtml
|
||||
inView={true}
|
||||
position={"relative"}
|
||||
z={5}
|
||||
node={{
|
||||
id: 0,
|
||||
type: node.id,
|
||||
position: [0, 0],
|
||||
tmp: {
|
||||
type: node,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<NodeHtml inView={true} position={"relative"} z={5} bind:node={nodeData} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -121,110 +121,80 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
|
||||
const node_type = this.definitionMap.get(node.type)!;
|
||||
|
||||
if (node?.tmp && node_type?.execute) {
|
||||
const inputs: Record<string, string | number | boolean> = {};
|
||||
for (const [key, input] of Object.entries(node_type.inputs || {})) {
|
||||
|
||||
const inputs = Object.entries(node_type.inputs || {}).map(([key, input]) => {
|
||||
|
||||
if (input.type === "seed") {
|
||||
inputs[key] = runSeed;
|
||||
continue;
|
||||
return runSeed;
|
||||
}
|
||||
|
||||
if (input.setting) {
|
||||
if (settings[input.setting] === undefined) {
|
||||
if (input.value !== undefined) {
|
||||
inputs[key] = input.value;
|
||||
if ("value" in input && input.value !== undefined) {
|
||||
if (input.type === "float") {
|
||||
return encodeFloat(input.value);
|
||||
}
|
||||
return input.value;
|
||||
} else {
|
||||
log.warn(`Setting ${input.setting} is not defined`);
|
||||
}
|
||||
} else {
|
||||
inputs[key] = settings[input.setting] as number;
|
||||
if (input.type === "float") {
|
||||
return encodeFloat(settings[input.setting] as number);
|
||||
}
|
||||
return settings[input.setting];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the input is connected to another node
|
||||
const inputNode = node.tmp.inputNodes?.[key];
|
||||
const inputNode = node.tmp?.inputNodes?.[key];
|
||||
if (inputNode) {
|
||||
if (results[inputNode.id] === undefined) {
|
||||
throw new Error("Input node has no result");
|
||||
}
|
||||
inputs[key] = results[inputNode.id];
|
||||
continue;
|
||||
return results[inputNode.id];
|
||||
}
|
||||
|
||||
// if the input is not connected to another node, we use the value from the node itself
|
||||
let value = node.props?.[key] ?? input?.value;
|
||||
if (Array.isArray(value)) {
|
||||
inputs[key] = [0, value.length + 1, ...value, 1, 1];
|
||||
} else {
|
||||
inputs[key] = value;
|
||||
// If the value is stored in the node itself, we use that value
|
||||
if (node.props?.[key] !== undefined) {
|
||||
let value = node.props[key];
|
||||
if (input.type === "vec3") {
|
||||
return [0, 4, ...value.map(v => encodeFloat(v)), 1, 1]
|
||||
} else if (Array.isArray(value)) {
|
||||
return [0, value.length + 1, ...value, 1, 1];
|
||||
} else if (input.type === "float") {
|
||||
return encodeFloat(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
let defaultValue = input.value;
|
||||
if (defaultValue !== undefined) {
|
||||
if (Array.isArray(defaultValue)) {
|
||||
return [0, defaultValue.length + 1, ...defaultValue.map(v => encodeFloat(v)), 1, 1];
|
||||
} else if (input.type === "float") {
|
||||
return encodeFloat(defaultValue);
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Input ${key} is not connected and has no default value`);
|
||||
|
||||
// log.log(" ");
|
||||
// log.log("--> EXECUTING NODE " + node_type.id, node.id);
|
||||
});
|
||||
|
||||
|
||||
// execute the node and store the result
|
||||
try {
|
||||
const a0 = performance.now();
|
||||
|
||||
const node_inputs = Object.entries(inputs);
|
||||
const cacheKey = "123" || `${node.id}/${fastHash(node_inputs.map(([_, value]: [string, any]) => {
|
||||
return value
|
||||
}))}`;
|
||||
|
||||
const a1 = performance.now();
|
||||
// log.log(`${a1 - a0}ms hashed inputs: ${node.id} -> ${cacheKey}`);
|
||||
|
||||
if (false && this.cache[cacheKey] && this.cache[cacheKey].eol > Date.now()) {
|
||||
results[node.id] = this.cache[cacheKey].value;
|
||||
log.log(`Using cached value`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const transformed_inputs = node_inputs.map(([key, value]: [string, any]) => {
|
||||
const input_type = node_type.inputs?.[key]!;
|
||||
if (value instanceof Int32Array) {
|
||||
let _v = new Array(value.length);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
_v[i] = value[i];
|
||||
}
|
||||
return _v;
|
||||
}
|
||||
|
||||
if (input_type.type === "float") {
|
||||
return encodeFloat(value as number);
|
||||
}
|
||||
|
||||
return value;
|
||||
});
|
||||
|
||||
// log.log(transformed_inputs);
|
||||
|
||||
const a2 = performance.now();
|
||||
|
||||
// log.log(`${a2 - a1}ms TRANSFORMED_INPUTS`);
|
||||
|
||||
const encoded_inputs = concatEncodedArrays(transformed_inputs);
|
||||
const a3 = performance.now();
|
||||
const encoded_inputs = concatEncodedArrays(inputs);
|
||||
log.group(`executing ${node_type.id || node.id}`);
|
||||
log.log(`Inputs:`, transformed_inputs);
|
||||
log.log(`Inputs:`, inputs);
|
||||
log.log(`Encoded Inputs:`, encoded_inputs);
|
||||
results[node.id] = node_type.execute(encoded_inputs);
|
||||
log.log("Result:", results[node.id]);
|
||||
log.log("Result (decoded):", decodeNestedArray(results[node.id]));
|
||||
log.groupEnd();
|
||||
const duration = performance.now() - a3;
|
||||
if (duration > 5) {
|
||||
this.cache[cacheKey] = { eol: Date.now() + 10_000, value: results[node.id] };
|
||||
// log.log(`Caching for 10 seconds`);
|
||||
}
|
||||
// log.log(`${duration}ms Executed`);
|
||||
const a4 = performance.now();
|
||||
// log.log(`${a4 - a0}ms e2e duration`);
|
||||
|
||||
} catch (e) {
|
||||
log.groupEnd();
|
||||
log.error(`Error executing node ${node_type.id || node.id}`, e);
|
||||
|
@ -3,7 +3,6 @@
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
import { writable } from "svelte/store";
|
||||
import type { GraphManager } from "$lib/graph-interface/graph-manager";
|
||||
import { encodeFloat } from "@nodes/utils";
|
||||
|
||||
function filterInputs(inputs: Record<string, NodeInput>) {
|
||||
return Object.fromEntries(
|
||||
@ -43,16 +42,11 @@
|
||||
node.props = node.props || {};
|
||||
const key = _key as keyof typeof $store;
|
||||
if (node && $store) {
|
||||
if (Array.isArray($store[key])) {
|
||||
node.props[key] = [...$store[key]].map((v) => encodeFloat(v));
|
||||
needsUpdate = true;
|
||||
} else if (node.props[key] !== $store[key]) {
|
||||
needsUpdate = true;
|
||||
node.props[key] = $store[key];
|
||||
}
|
||||
needsUpdate = true;
|
||||
node.props[key] = $store[key];
|
||||
}
|
||||
});
|
||||
console.log(needsUpdate, node.props, $store);
|
||||
// console.log(needsUpdate, node.props, $store);
|
||||
if (needsUpdate) {
|
||||
manager.execute();
|
||||
}
|
||||
|
@ -25,38 +25,39 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
{#each keys as key}
|
||||
{@const value = settings[key]}
|
||||
<div class="wrapper" class:first-level={depth === 0}>
|
||||
{#if isNodeInput(value)}
|
||||
<div class="input input-{settings[key].type}">
|
||||
{#if settings[key].type === "button"}
|
||||
<button on:click={() => settings[key]?.callback?.()}
|
||||
>{settings[key].label || key}</button
|
||||
>
|
||||
{:else}
|
||||
<label for={key}>{settings[key].label || key}</label>
|
||||
<Input
|
||||
id={key}
|
||||
input={value}
|
||||
bind:value={$store[value?.setting || key]}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
{#if depth > 0}
|
||||
<hr />
|
||||
{/if}
|
||||
|
||||
<details bind:open={$expandedDetails[key]}>
|
||||
<summary>{settings[key]?.__title || key}</summary>
|
||||
<div class="content">
|
||||
<svelte:self settings={settings[key]} {store} depth={depth + 1} />
|
||||
{#if store}
|
||||
{#each keys as key}
|
||||
{@const value = settings[key]}
|
||||
<div class="wrapper" class:first-level={depth === 0}>
|
||||
{#if isNodeInput(value)}
|
||||
<div class="input input-{settings[key].type}">
|
||||
{#if settings[key].type === "button"}
|
||||
<button on:click={() => settings[key]?.callback?.()}
|
||||
>{settings[key].label || key}</button
|
||||
>
|
||||
{:else if "setting" in value}
|
||||
<label for={key}>{settings[key].label || key}</label>
|
||||
<Input id={key} input={value} bind:value={$store[value?.setting]} />
|
||||
{:else}
|
||||
<label for={key}>{settings[key].label || key}</label>
|
||||
<Input id={key} input={value} bind:value={$store[key]} />
|
||||
{/if}
|
||||
</div>
|
||||
</details>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{:else}
|
||||
{#if depth > 0}
|
||||
<hr />
|
||||
{/if}
|
||||
|
||||
<details bind:open={$expandedDetails[key]}>
|
||||
<summary>{settings[key]?.__title || key}</summary>
|
||||
<div class="content">
|
||||
<svelte:self settings={settings[key]} {store} depth={depth + 1} />
|
||||
</div>
|
||||
</details>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
summary {
|
||||
|
@ -14,7 +14,11 @@
|
||||
import NodeStore from "$lib/node-store/NodeStore.svelte";
|
||||
import type { GraphManager } from "$lib/graph-interface/graph-manager";
|
||||
import { setContext } from "svelte";
|
||||
import { decodeNestedArray, encodeNestedArray } from "@nodes/utils";
|
||||
import {
|
||||
decodeFloat,
|
||||
decodeNestedArray,
|
||||
encodeNestedArray,
|
||||
} from "@nodes/utils";
|
||||
import type { PerspectiveCamera, Vector3 } from "three";
|
||||
import type { OrbitControls } from "three/examples/jsm/Addons.js";
|
||||
import ActiveNode from "$lib/settings/ActiveNode.svelte";
|
||||
@ -24,6 +28,7 @@
|
||||
|
||||
globalThis.decode = decodeNestedArray;
|
||||
globalThis.encode = encodeNestedArray;
|
||||
globalThis.decodeFloat = decodeFloat;
|
||||
|
||||
let res: Int32Array;
|
||||
let viewerCamera: PerspectiveCamera;
|
||||
|
@ -21,6 +21,7 @@
|
||||
"type": "float",
|
||||
"label": "Fixate bottom of plant",
|
||||
"hidden": true,
|
||||
"value": 0,
|
||||
"min": 0,
|
||||
"max": 1
|
||||
},
|
||||
|
@ -1,5 +1,4 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
@ -9,6 +9,7 @@
|
||||
export let max: number | undefined = undefined;
|
||||
export let step = 1;
|
||||
export let value = 0;
|
||||
export let id = "";
|
||||
|
||||
if (!value) {
|
||||
value = 0;
|
||||
|
@ -12,7 +12,7 @@ export function concatEncodedArrays(input: (number | number[])[]): number[] {
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
const item = input[i];
|
||||
if (Array.isArray(item)) {
|
||||
if (Array.isArray(item) || item instanceof Int32Array) {
|
||||
result.push(...item);
|
||||
last_closing_bracket = result.length - 1;
|
||||
} else {
|
||||
|
@ -1,5 +1,3 @@
|
||||
use crate::log;
|
||||
|
||||
use super::{create_geometry_data, wrap_geometry_data};
|
||||
use glam::{Mat4, Vec3};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user