diff --git a/Cargo.toml b/Cargo.toml index d70bc89..babae97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -egui = "0" -epaint = "0" +egui = "0.27" +epaint = "0.27" +egui_hooks = "0.4" [dev-dependencies] -eframe = "0" +eframe = "0.27" diff --git a/src/cable.rs b/src/cable.rs index 12cdcdd..fe75f29 100644 --- a/src/cable.rs +++ b/src/cable.rs @@ -160,7 +160,7 @@ impl Widget for Cable { cable_state.drag_offset = vec2(0.0, 0.0); } } - if response.drag_released() { + if response.drag_stopped() { cable_state.dragged = false; } if response.dragged() { @@ -213,7 +213,6 @@ fn bezier_close(bezier: &QuadraticBezierShape, pointer_pos: Pos2, distance_sq: f let distance2 = bezier.points[1].distance(bezier.points[2]); let count = distance1 + distance2; (0..count as usize) - .into_iter() .map(|t| bezier.sample(t as f32 / count)) .any(|point| (point - pointer_pos).length_sq() < distance_sq) } diff --git a/src/cable_params.rs b/src/cable_params.rs index a0b0ab1..357a905 100644 --- a/src/cable_params.rs +++ b/src/cable_params.rs @@ -17,13 +17,13 @@ pub struct CableParams { impl CableParams { pub fn get(ui: &mut egui::Ui) -> Self { ui.data_mut(|data| { - let params = data.get_persisted::>(Id::null()).unwrap(); - data.remove::>(Id::null()); + let params = data.get_persisted::>(Id::NULL).unwrap(); + data.remove::>(Id::NULL); Arc::try_unwrap(params).unwrap() }) } pub(crate) fn set(self, ui: &mut egui::Ui) { - ui.data_mut(|data| data.insert_persisted(Id::null(), Arc::new(self))); + ui.data_mut(|data| data.insert_persisted(Id::NULL, Arc::new(self))); } } diff --git a/src/default_cable.rs b/src/default_cable.rs index 884168d..c0fa3ac 100644 --- a/src/default_cable.rs +++ b/src/default_cable.rs @@ -23,7 +23,11 @@ impl Widget for DefaultCable { let response = if line_hovered && !plugs_interacted { ui.add(cable_control) } else { - ui.interact(Rect::NOTHING, egui::Id::new("dummy-cable-control"), Sense::focusable_noninteractive()) + ui.interact( + Rect::NOTHING, + egui::Id::new("dummy-cable-control"), + Sense::focusable_noninteractive(), + ) }; let in_pos = bezier.points[0]; @@ -46,7 +50,7 @@ impl Widget for DefaultCable { center, cable_control_pos.distance(in_pos) / 2.0, cable_visual.fg_stroke, - ) + ); } else { ui.painter().add(bezier); } diff --git a/src/plug.rs b/src/plug.rs index 8c85611..bb33334 100644 --- a/src/plug.rs +++ b/src/plug.rs @@ -180,7 +180,7 @@ impl Widget for Plug { }); } - if response.drag_released() { + if response.drag_stopped() { match (self.plug_to, state.hovered_port_id()) { // Connect event (_, Some(port_id)) => { diff --git a/src/plug_params.rs b/src/plug_params.rs index 4b4dee6..084ebe7 100644 --- a/src/plug_params.rs +++ b/src/plug_params.rs @@ -12,10 +12,10 @@ pub struct PlugParams { impl PlugParams { pub fn get(ui: &mut egui::Ui) -> Arc { - ui.data_mut(|data| data.get_persisted::>(Id::null()).unwrap()) + ui.data_mut(|data| data.get_persisted::>(Id::NULL).unwrap()) } pub(crate) fn set(self, ui: &mut egui::Ui) { - ui.data_mut(|data| data.insert_persisted(Id::null(), Arc::new(self))); + ui.data_mut(|data| data.insert_persisted(Id::NULL, Arc::new(self))); } } diff --git a/src/port.rs b/src/port.rs index 73537f2..cee950e 100644 --- a/src/port.rs +++ b/src/port.rs @@ -2,6 +2,7 @@ use std::fmt::Debug; use std::hash::Hash; use egui::{Vec2, Widget}; +use egui_hooks::UseHookExt as _; use crate::{ custom_widget::CustomWidget, default_port::DefaultPort, id::Id, plug::DraggedPlug, @@ -32,44 +33,51 @@ impl Port { impl Widget for Port { fn ui(self, ui: &mut egui::Ui) -> egui::Response { - // This widget is not need to use egui::Area - - let mut state = State::get_cloned(ui); - - // Render port with params - PortParams { - hovered: state.hovered_port_id() == Some(self.port_id.clone()), - } - .set(ui); - let response = self.widget.unwrap_or_else(|| DefaultPort.into()).ui(ui); - - // advance generation if this port is rendered twice - state.advance_generation_if_twice(self.port_id.clone()); - // update port's position used for plug rendering - state.update_port_pos(self.port_id.clone(), response.rect.left_top()); - - let dragged_plug = state.dragged_plug().unwrap_or(DraggedPlug { - pos: egui::pos2(-100.0, -100.0), // far - size: Vec2::ZERO, - }); - - // distance between the port and the dragged plug - let distance_sq = response.rect.center().distance_sq(dragged_plug.pos); - let min_length = |vec: Vec2| vec.x.min(vec.y); - let close_distance = - (min_length(response.rect.size()) + min_length(dragged_plug.size)) / 2.0; - - // distance required because `response.hovered()` always returns false when plug is interacted - let hovered = response.hovered() || distance_sq < close_distance.powi(2); - - // update hovered port id used for cable connection - if hovered { - state.update_hovered_port_id(self.port_id); - } - - // finally update the state - state.store_to(ui); - - response + ui.push_id(self.port_id.clone(), |ui| { + // This widget is not need to use egui::Area + + let mut state = State::get_cloned(ui); + + // Render port with params + PortParams { + hovered: state.hovered_port_id() == Some(self.port_id.clone()), + } + .set(ui); + let response = self.widget.unwrap_or_else(|| DefaultPort.into()).ui(ui); + + // advance generation if this port is rendered twice + state.advance_generation_if_twice(self.port_id.clone()); + // update port's position used for plug rendering + state.update_port_pos(self.port_id.clone(), response.rect.left_top()); + + let dragged_plug = state.dragged_plug().unwrap_or(DraggedPlug { + pos: egui::pos2(-100.0, -100.0), // far + size: Vec2::ZERO, + }); + + println!("dragged: {:?}", dragged_plug.pos); + println!("response: {:?}", response.rect.center()); + + // distance between the port and the dragged plug + let distance_sq = response.rect.center().distance_sq(dragged_plug.pos); + let min_length = |vec: Vec2| vec.x.min(vec.y); + let close_distance = + (min_length(response.rect.size()) + min_length(dragged_plug.size)) / 2.0; + + // distance required because `response.hovered()` always returns false when plug is interacted + let hovered = response.hovered() || distance_sq < close_distance.powi(2); + + // update hovered port id used for cable connection + if hovered { + println!("hoverd: {:?}", self.port_id); + state.update_hovered_port_id(self.port_id); + } + + // finally update the state + state.store_to(ui); + + response + }) + .inner } } diff --git a/src/port_params.rs b/src/port_params.rs index cdf8087..8b097d2 100644 --- a/src/port_params.rs +++ b/src/port_params.rs @@ -9,10 +9,10 @@ pub struct PortParams { impl PortParams { pub fn get(ui: &mut egui::Ui) -> Arc { - ui.data_mut(|data| data.get_persisted::>(Id::null()).unwrap()) + ui.data_mut(|data| data.get_persisted::>(Id::NULL).unwrap()) } pub(crate) fn set(self, ui: &mut egui::Ui) { - ui.data_mut(|data| data.insert_persisted(Id::null(), Arc::new(self))); + ui.data_mut(|data| data.insert_persisted(Id::NULL, Arc::new(self))); } } diff --git a/src/state.rs b/src/state.rs index 2d04c97..da68f5a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -142,7 +142,7 @@ impl State { ui.data_mut(|data| { Self::clone( &data - .get_persisted::>(Id::null()) + .get_persisted::>(Id::NULL) .unwrap_or_default(), ) }) @@ -150,21 +150,21 @@ impl State { pub fn get(ui: &mut egui::Ui) -> Arc { ui.data_mut(|data| { - data.get_persisted::>(Id::null()) + data.get_persisted::>(Id::NULL) .unwrap_or_default() }) } pub fn get_with_ctx(ctx: &mut egui::Context) -> Arc { ctx.data_mut(|data| { - data.get_persisted::>(Id::null()) + data.get_persisted::>(Id::NULL) .unwrap_or_default() }) } pub fn store_to(self, ui: &mut egui::Ui) { ui.data_mut(|data| { - data.insert_persisted(Id::null(), Arc::new(self)); + data.insert_persisted(Id::NULL, Arc::new(self)); }); } }