feat: add active node settings
This commit is contained in:
@ -5,6 +5,7 @@ import EventEmitter from "./helpers/EventEmitter.js";
|
||||
import throttle from "./helpers/throttle.js";
|
||||
import { createLogger } from "./helpers/index.js";
|
||||
import type { NodeInput } from "@nodes/types";
|
||||
import { fastHashString } from "@nodes/utils";
|
||||
|
||||
const logger = createLogger("graph-manager");
|
||||
|
||||
@ -70,7 +71,13 @@ export class GraphManager extends EventEmitter<{ "save": Graph, "result": any, "
|
||||
}
|
||||
|
||||
|
||||
private lastSettingsHash = 0;
|
||||
setSettings(settings: Record<string, unknown>) {
|
||||
|
||||
let hash = fastHashString(JSON.stringify(settings));
|
||||
if (hash === this.lastSettingsHash) return;
|
||||
this.lastSettingsHash = hash;
|
||||
|
||||
this.settings = settings;
|
||||
this.save();
|
||||
this.execute();
|
||||
|
@ -39,10 +39,11 @@
|
||||
const edges = graph.edges;
|
||||
|
||||
let wrapper: HTMLDivElement;
|
||||
let rect: DOMRect;
|
||||
$: rect =
|
||||
wrapper && width
|
||||
? wrapper.getBoundingClientRect()
|
||||
: { x: 0, y: 0, width: 0, height: 0 };
|
||||
: ({ x: 0, y: 0, width: 0, height: 0 } as DOMRect);
|
||||
|
||||
let camera: OrthographicCamera;
|
||||
const minZoom = 1;
|
||||
@ -121,10 +122,13 @@
|
||||
const height =
|
||||
5 +
|
||||
10 *
|
||||
Object.keys(node.inputs)
|
||||
.filter((i) => i !== "seed")
|
||||
.filter((p) => node?.inputs && !("setting" in node?.inputs?.[p]))
|
||||
.length;
|
||||
Object.keys(node.inputs).filter(
|
||||
(p) =>
|
||||
p !== "seed" &&
|
||||
node?.inputs &&
|
||||
!("setting" in node?.inputs?.[p]) &&
|
||||
node.inputs[p].hidden !== true,
|
||||
).length;
|
||||
nodeHeightCache[nodeTypeId] = height;
|
||||
return height;
|
||||
}
|
||||
@ -756,7 +760,8 @@
|
||||
clickedNodeId === -1 &&
|
||||
!boxSelection &&
|
||||
cameraDown[0] === cameraPosition[0] &&
|
||||
cameraDown[1] === cameraPosition[1]
|
||||
cameraDown[1] === cameraPosition[1] &&
|
||||
isBodyFocused()
|
||||
) {
|
||||
$activeNodeId = -1;
|
||||
$selectedNodes?.clear();
|
||||
@ -817,7 +822,6 @@
|
||||
function handleDragEnter(e: DragEvent) {
|
||||
e.preventDefault();
|
||||
isDragging = true;
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
function handlerDragOver(e: DragEvent) {
|
||||
@ -840,7 +844,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:window on:mousemove={handleMouseMove} on:mouseup={handleMouseUp} />
|
||||
<svelte:window on:mousemove={handleMouseMove} />
|
||||
|
||||
<div
|
||||
on:wheel={handleMouseScroll}
|
||||
@ -851,6 +855,7 @@
|
||||
tabindex="0"
|
||||
bind:clientWidth={width}
|
||||
bind:clientHeight={height}
|
||||
on:mouseup={handleMouseUp}
|
||||
on:dragenter={handleDragEnter}
|
||||
on:dragover={handlerDragOver}
|
||||
on:drop={handleDrop}
|
||||
|
@ -1,17 +1,23 @@
|
||||
<script lang="ts">
|
||||
import type { Graph, NodeRegistry } from "@nodes/types";
|
||||
import type { Graph, Node, NodeRegistry } from "@nodes/types";
|
||||
import GraphEl from "./Graph.svelte";
|
||||
import { GraphManager } from "../graph-manager.js";
|
||||
import { createEventDispatcher, setContext } from "svelte";
|
||||
import type { Writable } from "svelte/store";
|
||||
import { type Writable } from "svelte/store";
|
||||
import { debounce } from "$lib/helpers";
|
||||
import { createKeyMap } from "$lib/helpers/createKeyMap";
|
||||
import { activeNodeId } from "./stores";
|
||||
|
||||
export let registry: NodeRegistry;
|
||||
export let graph: Graph;
|
||||
export let settings: Writable<Record<string, any>> | undefined;
|
||||
|
||||
export const manager = new GraphManager(registry);
|
||||
export let activeNode: Node | undefined;
|
||||
$: if ($activeNodeId !== -1) {
|
||||
activeNode = manager.getNode($activeNodeId);
|
||||
} else {
|
||||
activeNode = undefined;
|
||||
}
|
||||
|
||||
export const status = manager.status;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
import NodeHeader from "./NodeHeader.svelte";
|
||||
import NodeParameter from "./NodeParameter.svelte";
|
||||
import { getContext, onMount } from "svelte";
|
||||
import Page from "../../../routes/+page.svelte";
|
||||
export let isActive = false;
|
||||
export let isSelected = false;
|
||||
export let inView = true;
|
||||
@ -17,9 +18,10 @@
|
||||
|
||||
const type = node?.tmp?.type;
|
||||
|
||||
const parameters = Object.entries(type?.inputs || {})
|
||||
.filter((p) => p[1].type !== "seed")
|
||||
.filter((p) => !("setting" in p[1]));
|
||||
const parameters = Object.entries(type?.inputs || {}).filter(
|
||||
(p) =>
|
||||
p[1].type !== "seed" && !("setting" in p[1]) && p[1]?.hidden !== true,
|
||||
);
|
||||
|
||||
const updateNodePosition =
|
||||
getContext<(n: Node) => void>("updateNodePosition");
|
||||
|
71
app/src/lib/settings/ActiveNode.svelte
Normal file
71
app/src/lib/settings/ActiveNode.svelte
Normal file
@ -0,0 +1,71 @@
|
||||
<script lang="ts">
|
||||
import type { Node, NodeInput } from "@nodes/types";
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
import { writable } from "svelte/store";
|
||||
import type { GraphManager } from "$lib/graph-interface/graph-manager";
|
||||
|
||||
function filterInputs(inputs: Record<string, NodeInput>) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(inputs).filter(([key, value]) => {
|
||||
return value.hidden === true;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function createStore(
|
||||
props: Node["props"],
|
||||
inputs: Record<string, NodeInput>,
|
||||
) {
|
||||
const store = {};
|
||||
Object.keys(inputs).forEach((key) => {
|
||||
store[key] = props[key] || inputs[key].value;
|
||||
});
|
||||
console.log({ store, props });
|
||||
return writable(store);
|
||||
}
|
||||
|
||||
export let manager: GraphManager;
|
||||
|
||||
export let node: Node;
|
||||
let nodeDefinition: Record<string, NodeInput> | undefined;
|
||||
$: nodeDefinition = node?.tmp?.type
|
||||
? filterInputs(node.tmp.type.inputs)
|
||||
: undefined;
|
||||
$: store = node ? createStore(node.props, nodeDefinition) : undefined;
|
||||
|
||||
function updateNode() {
|
||||
if (!node || !$store) return;
|
||||
Object.keys($store).forEach((_key: string) => {
|
||||
node.props = node.props || {};
|
||||
const key = _key as keyof typeof $store;
|
||||
let needsUpdate = false;
|
||||
console.log({ key });
|
||||
if (
|
||||
node &&
|
||||
$store &&
|
||||
key in node.props &&
|
||||
node.props[key] !== $store[key]
|
||||
) {
|
||||
needsUpdate = true;
|
||||
node.props[key] = $store[key];
|
||||
}
|
||||
if (needsUpdate) {
|
||||
manager.execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$: if (store && $store) {
|
||||
updateNode();
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if node}
|
||||
{#if nodeDefinition && store && Object.keys(nodeDefinition).length > 0}
|
||||
<NestedSettings id="activeNodeSettings" settings={nodeDefinition} {store} />
|
||||
{:else}
|
||||
<p class="mx-4">Active Node has no Settings</p>
|
||||
{/if}
|
||||
{:else}
|
||||
<p class="mx-4">No active node</p>
|
||||
{/if}
|
@ -10,6 +10,8 @@
|
||||
{
|
||||
icon: string;
|
||||
id: string;
|
||||
hidden?: boolean;
|
||||
props?: Record<string, unknown>;
|
||||
component?: typeof SvelteComponent<{}, {}, {}>;
|
||||
definition: Record<string, NodeInput>;
|
||||
settings: Writable<Record<string, unknown>>;
|
||||
@ -22,7 +24,7 @@
|
||||
);
|
||||
$: keys = panels
|
||||
? (Object.keys(panels) as unknown as (keyof typeof panels)[]).filter(
|
||||
(key) => !!panels[key]?.id,
|
||||
(key) => !!panels[key]?.id && panels[key]?.hidden !== true,
|
||||
)
|
||||
: [];
|
||||
|
||||
@ -79,7 +81,7 @@
|
||||
{/each}
|
||||
</div>
|
||||
<div class="content">
|
||||
{#if $activePanel && panels[$activePanel]}
|
||||
{#if $activePanel && panels[$activePanel] && panels[$activePanel].hidden !== true}
|
||||
<h1 class="m-0 p-4">{panels[$activePanel].id}</h1>
|
||||
{#key $activePanel}
|
||||
{#if panels[$activePanel]?.component}
|
||||
|
@ -4,11 +4,11 @@
|
||||
import { MemoryRuntimeExecutor } from "$lib/runtime-executor";
|
||||
import { RemoteNodeRegistry } from "$lib/node-registry-client";
|
||||
import * as templates from "$lib/graph-templates";
|
||||
import type { Graph } from "@nodes/types";
|
||||
import type { Graph, Node } from "@nodes/types";
|
||||
import Viewer from "$lib/result-viewer/Viewer.svelte";
|
||||
import Settings from "$lib/settings/Settings.svelte";
|
||||
import { AppSettings, AppSettingTypes } from "$lib/settings/app-settings";
|
||||
import { get, writable, type Writable } from "svelte/store";
|
||||
import { get, writable, type Readable, type Writable } from "svelte/store";
|
||||
import Keymap from "$lib/settings/Keymap.svelte";
|
||||
import type { createKeyMap } from "$lib/helpers/createKeyMap";
|
||||
import NodeStore from "$lib/node-store/NodeStore.svelte";
|
||||
@ -17,7 +17,7 @@
|
||||
import { decodeNestedArray, encodeNestedArray } from "@nodes/utils";
|
||||
import type { PerspectiveCamera, Vector3 } from "three";
|
||||
import type { OrbitControls } from "three/examples/jsm/Addons.js";
|
||||
import GraphView from "$lib/graph-interface/graph/GraphView.svelte";
|
||||
import ActiveNode from "$lib/settings/ActiveNode.svelte";
|
||||
|
||||
const nodeRegistry = new RemoteNodeRegistry("");
|
||||
const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry);
|
||||
@ -29,6 +29,7 @@
|
||||
let viewerCamera: PerspectiveCamera;
|
||||
let viewerControls: OrbitControls;
|
||||
let viewerCenter: Vector3;
|
||||
let activeNode: Node | undefined;
|
||||
|
||||
let graph = localStorage.getItem("graph")
|
||||
? JSON.parse(localStorage.getItem("graph")!)
|
||||
@ -65,6 +66,12 @@
|
||||
shortcuts: {},
|
||||
nodeStore: {},
|
||||
graph: {},
|
||||
activeNode: {
|
||||
id: "Active Node",
|
||||
icon: "i-tabler-adjustments",
|
||||
props: { node: undefined, manager },
|
||||
component: ActiveNode,
|
||||
},
|
||||
};
|
||||
|
||||
$: if (keymap) {
|
||||
@ -79,6 +86,7 @@
|
||||
}
|
||||
|
||||
$: if (manager) {
|
||||
settings.activeNode.props.manager = manager;
|
||||
settings.nodeStore = {
|
||||
id: "Node Store",
|
||||
icon: "i-tabler-database",
|
||||
@ -88,6 +96,14 @@
|
||||
settings = settings;
|
||||
}
|
||||
|
||||
$: if (activeNode) {
|
||||
settings.activeNode.props.node = activeNode;
|
||||
settings = settings;
|
||||
} else {
|
||||
settings.activeNode.props.node = undefined;
|
||||
settings = settings;
|
||||
}
|
||||
|
||||
function handleSettings(
|
||||
ev: CustomEvent<{
|
||||
values: Record<string, unknown>;
|
||||
@ -107,7 +123,7 @@
|
||||
};
|
||||
|
||||
settings.graph = {
|
||||
icon: "i-tabler-chart-bar",
|
||||
icon: "i-tabler-git-fork",
|
||||
id: "graph",
|
||||
settings: writable(ev.detail.values),
|
||||
definition: {
|
||||
@ -139,6 +155,7 @@
|
||||
{#key graph}
|
||||
<GraphInterface
|
||||
bind:manager
|
||||
bind:activeNode
|
||||
registry={nodeRegistry}
|
||||
{graph}
|
||||
bind:keymap
|
||||
|
Reference in New Issue
Block a user