Fix merge conflicts and update to latest main

This commit is contained in:
Setzer22 2022-05-24 11:48:19 +02:00
commit 84884f05a9
6 changed files with 97 additions and 73 deletions

View File

@ -15,7 +15,7 @@ workspace = ".."
persistence = ["serde", "slotmap/serde", "smallvec/serde", "egui/persistence"] persistence = ["serde", "slotmap/serde", "smallvec/serde", "egui/persistence"]
[dependencies] [dependencies]
egui = { version = "0.16" } egui = { version = "0.18" }
slotmap = { version = "1.0" } slotmap = { version = "1.0" }
smallvec = { version = "1.7.0" } smallvec = { version = "1.7.0" }
serde = { version = "1.0", optional = true, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] }

View File

@ -60,11 +60,17 @@ where
#[must_use] #[must_use]
pub fn draw_graph_editor( pub fn draw_graph_editor(
&mut self, &mut self,
ctx: &CtxRef, ui: &mut Ui,
all_kinds: impl NodeTemplateIter<Item = NodeTemplate>, all_kinds: impl NodeTemplateIter<Item = NodeTemplate>,
) -> GraphResponse<UserResponse> { ) -> GraphResponse<UserResponse> {
let mouse = &ctx.input().pointer; // This causes the graph editor to use as much free space as it can.
let cursor_pos = mouse.hover_pos().unwrap_or(Pos2::ZERO); // (so for windows it will use up to the resizeably set limit
// and for a Panel it will fill it completely)
let editor_rect = ui.max_rect();
ui.allocate_rect(editor_rect, Sense::hover());
let cursor_pos = ui.ctx().input().pointer.hover_pos().unwrap_or(Pos2::ZERO);
let mut cursor_in_editor = editor_rect.contains(cursor_pos);
// Gets filled with the port locations as nodes are drawn // Gets filled with the port locations as nodes are drawn
let mut port_locations = PortLocations::new(); let mut port_locations = PortLocations::new();
@ -83,32 +89,30 @@ where
inconsistent self. It has either more or less values than the graph." inconsistent self. It has either more or less values than the graph."
); );
CentralPanel::default().show(ctx, |ui| { /* Draw nodes */
/* Draw nodes */ for node_id in self.node_order.iter().copied() {
for node_id in self.node_order.iter().copied() { let responses = GraphNodeWidget {
let responses = GraphNodeWidget { position: self.node_positions.get_mut(node_id).unwrap(),
position: self.node_positions.get_mut(node_id).unwrap(), graph: &mut self.graph,
graph: &mut self.graph, port_locations: &mut port_locations,
port_locations: &mut port_locations, node_id,
node_id, ongoing_drag: self.connection_in_progress,
ongoing_drag: self.connection_in_progress, selected: self
selected: self .selected_node
.selected_node .map(|selected| selected == node_id)
.map(|selected| selected == node_id) .unwrap_or(false),
.unwrap_or(false), pan: self.pan_zoom.pan + editor_rect.min.to_vec2(),
pan: self.pan_zoom.pan, }
}
.show(ui, &self.user_state); .show(ui, &self.user_state);
// Actions executed later // Actions executed later
delayed_responses.extend(responses); delayed_responses.extend(responses);
} }
let r = ui.allocate_rect(ui.min_rect(), Sense::click()); let r = ui.allocate_rect(ui.min_rect(), Sense::click());
if r.clicked() { if r.clicked() {
click_on_background = true; click_on_background = true;
} }
});
/* Draw the node finder, if open */ /* Draw the node finder, if open */
let mut should_close_node_finder = false; let mut should_close_node_finder = false;
@ -117,20 +121,28 @@ where
if let Some(pos) = node_finder.position { if let Some(pos) = node_finder.position {
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(ui.ctx(), |ui| {
if let Some(node_kind) = node_finder.show(ui, all_kinds) { if let Some(node_kind) = node_finder.show(ui, all_kinds) {
let new_node = self.graph.add_node( let new_node = self.graph.add_node(
node_kind.node_graph_label(), node_kind.node_graph_label(),
node_kind.user_data(), node_kind.user_data(),
|graph, node_id| node_kind.build_node(graph, node_id), |graph, node_id| node_kind.build_node(graph, node_id),
); );
self.node_positions self.node_positions.insert(
.insert(new_node, cursor_pos - self.pan_zoom.pan); new_node,
cursor_pos - self.pan_zoom.pan - editor_rect.min.to_vec2()
);
self.node_order.push(new_node); self.node_order.push(new_node);
should_close_node_finder = true; should_close_node_finder = true;
delayed_responses.push(NodeResponse::CreatedNode(new_node)); delayed_responses.push(NodeResponse::CreatedNode(new_node));
} }
let finder_rect = ui.max_rect();
// If the cursor is not in the main editor, check if the cursor *is* in the finder
// if the cursor is in the finder, then we can consider that also in the editor.
if !cursor_in_editor && finder_rect.contains(cursor_pos){
cursor_in_editor = true;
}
}); });
} }
if should_close_node_finder { if should_close_node_finder {
@ -144,16 +156,14 @@ where
}; };
if let Some((_, ref locator)) = self.connection_in_progress { if let Some((_, ref locator)) = self.connection_in_progress {
let painter = ctx.layer_painter(LayerId::background());
let start_pos = port_locations[locator]; let start_pos = port_locations[locator];
painter.line_segment([start_pos, cursor_pos], connection_stroke) ui.painter().line_segment([start_pos, cursor_pos], connection_stroke)
} }
for (input, output) in self.graph.iter_connections() { for (input, output) in self.graph.iter_connections() {
let painter = ctx.layer_painter(LayerId::background());
let src_pos = port_locations[&AnyParameterId::Output(output)]; let src_pos = port_locations[&AnyParameterId::Output(output)];
let dst_pos = port_locations[&AnyParameterId::Input(input)]; let dst_pos = port_locations[&AnyParameterId::Input(input)];
painter.line_segment([src_pos, dst_pos], connection_stroke); ui.painter().line_segment([src_pos, dst_pos], connection_stroke);
} }
/* Handle responses from drawing nodes */ /* Handle responses from drawing nodes */
@ -224,22 +234,27 @@ where
/* Mouse input handling */ /* Mouse input handling */
// This locks the context, so don't hold on to it for too long.
let mouse = &ui.ctx().input().pointer;
if mouse.any_released() && self.connection_in_progress.is_some() { if mouse.any_released() && self.connection_in_progress.is_some() {
self.connection_in_progress = None; self.connection_in_progress = None;
} }
if mouse.button_down(PointerButton::Secondary) { if mouse.button_down(PointerButton::Secondary) && cursor_in_editor{
self.node_finder = Some(NodeFinder::new_at(cursor_pos)); self.node_finder = Some(NodeFinder::new_at(cursor_pos));
} }
if ctx.input().key_pressed(Key::Escape) { if ui.ctx().input().key_pressed(Key::Escape) {
self.node_finder = None; self.node_finder = None;
} }
if ctx.input().pointer.middle_down() { if ui.ctx().input().pointer.middle_down() {
self.pan_zoom.pan += ctx.input().pointer.delta(); self.pan_zoom.pan += ui.ctx().input().pointer.delta();
} }
if click_on_background { // Deselect and deactivate finder if the editor backround is clicked,
// *or* if the the mouse clicks off the ui
if click_on_background || (mouse.any_click() && !cursor_in_editor){
self.selected_node = None; self.selected_node = None;
self.node_finder = None; self.node_finder = None;
} }
@ -467,25 +482,26 @@ where
// does not support drawing rectangles with asymmetrical round corners. // does not support drawing rectangles with asymmetrical round corners.
let (shape, outline) = { let (shape, outline) = {
let corner_radius = 4.0; let rounding_radius = 4.0;
let rounding = Rounding::same(rounding_radius);
let titlebar_height = title_height + margin.y; let titlebar_height = title_height + margin.y;
let titlebar_rect = let titlebar_rect =
Rect::from_min_size(outer_rect.min, vec2(outer_rect.width(), titlebar_height)); Rect::from_min_size(outer_rect.min, vec2(outer_rect.width(), titlebar_height));
let titlebar = Shape::Rect(RectShape { let titlebar = Shape::Rect(RectShape {
rect: titlebar_rect, rect: titlebar_rect,
corner_radius, rounding,
fill: titlebar_color, fill: titlebar_color,
stroke: Stroke::none(), stroke: Stroke::none(),
}); });
let body_rect = Rect::from_min_size( let body_rect = Rect::from_min_size(
outer_rect.min + vec2(0.0, titlebar_height - corner_radius), outer_rect.min + vec2(0.0, titlebar_height - rounding_radius),
vec2(outer_rect.width(), outer_rect.height() - titlebar_height), vec2(outer_rect.width(), outer_rect.height() - titlebar_height),
); );
let body = Shape::Rect(RectShape { let body = Shape::Rect(RectShape {
rect: body_rect, rect: body_rect,
corner_radius: 0.0, rounding: Rounding::none(),
fill: background_color, fill: background_color,
stroke: Stroke::none(), stroke: Stroke::none(),
}); });
@ -496,7 +512,7 @@ where
); );
let bottom_body = Shape::Rect(RectShape { let bottom_body = Shape::Rect(RectShape {
rect: bottom_body_rect, rect: bottom_body_rect,
corner_radius, rounding,
fill: background_color, fill: background_color,
stroke: Stroke::none(), stroke: Stroke::none(),
}); });
@ -507,7 +523,7 @@ where
.union(body_rect) .union(body_rect)
.union(bottom_body_rect) .union(bottom_body_rect)
.expand(1.0), .expand(1.0),
corner_radius: 4.0, rounding,
fill: Color32::WHITE.lighten(0.8), fill: Color32::WHITE.lighten(0.8),
stroke: Stroke::none(), stroke: Stroke::none(),
}) })

View File

@ -41,7 +41,7 @@ where
let frame = Frame::dark_canvas(ui.style()) let frame = Frame::dark_canvas(ui.style())
.fill(background_color) .fill(background_color)
.margin(vec2(5.0, 5.0)); .inner_margin(vec2(5.0, 5.0));
// The archetype that will be returned. // The archetype that will be returned.
let mut submitted_archetype = None; let mut submitted_archetype = None;
@ -55,19 +55,21 @@ where
let mut query_submit = resp.lost_focus() && ui.input().key_down(Key::Enter); 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()
for kind in all_kinds.all_kinds() { .inner_margin(vec2(10.0, 10.0))
let kind_name = kind.node_finder_label().to_string(); .show(ui, |ui| {
if kind_name.contains(self.query.as_str()) { for kind in all_kinds.all_kinds() {
if ui.selectable_label(false, kind_name).clicked() { let kind_name = kind.node_finder_label().to_string();
submitted_archetype = Some(kind); if kind_name.contains(self.query.as_str()) {
} else if query_submit { if ui.selectable_label(false, kind_name).clicked() {
submitted_archetype = Some(kind); submitted_archetype = Some(kind);
query_submit = false; } else if query_submit {
submitted_archetype = Some(kind);
query_submit = false;
}
} }
} }
} });
});
}); });
}); });

