Skip to content

Commit 354d777

Browse files
refactor: better node evaluation in frontend
1 parent 8cce59e commit 354d777

File tree

6 files changed

+115
-45
lines changed

6 files changed

+115
-45
lines changed

client/src-tauri/src/nodes.rs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{
55

66
use log::info;
77
use node_graph::{
8-
evaluate_adi_device, evaluate_smart_device, interpreter::Device, parser::NodeGraph,
8+
evaluate, interpreter::{Device, InterpreterOutput, InterpreterContext}, parser::NodeGraph
99
};
1010
use serde::Serialize;
1111
use tauri::{Emitter, Manager, State};
@@ -38,33 +38,21 @@ pub fn start_node_graph_interpreter(state: State<'_, Mutex<AppState>>, app: taur
3838
let start = Instant::now();
3939

4040
let brain = state.lock().await.interpreter.node_ast.clone();
41-
let graph = state.lock().await.interpreter.node_graph.clone();
41+
let mut ctx = InterpreterContext::from_brain(time, &brain);
4242

4343
let mut devices: BTreeMap<String, Device> = BTreeMap::new();
4444

45-
let smart_ports = brain
46-
.smart_ports()
47-
.into_iter()
48-
.zip(graph.brain.smart_ports())
49-
.map(|((_, node), (_, id))| (node, id))
50-
.collect::<Vec<_>>();
51-
let adi_ports = brain
52-
.adi_ports()
53-
.into_iter()
54-
.zip(graph.brain.adi_ports())
55-
.map(|((_, node), (_, id))| (node, id))
56-
.collect::<Vec<_>>();
57-
58-
// Evaluate smart ports
59-
for (node, id) in smart_ports.iter() {
60-
let device = evaluate_smart_device(node, time);
61-
devices.insert((*id).to_owned(), device);
45+
// Evaluate all nodes in the graph by starting at the root nodes
46+
for node in ctx.root_nodes() {
47+
evaluate(&node, &mut ctx);
6248
}
63-
// Evaluate ADI ports
64-
for (node, id) in adi_ports.iter() {
65-
let device = evaluate_adi_device(node, time);
66-
devices.insert((*id).to_owned(), device);
49+
50+
for (id, value) in ctx.evaluated_nodes() {
51+
if let InterpreterOutput::Device(device) = value {
52+
devices.insert(id.clone(), *device);
53+
}
6754
}
55+
6856
app.emit("node-graph-update", NodeGraphUpdate { devices })
6957
.unwrap();
7058
let elapsed = start.elapsed();

client/src/lib/interpreter.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { startNodeGraphInterpreter, stopNodeGraphInterpreter, updateNodeGraph } from "~/lib/invoke";
1+
import { startNodeGraphInterpreter, stopNodeGraphInterpreter, updateNodeGraph, type NodeGraph } from "~/lib/invoke";
22

33
class Interpreter {
44
started: boolean = false;
@@ -12,10 +12,9 @@ class Interpreter {
1212
startNodeGraphInterpreter();
1313
}
1414
}
15-
//TODO: actually support updating
16-
async update() {
15+
async update(nodeGraph: NodeGraph) {
1716
if (this.started) {
18-
updateNodeGraph();
17+
updateNodeGraph(nodeGraph);
1918
}
2019
}
2120
async stop() {

client/src/lib/invoke.ts

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,68 @@ export function stopNodeGraphInterpreter() {
3030
invoke("stop_node_graph_interpreter", {});
3131
}
3232
}
33-
export function updateNodeGraph() {
33+
34+
export interface Brain {
35+
port_1?: string | undefined,
36+
port_2?: string | undefined,
37+
port_3?: string | undefined,
38+
port_4?: string | undefined,
39+
port_5?: string | undefined,
40+
port_6?: string | undefined,
41+
port_7?: string | undefined,
42+
port_8?: string | undefined,
43+
port_9?: string | undefined,
44+
port_10?: string | undefined,
45+
port_11?: string | undefined,
46+
port_12?: string | undefined,
47+
port_13?: string | undefined,
48+
port_14?: string | undefined,
49+
port_15?: string | undefined,
50+
port_16?: string | undefined,
51+
port_17?: string | undefined,
52+
port_18?: string | undefined,
53+
port_19?: string | undefined,
54+
port_20?: string | undefined,
55+
port_21?: string | undefined
56+
}
57+
58+
export interface Input {
59+
source_id: string,
60+
target_handle_id: string,
61+
source_handle_id: string,
62+
}
63+
64+
export interface DistanceSensor {
65+
distance?: number | undefined,
66+
size?: number | undefined
67+
}
68+
69+
export interface LightSensor {
70+
darkness?: number | undefined
71+
}
72+
73+
export interface Value {
74+
value?: number | undefined
75+
}
76+
77+
export interface Math {
78+
operation: string,
79+
lhs?: number | undefined
80+
rhs?: number | undefined
81+
}
82+
83+
export interface Node {
84+
data: {
85+
type: "DistanceSensor" | "LightSensor" | "Value" | "Math",
86+
data: DistanceSensor | LightSensor | Value | Math
87+
} | "Time"
88+
inputs?: Input[] | undefined
89+
}
90+
91+
export interface NodeGraph { brain: Brain, nodes: { [key: string]: Node } }
92+
93+
export function updateNodeGraph(nodeGraph: NodeGraph) {
3494
if ("__TAURI_INTERNALS__" in window) {
35-
invoke("update_node_graph", { opts: { brain: { port_1: "distance-node-0" }, nodes: { "distance-node-0": { data: { type: "DistanceSensor", data: { distance: 1000, size: 200 } } } } } });
95+
invoke("update_node_graph", { opts: nodeGraph });
3696
}
3797
}

client/src/lib/layout/Flow.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
$: {
7777
console.log($nodes);
7878
console.log($edges);
79-
$interpreter?.update();
79+
$interpreter?.update({ brain: { port_1: "distance-node-0" }, nodes: { "distance-node-0": { data: { type: "DistanceSensor", data: { distance: 1000, size: 200 } } } } });
8080
}
8181
</script>
8282

node-graph/src/ast.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ impl Node {
7272
Node::AdiDeviceNode(node) => &node.id,
7373
}
7474
}
75+
pub fn from_data(data: NodeData, id: String) -> Self {
76+
match data {
77+
NodeData::DataNode(data) => Node::DataNode(DataNode { data, id }),
78+
NodeData::SmartDeviceNode(data) => Node::SmartDeviceNode(SmartDeviceNode { data, id }),
79+
NodeData::AdiDeviceNode(data) => Node::AdiDeviceNode(AdiDeviceNode { data, id }),
80+
}
81+
}
7582
pub fn into_data(self) -> NodeData {
7683
match self {
7784
Node::DataNode(node) => NodeData::DataNode(node.data),

node-graph/src/interpreter.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl From<Device> for NodeType {
3232

3333
/// Represents an evaluated output from an AST.
3434
#[derive(Debug, Clone, Copy, PartialEq)]
35-
pub enum InterpereterOutput {
35+
pub enum InterpreterOutput {
3636
/// The AST evaluated down to a single value.
3737
Value(f32),
3838
/// The AST evaluated down to a device node.
@@ -43,7 +43,7 @@ pub struct InterpreterContext {
4343
time: f32,
4444
roots: Vec<String>,
4545
nodes: BTreeMap<String, NodeData>,
46-
evaluated: BTreeMap<String, InterpereterOutput>,
46+
evaluated: BTreeMap<String, InterpreterOutput>,
4747
}
4848
impl InterpreterContext {
4949
pub fn from_brain(time: f32, brain: &Brain) -> Self {
@@ -77,22 +77,38 @@ impl InterpreterContext {
7777
}
7878
}
7979

80+
pub fn new(time: f32) -> Self {
81+
Self {
82+
time,
83+
roots: Vec::new(),
84+
nodes: BTreeMap::new(),
85+
evaluated: BTreeMap::new(),
86+
}
87+
}
88+
8089
pub fn update_time(&mut self, time: f32) {
8190
self.time = time;
8291
self.evaluated.clear();
8392
}
8493

85-
pub fn root_nodes(&self) -> Vec<NodeData> {
94+
pub fn root_nodes(&self) -> Vec<Node> {
8695
self.roots
8796
.iter()
88-
.filter_map(|id| self.nodes.get(id))
89-
.cloned()
97+
.filter_map(|id| {
98+
self.nodes
99+
.get(id)
100+
.map(|node| Node::from_data(node.clone(), id.to_owned()))
101+
})
90102
.collect()
91103
}
104+
105+
pub fn evaluated_nodes(&self) -> &BTreeMap<String, InterpreterOutput> {
106+
&self.evaluated
107+
}
92108
}
93109

94110
pub fn evaluate_data(node: &DataNode, ctx: &mut InterpreterContext) -> f32 {
95-
if let Some(InterpereterOutput::Value(value)) = ctx.evaluated.get(&node.id) {
111+
if let Some(InterpreterOutput::Value(value)) = ctx.evaluated.get(&node.id) {
96112
return *value;
97113
}
98114

@@ -124,12 +140,12 @@ pub fn evaluate_data(node: &DataNode, ctx: &mut InterpreterContext) -> f32 {
124140
};
125141

126142
ctx.evaluated
127-
.insert(node.id.to_owned(), InterpereterOutput::Value(result));
143+
.insert(node.id.to_owned(), InterpreterOutput::Value(result));
128144
result
129145
}
130146

131147
pub fn evaluate_smart_device(node: &SmartDeviceNode, ctx: &mut InterpreterContext) -> Device {
132-
if let Some(InterpereterOutput::Device(device)) = ctx.evaluated.get(&node.id) {
148+
if let Some(InterpreterOutput::Device(device)) = ctx.evaluated.get(&node.id) {
133149
return *device;
134150
}
135151

@@ -153,12 +169,12 @@ pub fn evaluate_smart_device(node: &SmartDeviceNode, ctx: &mut InterpreterContex
153169
};
154170

155171
ctx.evaluated
156-
.insert(node.id.to_owned(), InterpereterOutput::Device(result));
172+
.insert(node.id.to_owned(), InterpreterOutput::Device(result));
157173
result
158174
}
159175

160176
pub fn evaluate_adi_device(node: &AdiDeviceNode, ctx: &mut InterpreterContext) -> Device {
161-
if let Some(InterpereterOutput::Device(device)) = ctx.evaluated.get(&node.id) {
177+
if let Some(InterpreterOutput::Device(device)) = ctx.evaluated.get(&node.id) {
162178
return *device;
163179
}
164180

@@ -176,19 +192,19 @@ pub fn evaluate_adi_device(node: &AdiDeviceNode, ctx: &mut InterpreterContext) -
176192
};
177193

178194
ctx.evaluated
179-
.insert(node.id.to_owned(), InterpereterOutput::Device(result));
195+
.insert(node.id.to_owned(), InterpreterOutput::Device(result));
180196
result
181197
}
182198

183-
pub fn evaluate(node: &Node, ctx: &mut InterpreterContext) -> Option<InterpereterOutput> {
199+
pub fn evaluate(node: &Node, ctx: &mut InterpreterContext) -> Option<InterpreterOutput> {
184200
if ctx.evaluated.contains_key(node.id()) {
185201
return Some(ctx.evaluated[node.id()]);
186202
}
187203

188204
let result = match node {
189-
Node::DataNode(node) => InterpereterOutput::Value(evaluate_data(node, ctx)),
190-
Node::SmartDeviceNode(_) => todo!(),
191-
Node::AdiDeviceNode(_) => todo!(),
205+
Node::DataNode(node) => InterpreterOutput::Value(evaluate_data(node, ctx)),
206+
Node::SmartDeviceNode(node) => InterpreterOutput::Device(evaluate_smart_device(node, ctx)),
207+
Node::AdiDeviceNode(node) => InterpreterOutput::Device(evaluate_adi_device(node, ctx))
192208
};
193209
ctx.evaluated.insert(node.id().to_owned(), result);
194210

0 commit comments

Comments
 (0)