Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

Update to egui 0.20 #79

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
Cargo.lock
dist/
2 changes: 1 addition & 1 deletion egui_node_graph/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ workspace = ".."
persistence = ["serde", "slotmap/serde", "smallvec/serde", "egui/persistence"]

[dependencies]
egui = { version = "0.19.0" }
egui = { version = "0.20.0" }
slotmap = { version = "1.0" }
smallvec = { version = "1.7.0" }
serde = { version = "1.0", optional = true, features = ["derive"] }
Expand Down
174 changes: 86 additions & 88 deletions egui_node_graph/src/editor_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::utils::ColorUtils;

use super::*;
use egui::epaint::{CubicBezierShape, RectShape};
use egui::style::Margin;
use egui::*;

pub type PortLocations = std::collections::HashMap<AnyParameterId, Pos2>;
Expand Down Expand Up @@ -408,9 +409,9 @@ where
self.node_finder = None;
}

if r.dragged() && ui.ctx().input().pointer.middle_down() {
self.pan_zoom.pan += ui.ctx().input().pointer.delta();
}
// if r.dragged() && ui.ctx().input().pointer.middle_down() {
// self.pan_zoom.pan += ui.ctx().input().pointer.delta();
// }

// Deselect and deactivate finder if the editor backround is clicked,
// *or* if the the mouse clicks off the ui
Expand Down Expand Up @@ -488,7 +489,12 @@ where
ui: &mut Ui,
user_state: &mut UserState,
) -> Vec<NodeResponse<UserResponse, NodeData>> {
let margin = egui::vec2(15.0, 5.0);
let margin = Margin {
left: 15.0,
right: 15.0,
top: 5.0,
bottom: 15.0,
};
let mut responses = Vec::<NodeResponse<UserResponse, NodeData>>::new();

let background_color;
Expand All @@ -507,82 +513,76 @@ where
let outline_shape = ui.painter().add(Shape::Noop);
let background_shape = ui.painter().add(Shape::Noop);

let outer_rect_bounds = ui.available_rect_before_wrap();
let mut inner_rect = outer_rect_bounds.shrink2(margin);

// Make sure we don't shrink to the negative:
inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x);
inner_rect.max.y = inner_rect.max.y.max(inner_rect.min.y);

let mut child_ui = ui.child_ui(inner_rect, *ui.layout());
let mut title_height = 0.0;

let mut input_port_heights = vec![];
let mut output_port_heights = vec![];

child_ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.add(Label::new(
RichText::new(&self.graph[self.node_id].label)
.text_style(TextStyle::Button)
.color(text_color),
));
ui.add_space(8.0); // The size of the little cross icon
});
ui.add_space(margin.y);
title_height = ui.min_size().y;
Frame::none().inner_margin(margin).show(ui, |ui| {
ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.add(Label::new(
RichText::new(&self.graph[self.node_id].label)
.text_style(TextStyle::Button)
.color(text_color),
));
ui.add_space(8.0); // The size of the little cross icon
});
title_height = ui.min_size().y;
ui.add_space(margin.top);

// First pass: Draw the inner fields. Compute port heights
let inputs = self.graph[self.node_id].inputs.clone();
for (param_name, param_id) in inputs {
if self.graph[param_id].shown_inline {
let height_before = ui.min_rect().bottom();
if self.graph.connection(param_id).is_some() {
ui.label(param_name);
} else {
// NOTE: We want to pass the `user_data` to
// `value_widget`, but we can't since that would require
// borrowing the graph twice. Here, we make the
// assumption that the value is cheaply replaced, and
// use `std::mem::take` to temporarily replace it with a
// dummy value. This requires `ValueType` to implement
// Default, but results in a totally safe alternative.
let mut value = std::mem::take(&mut self.graph[param_id].value);
let node_responses = value.value_widget(
&param_name,
self.node_id,
ui,
user_state,
&self.graph[self.node_id].user_data,
);
self.graph[param_id].value = value;
responses.extend(node_responses.into_iter().map(NodeResponse::User));
}
let height_after = ui.min_rect().bottom();
input_port_heights.push((height_before + height_after) / 2.0);
}
}

// First pass: Draw the inner fields. Compute port heights
let inputs = self.graph[self.node_id].inputs.clone();
for (param_name, param_id) in inputs {
if self.graph[param_id].shown_inline {
let outputs = self.graph[self.node_id].outputs.clone();
for (param_name, _param) in outputs {
let height_before = ui.min_rect().bottom();
if self.graph.connection(param_id).is_some() {
ui.label(param_name);
} else {
// NOTE: We want to pass the `user_data` to
// `value_widget`, but we can't since that would require
// borrowing the graph twice. Here, we make the
// assumption that the value is cheaply replaced, and
// use `std::mem::take` to temporarily replace it with a
// dummy value. This requires `ValueType` to implement
// Default, but results in a totally safe alternative.
let mut value = std::mem::take(&mut self.graph[param_id].value);
let node_responses = value.value_widget(
&param_name,
self.node_id,
ui,
user_state,
&self.graph[self.node_id].user_data,
);
self.graph[param_id].value = value;
responses.extend(node_responses.into_iter().map(NodeResponse::User));
}
ui.label(&param_name);
let height_after = ui.min_rect().bottom();
input_port_heights.push((height_before + height_after) / 2.0);
output_port_heights.push((height_before + height_after) / 2.0);
}
}

let outputs = self.graph[self.node_id].outputs.clone();
for (param_name, _param) in outputs {
let height_before = ui.min_rect().bottom();
ui.label(&param_name);
let height_after = ui.min_rect().bottom();
output_port_heights.push((height_before + height_after) / 2.0);
}

responses.extend(
self.graph[self.node_id]
.user_data
.bottom_ui(ui, self.node_id, self.graph, user_state)
.into_iter(),
);
responses.extend(
self.graph[self.node_id]
.user_data
.bottom_ui(ui, self.node_id, self.graph, user_state)
.into_iter(),
);
})
});