View File

@ -9,7 +9,7 @@ rust-version = "1.56"
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[dependencies] [dependencies]
eframe = "0.16.0" eframe = "0.18.0"
egui_node_graph = { path = "../egui_node_graph" } egui_node_graph = { path = "../egui_node_graph" }
anyhow = "1.0" anyhow = "1.0"

View File

@ -1,9 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use eframe::{ use eframe::egui::{self, DragValue, TextStyle};
egui::{self, DragValue},
epi,
};
use egui_node_graph::*; use egui_node_graph::*;
// ========= First, define your user data types ============= // ========= First, define your user data types =============
@ -352,15 +349,17 @@ impl Default for NodeGraphExample {
} }
} }
impl epi::App for NodeGraphExample { impl eframe::App for NodeGraphExample {
fn name(&self) -> &str {
"Egui node graph example"
}
/// Called each time the UI needs repainting, which may be many times per second. /// Called each time the UI needs repainting, which may be many times per second.
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`. /// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let graph_response = self.state.draw_graph_editor(ctx, AllMyNodeTemplates); let graph_response = egui::Window::new("Graph")
.show(ctx, |ui| {
self.state.draw_graph_editor(ui, AllMyNodeTemplates)
})
.unwrap()
.inner
.unwrap();
for node_response in graph_response.node_responses { for node_response in graph_response.node_responses {
// Here, we ignore all other graph events. But you may find // Here, we ignore all other graph events. But you may find
// some use for them. For example, by playing a sound when a new // some use for them. For example, by playing a sound when a new
@ -385,7 +384,7 @@ impl epi::App for NodeGraphExample {
egui::pos2(10.0, 10.0), egui::pos2(10.0, 10.0),
egui::Align2::LEFT_TOP, egui::Align2::LEFT_TOP,
text, text,
egui::TextStyle::Button, TextStyle::Button.resolve(&ctx.style()),
egui::Color32::WHITE, egui::Color32::WHITE,
); );
} else { } else {

View File

@ -5,7 +5,14 @@
// When compiling natively: // When compiling natively:
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
fn main() { fn main() {
let app = egui_node_graph_example::NodeGraphExample::default(); use eframe::egui::Visuals;
let native_options = eframe::NativeOptions::default();
eframe::run_native(Box::new(app), native_options); eframe::run_native(
"Egui node graph example",
eframe::NativeOptions::default(),
Box::new(|cc| {
cc.egui_ctx.set_visuals(Visuals::dark());
Box::new(egui_node_graph_example::NodeGraphExample::default())
}),
);
} }