work on adding custom nodes

This commit is contained in:
Michael Mikovsky
2024-11-26 15:08:37 -07:00
parent 549d3bff59
commit 7a39b610b5
4 changed files with 319 additions and 67 deletions
+63 -23
View File
@@ -1,24 +1,10 @@
[ [
{
"pane": {
"type": "BluePane"
},
"id": "BLUE",
"mode": "Left"
},
{
"pane": {
"type": "GreenPane"
},
"id": "Green",
"mode": "Bottom"
},
{ {
"pane": { "pane": {
"type": "PointRendererPane" "type": "PointRendererPane"
}, },
"id": "Point Cloud", "id": "Point Cloud",
"mode": "Center" "mode": "Hidden"
}, },
{ {
"pane": { "pane": {
@@ -27,21 +13,55 @@
"nodes": { "nodes": {
"0": { "0": {
"value": { "value": {
"type": "Node1" "type": "Node2"
}, },
"pos": { "pos": {
"x": -56.0, "x": -282.38733,
"y": -52.5 "y": -103.8249
}, },
"open": true "open": true
}, },
"1": { "1": {
"value": {
"type": "Node3"
},
"pos": {
"x": 101.502266,
"y": -93.96767
},
"open": true
},
"2": {
"value": { "value": {
"type": "Node1" "type": "Node1"
}, },
"pos": { "pos": {
"x": -61.21814, "x": -70.495674,
"y": 155.28181 "y": -69.65721
},
"open": true
},
"3": {
"value": {
"type": "Constants",
"vars": [],
"popup_open": false
},
"pos": {
"x": -523.0798,
"y": -137.1891
},
"open": true
},
"4": {
"value": {
"type": "Constants",
"vars": [],
"popup_open": false
},
"pos": {
"x": -525.76666,
"y": -80.20156
}, },
"open": true "open": true
} }
@@ -49,7 +69,27 @@
"wires": [ "wires": [
{ {
"out_pin": { "out_pin": {
"node": 2,
"output": 0
},
"in_pin": {
"node": 1, "node": 1,
"input": 0
}
},
{
"out_pin": {
"node": 4,
"output": 0
},
"in_pin": {
"node": 0,
"input": 1
}
},
{
"out_pin": {
"node": 3,
"output": 0 "output": 0
}, },
"in_pin": { "in_pin": {
@@ -63,7 +103,7 @@
"output": 0 "output": 0
}, },
"in_pin": { "in_pin": {
"node": 1, "node": 2,
"input": 0 "input": 0
} }
} }
@@ -72,9 +112,9 @@
"style": { "style": {
"select_rect_contained": null "select_rect_contained": null
}, },
"snarl_ui_id": 12028535709621507733 "snarl_ui_id": 968669704945789632
}, },
"id": "Pipeline Pane", "id": "Pipeline Pane",
"mode": "Right" "mode": "Center"
} }
] ]
+85
View File
@@ -0,0 +1,85 @@
use eframe::epaint::Color32;
use egui::Ui;
use egui_snarl::{InPin, OutPin};
use egui_snarl::ui::{PinInfo, WireStyle};
use crate::pane_manager::{Pane, PaneMode, PaneState, PsudoCreationContext};
use crate::panes::pipeline_editor::Node;
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Constants {
vars: Vec<String>,
popup_open: bool,
}
#[typetag::serde]
impl Node for Constants {
fn new() -> Self {
Self {
vars: Vec::new(),
popup_open: false,
}
}
fn get_name(&self) -> &str {
"Constants"
}
fn get_description(&self) -> &str {"Test Node"}
fn duplicate(&self) -> Box<dyn Node> {
Box::new(Self::new())
}
fn inputs(&self) -> usize {
0
}
fn outputs(&self) -> usize {
1
}
fn show_input(&self, _pin: &InPin, _ui: &mut Ui, _scale: f32) -> PinInfo {
PinInfo::square()
}
fn show_output(&self, _pin: &OutPin, _ui: &mut Ui, _scale: f32) -> PinInfo {
PinInfo::square().with_fill(Color32::RED).with_wire_style(WireStyle::Bezier3)
}
fn can_rx(&self, _other: &Box<dyn Node>) -> bool {
true
}
fn can_tx(&self, _other: &Box<dyn Node>) -> bool {
true
}
fn context_menu(&self, ui: &mut Ui) {
egui::Window::new("TEST").show(ui.ctx(), |ui| {
ui.heading("EEEEE");
});
// if ui.button("Edit").clicked() {
// self.popup_open = !self.popup_open;
// }
}
fn update(&self, ui: &mut Ui) {
}
}
// #[derive(serde::Serialize, serde::Deserialize, Clone)]
// pub struct Constant_Edit_Popup {
// pub data: Vec<String>,
// pub has_changed: bool,
// }
// #[typetag::serde]
// impl Pane for Constant_Edit_Popup {
// fn new() -> PaneState where Self: Sized {
// let mut s = Self {
// node: None,
// has_changed: false,
// };
// PaneState {
// id: s.name().to_string(),
// mode: PaneMode::Popup,
// pane: Box::new(s),
// }
// }
// fn init(&mut self, _pcc: &PsudoCreationContext) {}
// fn name(&mut self) -> &str {"ERROR"}
// fn render(&mut self, _ui: &mut Ui){}
// fn context_menu(&mut self, _ui: &mut Ui) {}
// }
+7 -16
View File
@@ -12,6 +12,7 @@ pub enum PaneMode {
Left, Left,
Bottom, Bottom,
Center, Center,
Popup,
} }
#[typetag::serde(tag = "type")] #[typetag::serde(tag = "type")]
@@ -62,20 +63,6 @@ impl PaneState {
} }
// impl Default for dyn Pane {
// fn default() -> (impl Pane + 'static) {
// Box::new(NoPane {})
// }
// }
// pub struct PaneGroup {
// pub direction: TileDirection,
// pub panes: Vec<PaneState>,
// }
// #[derive(serde::Deserialize, serde::Serialize)]
// #[derive(serde::Deserialize, serde::Serialize)]
pub struct PsudoCreationContext { pub struct PsudoCreationContext {
pub gl: Option<Arc<glow::Context>>, pub gl: Option<Arc<glow::Context>>,
} }
@@ -130,7 +117,11 @@ impl PaneManager {
ui.menu_button("View", |ui| { ui.menu_button("View", |ui| {
for i in 0..len { for i in 0..len {
if self.panes[i].mode == PaneMode::Popup {
continue;
}
ui.menu_button(self.panes[i].id.clone(), |ui| { ui.menu_button(self.panes[i].id.clone(), |ui| {
if ui.button("Center").clicked() { if ui.button("Center").clicked() {
for a in 0..len { for a in 0..len {
let pane2: &mut PaneState = &mut self.panes[a]; let pane2: &mut PaneState = &mut self.panes[a];
@@ -168,7 +159,7 @@ impl PaneManager {
ui.separator(); ui.separator();
for i in 0..len { for i in 0..len {
if self.panes[i].mode != PaneMode::Hidden { if self.panes[i].mode != PaneMode::Hidden && self.panes[i].mode != PaneMode::Popup {
ui.menu_button(self.panes[i].id.clone(), |ui| { ui.menu_button(self.panes[i].id.clone(), |ui| {
let _ = &mut self.panes[i].pane.context_menu(ui); let _ = &mut self.panes[i].pane.context_menu(ui);
}); });
@@ -203,7 +194,7 @@ impl PaneManager {
pane.render(ui); pane.render(ui);
}); });
}, },
PaneMode::Windowed => { PaneMode::Windowed | PaneMode::Popup => {
egui::Window::new(pane.id.clone()) egui::Window::new(pane.id.clone())
.resizable(true) .resizable(true)
.max_width(ui.clip_rect().width()).max_height(ui.clip_rect().height()) .max_width(ui.clip_rect().width()).max_height(ui.clip_rect().height())
+164 -28
View File
@@ -2,11 +2,8 @@ use crate::pane_manager::{Pane, PaneMode, PaneState, PsudoCreationContext};
use egui::{Color32, Id, Pos2, Ui}; use egui::{Color32, Id, Pos2, Ui};
use egui_snarl::{ use egui_snarl::{ui::{PinInfo, SnarlStyle, SnarlViewer}, InPin, InPinId, NodeId, OutPin, OutPinId, Snarl};
ui::{PinInfo, SnarlStyle, SnarlViewer}, use egui_snarl::ui::{WireStyle};
InPin, NodeId, OutPin, Snarl,
};
use egui_snarl::ui::{PinShape, WireStyle};
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
pub struct PipelinePane { pub struct PipelinePane {
@@ -64,8 +61,75 @@ impl Pane for PipelinePane {
} }
impl PipelinePane { impl PipelinePane {
pub fn run(&mut self) { fn run(&mut self) {
// Todo: if let Some(snarl) = &mut self.snarl {
fn remove_duplicates(nodes: Vec<NodeId>) -> Vec<NodeId> {
let mut new_vec : Vec<NodeId> = Vec::new();
for node in nodes {
if !new_vec.contains(&node){
new_vec.push(node);
}
}
new_vec
}
fn has_input_wire(snarl: &Snarl<Box<dyn Node>>, nodeid: NodeId) -> bool {
for wire in snarl.wires() {
if wire.1.node == nodeid {
return true;
}
}
false
}
fn get_output_wires(snarl: &Snarl<Box<dyn Node>>, nodeid: &NodeId) -> Vec<OutPinId> {
let mut arr: Vec<OutPinId> = Vec::new();
for wire in snarl.wires() {
if &wire.0.node == nodeid {
arr.push(wire.0)
}
}
arr
}
// let wires = snarl.wires().map(|| {})
let mut nodes: Vec<Vec<NodeId>> = Vec::new();
let mut starting_nodes: Vec<NodeId> = Vec::new();
for node in snarl.nodes_ids_data() {
if !has_input_wire(snarl, node.0) {
starting_nodes.push(node.0.clone())
}
}
starting_nodes = remove_duplicates(starting_nodes);
nodes.push(starting_nodes);
for i in 1..50 {
if nodes.get(i-1).is_none() {break}
let mut prevarr = nodes.get(i-1).unwrap();
if prevarr.len() == 0 {break}
let mut newarr: Vec<NodeId> = Vec::new();
for node in prevarr {
for wire in get_output_wires(snarl, node) {
newarr.push(wire.node);
}
}
newarr = remove_duplicates(newarr);
nodes.push(newarr);
}
for nodearr in nodes {
println!("Nodes: ");
for node in nodearr {
println!("{}", snarl.get_node(node).unwrap().get_name());
}
}
}
} }
} }
@@ -75,7 +139,7 @@ fn format_float(v: f64) -> String {
} }
#[typetag::serde(tag = "type")] #[typetag::serde(tag = "type")]
trait Node { pub trait Node {
fn new() -> Self fn new() -> Self
where where
Self: Sized; Self: Sized;
@@ -89,6 +153,7 @@ trait Node {
fn can_rx(&self, other: &Box<dyn Node>) -> bool; fn can_rx(&self, other: &Box<dyn Node>) -> bool;
fn can_tx(&self, other: &Box<dyn Node>) -> bool; fn can_tx(&self, other: &Box<dyn Node>) -> bool;
fn context_menu(&self, ui: &mut Ui); fn context_menu(&self, ui: &mut Ui);
fn update(&self, ui: &mut Ui);
} }
#[derive(Clone, serde::Serialize, serde::Deserialize)] #[derive(Clone, serde::Serialize, serde::Deserialize)]
@@ -98,39 +163,84 @@ impl Node for Node1 {
fn new() -> Self { fn new() -> Self {
Self Self
} }
fn get_name(&self) -> &str { "Test" }
fn get_name(&self) -> &str {
"Test"
}
fn get_description(&self) -> &str {"Test Node"} fn get_description(&self) -> &str {"Test Node"}
fn duplicate(&self) -> Box<dyn Node> { Box::new(Self::new()) }
fn duplicate(&self) -> Box<dyn Node> {
Box::new(Self::new())
}
fn inputs(&self) -> usize { fn inputs(&self) -> usize {
1 1
} }
fn outputs(&self) -> usize { fn outputs(&self) -> usize {
1 1
} }
fn show_input(&self, _pin: &InPin, _ui: &mut Ui, _scale: f32) -> PinInfo { fn show_input(&self, _pin: &InPin, _ui: &mut Ui, _scale: f32) -> PinInfo { PinInfo::square() }
PinInfo::square() fn show_output(&self, _pin: &OutPin, _ui: &mut Ui, _scale: f32) -> PinInfo { PinInfo::square().with_fill(Color32::RED).with_wire_style(WireStyle::Bezier3) }
}
fn show_output(&self, _pin: &OutPin, _ui: &mut Ui, _scale: f32) -> PinInfo {
PinInfo::square().with_fill(Color32::RED).with_wire_style(WireStyle::Bezier3)
}
fn can_rx(&self, _other: &Box<dyn Node>) -> bool { fn can_rx(&self, _other: &Box<dyn Node>) -> bool {
true true
} }
fn can_tx(&self, _other: &Box<dyn Node>) -> bool { fn can_tx(&self, _other: &Box<dyn Node>) -> bool {
true true
} }
fn context_menu(&self, ui: &mut Ui) { fn context_menu(&self, ui: &mut Ui) { ui.label("Test!"); }
ui.label("Test!"); fn update(&self, ui: &mut Ui) {}
}
} }
#[derive(Clone, serde::Serialize, serde::Deserialize)]
struct Node2;
#[typetag::serde]
impl Node for Node2 {
fn new() -> Self {
Self
}
fn get_name(&self) -> &str { "Test 2-1" }
fn get_description(&self) -> &str {"Test Node"}
fn duplicate(&self) -> Box<dyn Node> { Box::new(Self::new()) }
fn inputs(&self) -> usize {
2
}
fn outputs(&self) -> usize {
1
}
fn show_input(&self, _pin: &InPin, _ui: &mut Ui, _scale: f32) -> PinInfo { PinInfo::square() }
fn show_output(&self, _pin: &OutPin, _ui: &mut Ui, _scale: f32) -> PinInfo { PinInfo::square().with_fill(Color32::RED).with_wire_style(WireStyle::Bezier3) }
fn can_rx(&self, _other: &Box<dyn Node>) -> bool {
true
}
fn can_tx(&self, _other: &Box<dyn Node>) -> bool {
true
}
fn context_menu(&self, ui: &mut Ui) { ui.label("Test!"); }
fn update(&self, ui: &mut Ui) {}
}
#[derive(Clone, serde::Serialize, serde::Deserialize)]
struct Node3;
#[typetag::serde]
impl Node for crate::panes::pipeline_editor::Node3 {
fn new() -> Self {
Self
}
fn get_name(&self) -> &str { "Test 1-2" }
fn get_description(&self) -> &str {"Test Node"}
fn duplicate(&self) -> Box<dyn Node> { Box::new(Self::new()) }
fn inputs(&self) -> usize {
1
}
fn outputs(&self) -> usize {
2
}
fn show_input(&self, _pin: &InPin, _ui: &mut Ui, _scale: f32) -> PinInfo { PinInfo::square() }
fn show_output(&self, _pin: &OutPin, _ui: &mut Ui, _scale: f32) -> PinInfo { PinInfo::square().with_fill(Color32::RED).with_wire_style(WireStyle::Bezier3) }
fn can_rx(&self, _other: &Box<dyn Node>) -> bool {
true
}
fn can_tx(&self, _other: &Box<dyn Node>) -> bool {
true
}
fn context_menu(&self, ui: &mut Ui) { ui.label("Test!"); }
fn update(&self, ui: &mut Ui) {}
}
#[derive(Clone, serde::Serialize, serde::Deserialize)] #[derive(Clone, serde::Serialize, serde::Deserialize)]
struct NodeViewer; struct NodeViewer;
@@ -150,6 +260,12 @@ impl SnarlViewer<Box<dyn Node>> for NodeViewer {
} }
} }
fn disconnect(&mut self, from: &OutPin, to: &InPin, snarl: &mut Snarl<Box<dyn Node>>) {
for &remote in &to.remotes {
snarl.disconnect(remote, to.id);
}
}
fn title(&mut self, node: &Box<dyn Node>) -> String { fn title(&mut self, node: &Box<dyn Node>) -> String {
node.get_name().to_string() node.get_name().to_string()
} }
@@ -239,19 +355,39 @@ impl SnarlViewer<Box<dyn Node>> for NodeViewer {
} else if ui.button("Duplicate").clicked() { } else if ui.button("Duplicate").clicked() {
snarl.insert_node(Pos2 {x:0.,y:0.}, snarl.get_node(nodeid).unwrap().duplicate()); snarl.insert_node(Pos2 {x:0.,y:0.}, snarl.get_node(nodeid).unwrap().duplicate());
ui.close_menu(); ui.close_menu();
// }// else if ui.button("Remove All Connections").clicked() {
// ui.
// ui.close_menu();
} else { } else {
snarl.get_node(nodeid).unwrap().context_menu(ui); snarl.get_node(nodeid).unwrap().context_menu(ui);
} }
} }
fn show_body(&mut self, node: NodeId, inputs: &[InPin], outputs: &[OutPin], ui: &mut Ui, scale: f32, snarl: &mut Snarl<Box<dyn Node>>) {
snarl.get_node(node).unwrap().update(ui);
}
} }
impl NodeViewer { impl NodeViewer {
pub fn add_node_menu(pos: Pos2, ui: &mut Ui, snarl: &mut Snarl<Box<dyn Node>>) { pub fn add_node_menu(pos: Pos2, ui: &mut Ui, snarl: &mut Snarl<Box<dyn Node>>) {
ui.label("Add node"); ui.label("Add node");
let button = ui.button("Test1");
if button.clicked() {
if ui.button("Test").clicked() {
snarl.insert_node(pos, Box::new(Node1::new())); snarl.insert_node(pos, Box::new(Node1::new()));
ui.close_menu(); ui.close_menu();
} else if ui.button("Constants").clicked() {
snarl.insert_node(pos, Box::new(crate::nodes::constants::Constants::new()));
ui.close_menu();
} else if ui.button("Test 2-1").clicked() {
snarl.insert_node(pos, Box::new(Node2::new()));
ui.close_menu();
} else if ui.button("Test 1-2").clicked() {
snarl.insert_node(pos, Box::new(Node3::new()));
ui.close_menu();
} }
} }
} }