Improve device panel
This commit is contained in:
parent
b4625849f1
commit
0c4e217fa7
7 changed files with 103 additions and 53 deletions
|
@ -4,9 +4,15 @@ use crate::color_hex_utils::*;
|
||||||
use crate::device::Device;
|
use crate::device::Device;
|
||||||
use crate::editor_state::GraphEditorState;
|
use crate::editor_state::GraphEditorState;
|
||||||
use crate::graph_node_ui::*;
|
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<VirtualDevice>,
|
||||||
|
) {
|
||||||
let mouse = &ctx.input().pointer;
|
let mouse = &ctx.input().pointer;
|
||||||
let cursor_pos = mouse.hover_pos().unwrap_or(Pos2::ZERO);
|
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 = node_finder_area.current_pos(pos);
|
||||||
}
|
}
|
||||||
node_finder_area.show(ctx, |ui| {
|
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());
|
let new_node = state.graph.add_node(node_device.to_descriptor());
|
||||||
state
|
state
|
||||||
.node_positions
|
.node_positions
|
||||||
.insert(new_node, cursor_pos - state.pan_zoom.pan);
|
.insert(new_node, cursor_pos - state.pan_zoom.pan);
|
||||||
should_close_node_finder = true;
|
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);
|
state.run_side_effect = Some(node_id);
|
||||||
}
|
}
|
||||||
DrawGraphNodeResponse::DeleteNode(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.graph.remove_node(node_id);
|
||||||
state.node_positions.remove(&node_id);
|
state.node_positions.remove(&node_id);
|
||||||
// Make sure to not leave references to old nodes hanging
|
// Make sure to not leave references to old nodes hanging
|
||||||
|
|
|
@ -159,10 +159,4 @@ impl Node {
|
||||||
.map(|x| x.1)
|
.map(|x| x.1)
|
||||||
.ok_or_else(|| anyhow!("Node {:?} has no parameter named {}", self.id, name))
|
.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)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,34 +114,12 @@ impl<'a> GraphNodeWidget<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let outputs = graph[node_id].outputs.clone();
|
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();
|
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();
|
let height_after = ui.min_rect().bottom();
|
||||||
output_port_heights.push((height_before + height_after) / 2.0);
|
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
|
// Second pass, iterate again to draw the ports. This happens outside
|
||||||
|
@ -162,6 +140,7 @@ impl<'a> GraphNodeWidget<'a> {
|
||||||
port_locations: &mut PortLocations,
|
port_locations: &mut PortLocations,
|
||||||
ongoing_drag: Option<(NodeId, ID)>,
|
ongoing_drag: Option<(NodeId, ID)>,
|
||||||
is_connected_input: bool,
|
is_connected_input: bool,
|
||||||
|
color: Color32,
|
||||||
) {
|
) {
|
||||||
let port_rect = Rect::from_center_size(port_pos, egui::vec2(10.0, 10.0));
|
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() {
|
let port_color = if resp.hovered() {
|
||||||
Color32::WHITE
|
Color32::WHITE
|
||||||
} else {
|
} else {
|
||||||
color_from_hex("#4b7f52").unwrap()
|
color
|
||||||
};
|
};
|
||||||
ui.painter()
|
ui.painter()
|
||||||
.circle(port_rect.center(), 5.0, port_color, Stroke::none());
|
.circle(port_rect.center(), 5.0, port_color, Stroke::none());
|
||||||
|
@ -222,6 +201,7 @@ impl<'a> GraphNodeWidget<'a> {
|
||||||
port_locations,
|
port_locations,
|
||||||
ongoing_drag,
|
ongoing_drag,
|
||||||
graph.connection(*param).is_some(),
|
graph.connection(*param).is_some(),
|
||||||
|
color_from_hex("#4b7f52").unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,6 +223,7 @@ impl<'a> GraphNodeWidget<'a> {
|
||||||
port_locations,
|
port_locations,
|
||||||
ongoing_drag,
|
ongoing_drag,
|
||||||
false,
|
false,
|
||||||
|
color_from_hex("#cd131f").unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
src/main.rs
17
src/main.rs
|
@ -12,20 +12,24 @@ mod id_types;
|
||||||
mod index_impls;
|
mod index_impls;
|
||||||
mod node_finder;
|
mod node_finder;
|
||||||
mod param_ui;
|
mod param_ui;
|
||||||
|
mod virtual_device;
|
||||||
|
|
||||||
use device::Device;
|
use device::Device;
|
||||||
|
use virtual_device::VirtualDevice;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct App {
|
struct App {
|
||||||
pub state: GraphEditorState,
|
state: GraphEditorState,
|
||||||
pub devices: Vec<Device>,
|
devices: Vec<Device>,
|
||||||
|
virtual_device: Option<VirtualDevice>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: GraphEditorState::default(),
|
state: GraphEditorState::default(),
|
||||||
devices: dbg!(Device::query()),
|
devices: Device::query(),
|
||||||
|
virtual_device: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +37,12 @@ impl App {
|
||||||
impl epi::App for App {
|
impl epi::App for App {
|
||||||
fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) {
|
fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) {
|
||||||
egui::CentralPanel::default().show(ctx, |_| {
|
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,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,22 @@ use egui::*;
|
||||||
|
|
||||||
use crate::color_hex_utils::*;
|
use crate::color_hex_utils::*;
|
||||||
use crate::device::Device;
|
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)]
|
#[derive(Default)]
|
||||||
pub struct NodeFinder {
|
pub struct NodeFinder {
|
||||||
|
@ -23,7 +39,12 @@ impl NodeFinder {
|
||||||
/// Shows the node selector panel with a search bar. Returns whether a node
|
/// 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
|
/// archetype was selected and, in that case, the finder should be hidden on
|
||||||
/// the next frame.
|
/// 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<SelectedDevice<'a>> {
|
||||||
let background_color = color_from_hex("#3f3f3f").unwrap();
|
let background_color = color_from_hex("#3f3f3f").unwrap();
|
||||||
let _titlebar_color = background_color.linear_multiply(0.8);
|
let _titlebar_color = background_color.linear_multiply(0.8);
|
||||||
let text_color = color_from_hex("#fefefe").unwrap();
|
let text_color = color_from_hex("#fefefe").unwrap();
|
||||||
|
@ -38,24 +59,20 @@ impl NodeFinder {
|
||||||
let mut submitted_device = None;
|
let mut submitted_device = None;
|
||||||
frame.show(ui, |ui| {
|
frame.show(ui, |ui| {
|
||||||
ui.vertical(|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| {
|
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 {
|
for device in devices {
|
||||||
let device_name = device.name();
|
let device_name = device.name();
|
||||||
if device_name.contains(self.query.as_str()) {
|
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() {
|
if ui.selectable_label(false, device_name).clicked() {
|
||||||
submitted_device = Some(device);
|
submitted_device = Some(SelectedDevice::Physical(device));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ impl Param {
|
||||||
ui.label(name);
|
ui.label(name);
|
||||||
}
|
}
|
||||||
Descriptor::Button => {
|
Descriptor::Button => {
|
||||||
ui.label(name);
|
ui.horizontal(|ui| ui.centered_and_justified(|ui| ui.label(name)));
|
||||||
}
|
}
|
||||||
Descriptor::Slider { min, max } => {
|
Descriptor::Slider { min, max } => {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
@ -20,6 +20,7 @@ impl Param {
|
||||||
.text(format!("{}", 0)),
|
.text(format!("{}", 0)),
|
||||||
);
|
);
|
||||||
ui.label(format!("{}", max));
|
ui.label(format!("{}", max));
|
||||||
|
ui.label(name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
src/virtual_device.rs
Normal file
31
src/virtual_device.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
use crate::{graph_types::NodeDescriptor, id_types::NodeId};
|
||||||
|
|
||||||
|
pub struct VirtualDevice {
|
||||||
|
name: String,
|
||||||
|
node_id: Option<NodeId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue