From b4224566edf4504fa6fb44b864f6a34760559322 Mon Sep 17 00:00:00 2001 From: Konkitoman Date: Fri, 20 Oct 2023 20:52:34 +0300 Subject: [PATCH] Now all viewports repaint when pixels_per_point are changed Added zoom shortcuts for viewports example --- crates/egui/src/context.rs | 42 ++++++++++++++++++++++------------ crates/egui/src/memory.rs | 4 ++-- examples/viewports/src/main.rs | 31 +++++++++++++++++-------- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 56d046826..70c2f02a6 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -62,7 +62,7 @@ struct Repaint { viewports_frame_nr: HashMap, /// While positive, keep requesting repaints. Decrement at the end of each frame. - repaint_request: HashMap, + repaint_request: HashMap, request_repaint_callback: Option>, requested_repaint_last_frame: HashMap, @@ -74,12 +74,9 @@ impl Repaint { } fn request_repaint_after(&mut self, after: std::time::Duration, viewport_id: ViewportId) { - if after == std::time::Duration::ZERO { - // This will only work if the current viewport is drawing - self.repaint_request.insert(viewport_id, true); - } + let requests = self.repaint_request.entry(viewport_id).or_default(); + *requests = 1.max(*requests); - // This will work always if let Some(callback) = &self.request_repaint_callback { let info = RequestRepaintInfo { after, @@ -92,11 +89,21 @@ impl Repaint { } } + fn request_repaint_settle(&mut self, viewport_id: ViewportId) { + self.repaint_request.insert(viewport_id, 2); + self.request_repaint(viewport_id); + } + fn start_frame(&mut self, viewport_id: ViewportId) { let request = self.repaint_request.entry(viewport_id).or_default(); self.requested_repaint_last_frame - .insert(viewport_id, *request); - *request = false; + .insert(viewport_id, *request > 0); + if *request > 0 { + *request -= 1; + if *request > 0 { + self.request_repaint(viewport_id); + } + } } // returns what is needed to be repainted @@ -122,6 +129,7 @@ impl Repaint { .get(viewport_id) .copied() .unwrap_or_default() + > 0 } } @@ -203,16 +211,16 @@ impl ContextImpl { self.output.entry(self.viewport_id()).or_default(); self.repaint.start_frame(self.viewport_id()); - if let Some(new_pixels_per_point) = self.memory.new_pixels_per_point { + if let Some(new_pixels_per_point) = self.memory.override_pixels_per_point { if self .memory - .new_pixels_per_viewport + .pixels_per_point_viewports .get(&pair) .map_or(true, |pixels| *pixels != new_pixels_per_point) { new_raw_input.pixels_per_point = Some(new_pixels_per_point); self.memory - .new_pixels_per_viewport + .pixels_per_point_viewports .insert(pair.this, new_pixels_per_point); let input = self.input.entry(pair.this).or_default(); @@ -222,6 +230,7 @@ impl ContextImpl { rect.min = (ratio * rect.min.to_vec2()).to_pos2(); rect.max = (ratio * rect.max.to_vec2()).to_pos2(); new_raw_input.screen_rect = Some(rect); + self.repaint.request_repaint_settle(pair.this); } } @@ -1338,8 +1347,13 @@ impl Context { /// For instance, when using `eframe` on web, the browsers native zoom level will always be used. pub fn set_pixels_per_point(&self, pixels_per_point: f32) { if pixels_per_point != self.pixels_per_point() { - self.request_repaint(); - self.memory_mut(|mem| mem.new_pixels_per_point = Some(pixels_per_point)); + self.write(|ctx| { + for viewport in ctx.viewports.values() { + ctx.repaint.request_repaint_settle(viewport.pair.this); + } + ctx.repaint.request_repaint_settle(ViewportId::MAIN); + ctx.memory.override_pixels_per_point = Some(pixels_per_point); + }); } } @@ -1632,7 +1646,7 @@ impl Context { ctx.graphics .retain(|id, _| avalibile_viewports.contains(id)); ctx.memory - .new_pixels_per_viewport + .pixels_per_point_viewports .retain(|id, _| avalibile_viewports.contains(id)); }); } diff --git a/crates/egui/src/memory.rs b/crates/egui/src/memory.rs index de9280c25..63bd1f457 100644 --- a/crates/egui/src/memory.rs +++ b/crates/egui/src/memory.rs @@ -70,10 +70,10 @@ pub struct Memory { // ------------------------------------------ /// new scale that will be applied at the start of the next frame #[cfg_attr(feature = "persistence", serde(skip))] - pub(crate) new_pixels_per_point: Option, + pub(crate) override_pixels_per_point: Option, #[cfg_attr(feature = "persistence", serde(skip))] - pub(crate) new_pixels_per_viewport: HashMap, + pub(crate) pixels_per_point_viewports: HashMap, /// new fonts that will be applied at the start of the next frame #[cfg_attr(feature = "persistence", serde(skip))] diff --git a/examples/viewports/src/main.rs b/examples/viewports/src/main.rs index 4ea2c579a..394ecfebc 100644 --- a/examples/viewports/src/main.rs +++ b/examples/viewports/src/main.rs @@ -347,18 +347,29 @@ fn generic_ui(ui: &mut egui::Ui, container_id: impl Into) { } ui.data_mut(|data| data.insert_temp(container_id.with("show_spinner"), show_spinner)); - let mut pixels_per_point = ctx.pixels_per_point(); - if ui - .add( - egui::DragValue::new(&mut pixels_per_point) - .prefix("Pixels per Point: ") - .speed(0.01) - .clamp_range(0.5..=4.0), - ) - .changed() - { + let tmp_pixels_per_point = ctx.pixels_per_point(); + let mut pixels_per_point = ui.data_mut(|data| { + *data.get_temp_mut_or(container_id.with("pixels_per_point"), tmp_pixels_per_point) + }); + let res = ui.add( + egui::DragValue::new(&mut pixels_per_point) + .prefix("Pixels per Point: ") + .speed(0.1) + .clamp_range(0.5..=4.0), + ); + if res.drag_released() { ctx.set_pixels_per_point(pixels_per_point); } + if res.dragged() { + ui.data_mut(|data| { + data.insert_temp(container_id.with("pixels_per_point"), pixels_per_point); + }); + } else { + ui.data_mut(|data| { + data.insert_temp(container_id.with("pixels_per_point"), tmp_pixels_per_point); + }); + } + egui::gui_zoom::zoom_with_keyboard_shortcuts(&ctx, None); if ctx.viewport_id() != ctx.parent_viewport_id() { let parent = ctx.parent_viewport_id();