1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-03 07:10:04 -04:00

Now all viewports repaint when pixels_per_point are changed

Added zoom shortcuts for viewports example
This commit is contained in:
Konkitoman
2023-10-20 20:52:34 +03:00
parent 239a807a8f
commit b4224566ed
3 changed files with 51 additions and 26 deletions

View File

@@ -62,7 +62,7 @@ struct Repaint {
viewports_frame_nr: HashMap<ViewportId, u64>, viewports_frame_nr: HashMap<ViewportId, u64>,
/// While positive, keep requesting repaints. Decrement at the end of each frame. /// While positive, keep requesting repaints. Decrement at the end of each frame.
repaint_request: HashMap<ViewportId, bool>, repaint_request: HashMap<ViewportId, u8>,
request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>, request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>,
requested_repaint_last_frame: HashMap<ViewportId, bool>, requested_repaint_last_frame: HashMap<ViewportId, bool>,
@@ -74,12 +74,9 @@ impl Repaint {
} }
fn request_repaint_after(&mut self, after: std::time::Duration, viewport_id: ViewportId) { fn request_repaint_after(&mut self, after: std::time::Duration, viewport_id: ViewportId) {
if after == std::time::Duration::ZERO { let requests = self.repaint_request.entry(viewport_id).or_default();
// This will only work if the current viewport is drawing *requests = 1.max(*requests);
self.repaint_request.insert(viewport_id, true);
}
// This will work always
if let Some(callback) = &self.request_repaint_callback { if let Some(callback) = &self.request_repaint_callback {
let info = RequestRepaintInfo { let info = RequestRepaintInfo {
after, 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) { fn start_frame(&mut self, viewport_id: ViewportId) {
let request = self.repaint_request.entry(viewport_id).or_default(); let request = self.repaint_request.entry(viewport_id).or_default();
self.requested_repaint_last_frame self.requested_repaint_last_frame
.insert(viewport_id, *request); .insert(viewport_id, *request > 0);
*request = false; if *request > 0 {
*request -= 1;
if *request > 0 {
self.request_repaint(viewport_id);
}
}
} }
// returns what is needed to be repainted // returns what is needed to be repainted
@@ -122,6 +129,7 @@ impl Repaint {
.get(viewport_id) .get(viewport_id)
.copied() .copied()
.unwrap_or_default() .unwrap_or_default()
> 0
} }
} }
@@ -203,16 +211,16 @@ impl ContextImpl {
self.output.entry(self.viewport_id()).or_default(); self.output.entry(self.viewport_id()).or_default();
self.repaint.start_frame(self.viewport_id()); 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 if self
.memory .memory
.new_pixels_per_viewport .pixels_per_point_viewports
.get(&pair) .get(&pair)
.map_or(true, |pixels| *pixels != new_pixels_per_point) .map_or(true, |pixels| *pixels != new_pixels_per_point)
{ {
new_raw_input.pixels_per_point = Some(new_pixels_per_point); new_raw_input.pixels_per_point = Some(new_pixels_per_point);
self.memory self.memory
.new_pixels_per_viewport .pixels_per_point_viewports
.insert(pair.this, new_pixels_per_point); .insert(pair.this, new_pixels_per_point);
let input = self.input.entry(pair.this).or_default(); 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.min = (ratio * rect.min.to_vec2()).to_pos2();
rect.max = (ratio * rect.max.to_vec2()).to_pos2(); rect.max = (ratio * rect.max.to_vec2()).to_pos2();
new_raw_input.screen_rect = Some(rect); 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. /// 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) { pub fn set_pixels_per_point(&self, pixels_per_point: f32) {
if pixels_per_point != self.pixels_per_point() { if pixels_per_point != self.pixels_per_point() {
self.request_repaint(); self.write(|ctx| {
self.memory_mut(|mem| mem.new_pixels_per_point = Some(pixels_per_point)); 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 ctx.graphics
.retain(|id, _| avalibile_viewports.contains(id)); .retain(|id, _| avalibile_viewports.contains(id));
ctx.memory ctx.memory
.new_pixels_per_viewport .pixels_per_point_viewports
.retain(|id, _| avalibile_viewports.contains(id)); .retain(|id, _| avalibile_viewports.contains(id));
}); });
} }

View File

@@ -70,10 +70,10 @@ pub struct Memory {
// ------------------------------------------ // ------------------------------------------
/// new scale that will be applied at the start of the next frame /// new scale that will be applied at the start of the next frame
#[cfg_attr(feature = "persistence", serde(skip))] #[cfg_attr(feature = "persistence", serde(skip))]
pub(crate) new_pixels_per_point: Option<f32>, pub(crate) override_pixels_per_point: Option<f32>,
#[cfg_attr(feature = "persistence", serde(skip))] #[cfg_attr(feature = "persistence", serde(skip))]
pub(crate) new_pixels_per_viewport: HashMap<ViewportId, f32>, pub(crate) pixels_per_point_viewports: HashMap<ViewportId, f32>,
/// new fonts that will be applied at the start of the next frame /// new fonts that will be applied at the start of the next frame
#[cfg_attr(feature = "persistence", serde(skip))] #[cfg_attr(feature = "persistence", serde(skip))]

View File

@@ -347,18 +347,29 @@ fn generic_ui(ui: &mut egui::Ui, container_id: impl Into<Id>) {
} }
ui.data_mut(|data| data.insert_temp(container_id.with("show_spinner"), show_spinner)); ui.data_mut(|data| data.insert_temp(container_id.with("show_spinner"), show_spinner));
let mut pixels_per_point = ctx.pixels_per_point(); let tmp_pixels_per_point = ctx.pixels_per_point();
if ui let mut pixels_per_point = ui.data_mut(|data| {
.add( *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) egui::DragValue::new(&mut pixels_per_point)
.prefix("Pixels per Point: ") .prefix("Pixels per Point: ")
.speed(0.01) .speed(0.1)
.clamp_range(0.5..=4.0), .clamp_range(0.5..=4.0),
) );
.changed() if res.drag_released() {
{
ctx.set_pixels_per_point(pixels_per_point); 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() { if ctx.viewport_id() != ctx.parent_viewport_id() {
let parent = ctx.parent_viewport_id(); let parent = ctx.parent_viewport_id();