mirror of
https://github.com/eliasstepanik/egui_node_graph.git
synced 2026-01-11 13:58:28 +00:00
Merge pull request #19 from nodeSpace/patch-1
Make editor ui work inside egui windows.
This commit is contained in:
commit
269e945256
@ -60,10 +60,17 @@ where
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn draw_graph_editor(
|
pub fn draw_graph_editor(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Context,
|
ui: &mut Ui,
|
||||||
all_kinds: impl NodeTemplateIter<Item = NodeTemplate>,
|
all_kinds: impl NodeTemplateIter<Item = NodeTemplate>,
|
||||||
) -> GraphResponse<UserResponse> {
|
) -> GraphResponse<UserResponse> {
|
||||||
let cursor_pos = ctx.input().pointer.hover_pos().unwrap_or(Pos2::ZERO);
|
// This causes the graph editor to use as much free space as it can.
|
||||||
|
// (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();
|
||||||
@ -82,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;
|
||||||
@ -116,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 {
|
||||||
@ -143,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,24 +235,26 @@ where
|
|||||||
/* Mouse input handling */
|
/* Mouse input handling */
|
||||||
|
|
||||||
// This locks the context, so don't hold on to it for too long.
|
// This locks the context, so don't hold on to it for too long.
|
||||||
let mouse = &ctx.input().pointer;
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -353,7 +353,11 @@ impl eframe::App for NodeGraphExample {
|
|||||||
/// 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::Context, _frame: &mut eframe::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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user