diff options
| author | s-ol <s+removethis@s-ol.nu> | 2025-12-25 10:07:06 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-12-25 10:07:06 +0000 |
| commit | 958c55f52a0b5c0d928be490ee01731f4b893274 (patch) | |
| tree | c5baf64fb6e3d528f33b10a492a1b5f635dbbe10 /src | |
| parent | typing working (diff) | |
| download | nodetoy-958c55f52a0b5c0d928be490ee01731f4b893274.tar.gz nodetoy-958c55f52a0b5c0d928be490ee01731f4b893274.zip | |
basic toposorted SSA
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 219 | ||||
| -rw-r--r-- | src/preview.rs | 17 |
2 files changed, 53 insertions, 183 deletions
diff --git a/src/main.rs b/src/main.rs index de5581b..6dafdfd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use egui::{Color32, Id, Ui}; use egui_snarl::{ InPin, InPinId, NodeId, OutPin, OutPinId, Snarl, ui::{ - AnyPins, NodeLayout, PinInfo, PinPlacement, SnarlStyle, SnarlViewer, SnarlWidget, + NodeLayout, PinInfo, PinPlacement, SnarlStyle, SnarlViewer, SnarlWidget, get_selected_nodes, }, }; @@ -121,6 +121,41 @@ impl DemoNode { .collect() } + fn compile_output(pin: OutPinId) -> String { + let node_id = pin.node.0; + let out_id = pin.output; + format!("n{node_id}_o{out_id}") + } + + fn get_inputs(&self, node: NodeId, snarl: &Snarl<DemoNode>) -> String { + (0..self.inputs()) + .map( + |input| match &*snarl.in_pin(InPinId { node, input }).remotes { + [] => "?".to_owned(), + [pin] => DemoNode::compile_output(*pin), + _ => unreachable!("cannot connect to multiple inputs"), + }, + ) + .collect::<Vec<_>>() + .join(", ") + } + + pub fn compile(&self, node: NodeId, snarl: &Snarl<DemoNode>) -> String { + let sig = self.get_node_signature(node, snarl); + let typ = if sig.outputs.is_empty() { + "".to_owned() + } else { + let output = sig.outputs[0]; + format!("{output:?}") + }; + + let node_id = node.0; + let name = format!("{self:?}"); + let inputs = self.get_inputs(node, snarl); + + format!("{typ} n{node_id}_o0 = {name}({inputs});\n") + } + pub fn get_node_signature(&self, node: NodeId, snarl: &Snarl<DemoNode>) -> TypeSignature { let connected = self.get_input_types(node, snarl); self.signature(&connected) @@ -224,133 +259,6 @@ impl SnarlViewer<DemoNode> for DemoViewer { } } - fn has_dropped_wire_menu(&mut self, _src_pins: AnyPins, _snarl: &mut Snarl<DemoNode>) -> bool { - false // true - } - - fn show_dropped_wire_menu( - &mut self, - _pos: egui::Pos2, - _ui: &mut Ui, - _src_pins: AnyPins, - _snarl: &mut Snarl<DemoNode>, - ) { - /* - // In this demo, we create a context-aware node graph menu, and connect a wire - // dropped on the fly based on user input to a new node created. - // - // In your implementation, you may want to define specifications for each node's - // pin inputs and outputs and compatibility to make this easier. - - type PinCompat = usize; - const PIN_NUM: PinCompat = 1; - const PIN_STR: PinCompat = 2; - const PIN_IMG: PinCompat = 4; - const PIN_SINK: PinCompat = PIN_NUM | PIN_STR | PIN_IMG; - - const fn pin_out_compat(node: &DemoNode) -> PinCompat { - match node { - DemoNode::Sink => 0, - DemoNode::String(_) => PIN_STR, - DemoNode::ShowImage(_) => PIN_IMG, - DemoNode::Number(_) | DemoNode::ExprNode(_) => PIN_NUM, - } - } - - const fn pin_in_compat(node: &DemoNode, pin: usize) -> PinCompat { - match node { - DemoNode::Sink => PIN_SINK, - DemoNode::Number(_) | DemoNode::String(_) => 0, - DemoNode::ShowImage(_) => PIN_STR, - DemoNode::ExprNode(_) => { - if pin == 0 { - PIN_STR - } else { - PIN_NUM - } - } - } - } - - ui.label("Add node"); - - match src_pins { - AnyPins::Out(src_pins) => { - if src_pins.len() != 1 { - ui.label("Multiple output pins are not supported in this demo"); - return; - } - - let src_pin = src_pins[0]; - let src_out_ty = pin_out_compat(snarl.get_node(src_pin.node).unwrap()); - let dst_in_candidates = [ - ("Sink", (|| DemoNode::Sink) as fn() -> DemoNode, PIN_SINK), - ("Show Image", || DemoNode::ShowImage(String::new()), PIN_STR), - ("Expr", || DemoNode::ExprNode(ExprNode::new()), PIN_STR), - ]; - - for (name, ctor, in_ty) in dst_in_candidates { - if src_out_ty & in_ty != 0 && ui.button(name).clicked() { - // Create new node. - let new_node = snarl.insert_node(pos, ctor()); - let dst_pin = InPinId { - node: new_node, - input: 0, - }; - - // Connect the wire. - snarl.connect(src_pin, dst_pin); - ui.close(); - } - } - } - AnyPins::In(pins) => { - let all_src_types = pins.iter().fold(0, |acc, pin| { - acc | pin_in_compat(snarl.get_node(pin.node).unwrap(), pin.input) - }); - - let dst_out_candidates = [ - ( - "Number", - (|| DemoNode::Number(0.)) as fn() -> DemoNode, - PIN_NUM, - ), - ("String", || DemoNode::String(String::new()), PIN_STR), - ("Expr", || DemoNode::ExprNode(ExprNode::new()), PIN_NUM), - ("Show Image", || DemoNode::ShowImage(String::new()), PIN_IMG), - ]; - - for (name, ctor, out_ty) in dst_out_candidates { - if all_src_types & out_ty != 0 && ui.button(name).clicked() { - // Create new node. - let new_node = ctor(); - let dst_ty = pin_out_compat(&new_node); - - let new_node = snarl.insert_node(pos, new_node); - let dst_pin = OutPinId { - node: new_node, - output: 0, - }; - - // Connect the wire. - for src_pin in pins { - let src_ty = - pin_in_compat(snarl.get_node(src_pin.node).unwrap(), src_pin.input); - if src_ty & dst_ty != 0 { - // In this demo, input pin MUST be unique ... - // Therefore here we drop inputs of source input pin. - snarl.drop_inputs(*src_pin); - snarl.connect(dst_pin, *src_pin); - ui.close(); - } - } - } - } - } - } - */ - } - fn has_node_menu(&mut self, _node: &DemoNode) -> bool { true } @@ -369,59 +277,6 @@ impl SnarlViewer<DemoNode> for DemoViewer { ui.close(); } } - - fn has_on_hover_popup(&mut self, _: &DemoNode) -> bool { - false // true - } - - fn show_on_hover_popup( - &mut self, - _node: NodeId, - _inputs: &[InPin], - _outputs: &[OutPin], - _ui: &mut Ui, - _snarl: &mut Snarl<DemoNode>, - ) { - /* - match snarl[node] { - DemoNode::Sink => { - ui.label("Displays anything connected to it"); - } - DemoNode::Number(_) => { - ui.label("Outputs integer value"); - } - DemoNode::String(_) => { - ui.label("Outputs string value"); - } - DemoNode::ShowImage(_) => { - ui.label("Displays image from URL in input"); - } - DemoNode::ExprNode(_) => { - ui.label("Evaluates algebraic expression with input for each unique variable name"); - } - } - */ - } - - fn header_frame( - &mut self, - frame: egui::Frame, - _node: NodeId, - _inputs: &[InPin], - _outputs: &[OutPin], - _snarl: &Snarl<DemoNode>, - ) -> egui::Frame { - frame - /* - match snarl[node] { - DemoNode::Sink => frame.fill(egui::Color32::from_rgb(70, 70, 80)), - DemoNode::Number(_) => frame.fill(egui::Color32::from_rgb(70, 40, 40)), - DemoNode::String(_) => frame.fill(egui::Color32::from_rgb(40, 70, 40)), - DemoNode::ShowImage(_) => frame.fill(egui::Color32::from_rgb(40, 40, 70)), - DemoNode::ExprNode(_) => frame.fill(egui::Color32::from_rgb(70, 66, 40)), - } - */ - } } pub struct DemoApp { @@ -541,7 +396,7 @@ impl App for DemoApp { egui::SidePanel::right("preview").show(ctx, |ui| { egui::ScrollArea::vertical().show(ui, |ui| { egui::Frame::canvas(ui.style()).show(ui, |ui| { - self.preview.custom_painting(ui); + self.preview.custom_painting(ui, &self.snarl); }); }); }); diff --git a/src/preview.rs b/src/preview.rs index 33c6b77..94bf128 100644 --- a/src/preview.rs +++ b/src/preview.rs @@ -7,6 +7,9 @@ use eframe::{ egui_wgpu::wgpu::util::DeviceExt as _, egui_wgpu::{self, wgpu}, }; +use egui_snarl::{ + Snarl, NodeId, +}; pub struct Custom3d { angle: f32, @@ -195,7 +198,7 @@ impl egui_wgpu::CallbackTrait for CustomTriangleCallback { } impl Custom3d { - pub fn custom_painting(&mut self, ui: &mut egui::Ui) { + pub fn custom_painting(&mut self, ui: &mut egui::Ui, snarl: &Snarl<crate::DemoNode>) { let (rect, response) = ui.allocate_exact_size(egui::Vec2::splat(300.0), egui::Sense::drag()); @@ -204,6 +207,18 @@ impl Custom3d { rect, CustomTriangleCallback { angle: self.angle }, )); + + if ui.button("compile").clicked() { + let mut order = topological_sort::TopologicalSort::<NodeId>::new(); + for (out, inp) in snarl.wires() { + order.add_dependency(out.node, inp.node); + } + + // let buf = BufWriter::new(Vec::new()); + while let Some(id) = order.pop() { + info!("{}", snarl[id].compile(id, snarl)); + } + } } } |
