From 0c4e217fa78c41efa8cddc272501d6bb81db6cfe Mon Sep 17 00:00:00 2001 From: hodasemi Date: Sun, 30 Jan 2022 20:57:12 +0100 Subject: [PATCH] Improve device panel --- src/graph_editor_egui.rs | 23 +++++++++++++++++--- src/graph_impls.rs | 6 ------ src/graph_node_ui.rs | 31 ++++++--------------------- src/main.rs | 17 +++++++++++---- src/node_finder.rs | 45 +++++++++++++++++++++++++++------------- src/param_ui.rs | 3 ++- src/virtual_device.rs | 31 +++++++++++++++++++++++++++ 7 files changed, 103 insertions(+), 53 deletions(-) create mode 100644 src/virtual_device.rs diff --git a/src/graph_editor_egui.rs b/src/graph_editor_egui.rs index a4f8551..d4f10bf 100644 --- a/src/graph_editor_egui.rs +++ b/src/graph_editor_egui.rs @@ -4,9 +4,15 @@ use crate::color_hex_utils::*; use crate::device::Device; use crate::editor_state::GraphEditorState; use crate::graph_node_ui::*; -use crate::node_finder::NodeFinder; +use crate::node_finder::{NodeFinder, SelectedDevice}; +use crate::virtual_device::VirtualDevice; -pub fn draw_graph_editor(ctx: &CtxRef, state: &mut GraphEditorState, devices: &[Device]) { +pub fn draw_graph_editor( + ctx: &CtxRef, + state: &mut GraphEditorState, + devices: &[Device], + virtual_device: &mut Option, +) { let mouse = &ctx.input().pointer; let cursor_pos = mouse.hover_pos().unwrap_or(Pos2::ZERO); @@ -49,12 +55,17 @@ pub fn draw_graph_editor(ctx: &CtxRef, state: &mut GraphEditorState, devices: &[ node_finder_area = node_finder_area.current_pos(pos); } node_finder_area.show(ctx, |ui| { - if let Some(node_device) = node_finder.show(devices, ui) { + if let Some(node_device) = node_finder.show(devices, virtual_device.is_none(), ui) { let new_node = state.graph.add_node(node_device.to_descriptor()); state .node_positions .insert(new_node, cursor_pos - state.pan_zoom.pan); should_close_node_finder = true; + + if let SelectedDevice::Virtual(mut virt) = node_device { + virt.connect_id(new_node); + *virtual_device = Some(virt); + } } }); } @@ -115,6 +126,12 @@ pub fn draw_graph_editor(ctx: &CtxRef, state: &mut GraphEditorState, devices: &[ state.run_side_effect = Some(node_id); } DrawGraphNodeResponse::DeleteNode(node_id) => { + if let Some(virt) = virtual_device { + if node_id == virt.node_id() { + *virtual_device = None; + } + } + state.graph.remove_node(node_id); state.node_positions.remove(&node_id); // Make sure to not leave references to old nodes hanging diff --git a/src/graph_impls.rs b/src/graph_impls.rs index bc5cd85..8662f58 100644 --- a/src/graph_impls.rs +++ b/src/graph_impls.rs @@ -159,10 +159,4 @@ impl Node { .map(|x| x.1) .ok_or_else(|| anyhow!("Node {:?} has no parameter named {}", self.id, name)) } - - // Can this node be enabled on the UI? I.e. does it output a mesh? - // pub fn can_be_enabled(&self, graph: &Graph) -> bool { - // self.outputs(graph) - // .any(|output| output.typ == DataType::Mesh) - // } } diff --git a/src/graph_node_ui.rs b/src/graph_node_ui.rs index 43006db..4ae493c 100644 --- a/src/graph_node_ui.rs +++ b/src/graph_node_ui.rs @@ -114,34 +114,12 @@ impl<'a> GraphNodeWidget<'a> { } let outputs = graph[node_id].outputs.clone(); - for (param_name, _param) in outputs { + for (param_name, param) in outputs { let height_before = ui.min_rect().bottom(); - ui.label(¶m_name); + graph.output(param).value_widget(¶m_name, ui); let height_after = ui.min_rect().bottom(); output_port_heights.push((height_before + height_after) / 2.0); } - - // // Button row - // ui.horizontal(|ui| { - // // Show 'Enable' button for nodes that output a mesh - // if graph[node_id].can_be_enabled(graph) { - // ui.horizontal(|ui| { - // if !active { - // if ui.button("👁 Set active").clicked() { - // response = Some(DrawGraphNodeResponse::SetActiveNode(node_id)); - // } - // } else { - // let button = egui::Button::new( - // RichText::new("👁 Active").color(egui::Color32::BLACK), - // ) - // .fill(egui::Color32::GOLD); - // if ui.add(button).clicked() { - // response = Some(DrawGraphNodeResponse::ClearActiveNode); - // } - // } - // }); - // } - // }) }); // Second pass, iterate again to draw the ports. This happens outside @@ -162,6 +140,7 @@ impl<'a> GraphNodeWidget<'a> { port_locations: &mut PortLocations, ongoing_drag: Option<(NodeId, ID)>, is_connected_input: bool, + color: Color32, ) { let port_rect = Rect::from_center_size(port_pos, egui::vec2(10.0, 10.0)); @@ -175,7 +154,7 @@ impl<'a> GraphNodeWidget<'a> { let port_color = if resp.hovered() { Color32::WHITE } else { - color_from_hex("#4b7f52").unwrap() + color }; ui.painter() .circle(port_rect.center(), 5.0, port_color, Stroke::none()); @@ -222,6 +201,7 @@ impl<'a> GraphNodeWidget<'a> { port_locations, ongoing_drag, graph.connection(*param).is_some(), + color_from_hex("#4b7f52").unwrap(), ); } } @@ -243,6 +223,7 @@ impl<'a> GraphNodeWidget<'a> { port_locations, ongoing_drag, false, + color_from_hex("#cd131f").unwrap(), ); } diff --git a/src/main.rs b/src/main.rs index bc923bc..b00981f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,20 +12,24 @@ mod id_types; mod index_impls; mod node_finder; mod param_ui; +mod virtual_device; use device::Device; +use virtual_device::VirtualDevice; #[derive(Default)] struct App { - pub state: GraphEditorState, - pub devices: Vec, + state: GraphEditorState, + devices: Vec, + virtual_device: Option, } impl App { fn new() -> Self { Self { state: GraphEditorState::default(), - devices: dbg!(Device::query()), + devices: Device::query(), + virtual_device: None, } } } @@ -33,7 +37,12 @@ impl App { impl epi::App for App { fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) { egui::CentralPanel::default().show(ctx, |_| { - graph_editor_egui::draw_graph_editor(&ctx, &mut self.state, &self.devices); + graph_editor_egui::draw_graph_editor( + &ctx, + &mut self.state, + &self.devices, + &mut self.virtual_device, + ); }); } diff --git a/src/node_finder.rs b/src/node_finder.rs index 2ce1cea..02851a5 100644 --- a/src/node_finder.rs +++ b/src/node_finder.rs @@ -2,6 +2,22 @@ use egui::*; use crate::color_hex_utils::*; use crate::device::Device; +use crate::graph_types::NodeDescriptor; +use crate::virtual_device::VirtualDevice; + +pub enum SelectedDevice<'a> { + Virtual(VirtualDevice), + Physical(&'a Device), +} + +impl<'a> SelectedDevice<'a> { + pub fn to_descriptor(&self) -> NodeDescriptor { + match self { + SelectedDevice::Virtual(dev) => dev.to_descriptor(), + SelectedDevice::Physical(dev) => dev.to_descriptor(), + } + } +} #[derive(Default)] pub struct NodeFinder { @@ -23,7 +39,12 @@ impl NodeFinder { /// Shows the node selector panel with a search bar. Returns whether a node /// archetype was selected and, in that case, the finder should be hidden on /// the next frame. - pub fn show<'a>(&mut self, devices: &'a [Device], ui: &mut Ui) -> Option<&'a Device> { + pub fn show<'a>( + &mut self, + devices: &'a [Device], + allow_virt_dev: bool, + ui: &mut Ui, + ) -> Option> { let background_color = color_from_hex("#3f3f3f").unwrap(); let _titlebar_color = background_color.linear_multiply(0.8); let text_color = color_from_hex("#fefefe").unwrap(); @@ -38,24 +59,20 @@ impl NodeFinder { let mut submitted_device = None; frame.show(ui, |ui| { ui.vertical(|ui| { - let resp = ui.text_edit_singleline(&mut self.query); - if self.just_spawned { - resp.request_focus(); - self.just_spawned = false; - } - - let mut query_submit = resp.lost_focus() && ui.input().key_down(Key::Enter); - Frame::default().margin(vec2(10.0, 10.0)).show(ui, |ui| { + if allow_virt_dev { + if ui.selectable_label(false, "New Virtual Device").clicked() { + submitted_device = Some(SelectedDevice::Virtual(VirtualDevice::new( + "New Virtual Device", + ))); + } + } + for device in devices { let device_name = device.name(); if device_name.contains(self.query.as_str()) { - if query_submit { - submitted_device = Some(device); - query_submit = false; - } if ui.selectable_label(false, device_name).clicked() { - submitted_device = Some(device); + submitted_device = Some(SelectedDevice::Physical(device)); } } } diff --git a/src/param_ui.rs b/src/param_ui.rs index 34c0e01..2cca22a 100644 --- a/src/param_ui.rs +++ b/src/param_ui.rs @@ -9,7 +9,7 @@ impl Param { ui.label(name); } Descriptor::Button => { - ui.label(name); + ui.horizontal(|ui| ui.centered_and_justified(|ui| ui.label(name))); } Descriptor::Slider { min, max } => { ui.horizontal(|ui| { @@ -20,6 +20,7 @@ impl Param { .text(format!("{}", 0)), ); ui.label(format!("{}", max)); + ui.label(name); }); } } diff --git a/src/virtual_device.rs b/src/virtual_device.rs new file mode 100644 index 0000000..9227496 --- /dev/null +++ b/src/virtual_device.rs @@ -0,0 +1,31 @@ +use crate::{graph_types::NodeDescriptor, id_types::NodeId}; + +pub struct VirtualDevice { + name: String, + node_id: Option, +} + +impl VirtualDevice { + pub fn new(name: impl ToString) -> Self { + Self { + name: name.to_string(), + node_id: None, + } + } + + pub fn connect_id(&mut self, node_id: NodeId) { + self.node_id = Some(node_id); + } + + pub fn node_id(&self) -> NodeId { + self.node_id.unwrap() + } + + pub fn to_descriptor(&self) -> NodeDescriptor { + NodeDescriptor { + op_name: self.name.clone(), + inputs: Vec::new(), + outputs: Vec::new(), + } + } +}