// Second pass, iterate again to draw the ports. This happens outside
// the child_ui because we want ports to overflow the node background.

let outer_rect = child_ui.min_rect().expand2(margin);
let outer_rect = ui.min_rect();
let port_left = outer_rect.left();
let port_right = outer_rect.right();

Expand Down Expand Up @@ -628,7 +628,7 @@ where
port_type.data_type_color(user_state)
};
ui.painter()
.circle(port_rect.center(), 5.0, port_color, Stroke::none());
.circle(port_rect.center(), 5.0, port_color, Stroke::NONE);

if resp.drag_started() {
if is_connected_input {
Expand Down Expand Up @@ -722,50 +722,48 @@ where

let (shape, outline) = {
let rounding_radius = 4.0;
let rounding = Rounding::same(rounding_radius);

let titlebar_height = title_height + margin.y;
let titlebar_height = title_height + margin.top * 2.0;
let titlebar_rect =
Rect::from_min_size(outer_rect.min, vec2(outer_rect.width(), titlebar_height));
let titlebar = Shape::Rect(RectShape {
rect: titlebar_rect,
rounding,
rounding: Rounding {
nw: rounding_radius,
ne: rounding_radius,
sw: 0.0,
se: 0.0,
},
fill: self.graph[self.node_id]
.user_data
.titlebar_color(ui, self.node_id, self.graph, user_state)
.unwrap_or_else(|| background_color.lighten(0.8)),
stroke: Stroke::none(),
stroke: Stroke::NONE,
});

let body_rect = Rect::from_min_size(
outer_rect.min + vec2(0.0, titlebar_height - rounding_radius),
outer_rect.min + vec2(0.0, titlebar_height),
vec2(outer_rect.width(), outer_rect.height() - titlebar_height),
);
let body = Shape::Rect(RectShape {
rect: body_rect,
rounding: Rounding::none(),
fill: background_color,
stroke: Stroke::none(),
});

let bottom_body_rect = Rect::from_min_size(
body_rect.min + vec2(0.0, body_rect.height() - titlebar_height * 0.5),
vec2(outer_rect.width(), titlebar_height),
);
let bottom_body = Shape::Rect(RectShape {
rect: bottom_body_rect,
rounding,
rounding: Rounding {
nw: 0.0,
ne: 0.0,
sw: rounding_radius,
se: rounding_radius,
},
fill: background_color,
stroke: Stroke::none(),
stroke: Stroke::NONE,
});

let node_rect = titlebar_rect.union(body_rect).union(bottom_body_rect);
let node_rect = titlebar_rect.union(body_rect);
let outline = if self.selected {
Shape::Rect(RectShape {
rect: node_rect.expand(1.0),
rounding,
rounding: Rounding::same(rounding_radius),
fill: Color32::WHITE.lighten(0.8),
stroke: Stroke::none(),
stroke: Stroke::NONE,
})
} else {
Shape::Noop
Expand All @@ -774,7 +772,7 @@ where
// Take note of the node rect, so the editor can use it later to compute intersections.
self.node_rects.insert(self.node_id, node_rect);

(Shape::Vec(vec![titlebar, body, bottom_body]), outline)
(Shape::Vec(vec![titlebar, body]), outline)
};

ui.painter().set(background_shape, shape);
Expand Down
14 changes: 10 additions & 4 deletions egui_node_graph_example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ rust-version = "1.56"
[lib]
crate-type = ["cdylib", "rlib"]

[features]
default = []
persistence = ["serde", "egui_node_graph/persistence", "eframe/persistence"]

[dependencies]
eframe = "0.19.0"
eframe = "0.20.0"
egui_node_graph = { path = "../egui_node_graph" }
anyhow = "1.0"
serde = { version = "1.0", optional = true }

[features]
default = []
persistence = ["serde", "egui_node_graph/persistence", "eframe/persistence"]
# web:
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen-futures = "0.4"
console_error_panic_hook = "0.1.6"
tracing-wasm = "0.2"

[profile.release]
opt-level = 2 # fast and small wasm
2 changes: 2 additions & 0 deletions egui_node_graph_example/Trunk.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
filehash = false
Binary file added egui_node_graph_example/assets/favicon.ico
Binary file not shown.
Binary file added egui_node_graph_example/assets/icon-1024.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added egui_node_graph_example/assets/icon-256.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions egui_node_graph_example/assets/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "egui Template PWA",
"short_name": "egui-template-pwa",
"icons": [
{
"src": "./icon-256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "./maskable_icon_x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "./icon-1024.png",
"sizes": "1024x1024",
"type": "image/png"
}
],
"lang": "en-US",
"id": "/index.html",
"start_url": "./index.html",
"display": "standalone",
"background_color": "white",
"theme_color": "white"
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions egui_node_graph_example/assets/sw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
var cacheName = 'egui-template-pwa';
var filesToCache = [
'./',
'./index.html',
'./egui_node_graph_example.js',
'./egui_node_graph_example_bg.wasm',
];

/* Start the service worker and cache all of the app's content */
self.addEventListener('install', function (e) {
e.waitUntil(
caches.open(cacheName).then(function (cache) {
return cache.addAll(filesToCache);
})
);
});

/* Serve cached content when offline */
self.addEventListener('fetch', function (e) {
e.respondWith(
caches.match(e.request).then(function (response) {
return response || fetch(e.request);
})
);
});
Loading