Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plot auto-bounds API improvement (part 1/2): clean-up #3587

Merged
merged 2 commits into from
Nov 21, 2023
Merged
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
62 changes: 31 additions & 31 deletions crates/egui_plot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ const MIN_LINE_SPACING_IN_POINTS: f64 = 6.0; // TODO(emilk): large enough for a
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone)]
struct PlotMemory {
/// Indicates if the user has modified the bounds, for example by moving or zooming,
/// or if the bounds should be calculated based by included point or auto bounds.
bounds_modified: Vec2b,
/// Indicates if the plot uses automatic bounds. This is disengaged whenever the user modifies
/// the bounds, for example by moving or zooming.
auto_bounds: Vec2b,

hovered_entry: Option<String>,
hidden_items: ahash::HashSet<String>,
Expand Down Expand Up @@ -137,7 +137,7 @@ struct CursorLinkGroups(HashMap<Id, Vec<PlotFrameCursors>>);
#[derive(Clone)]
struct LinkedBounds {
bounds: PlotBounds,
bounds_modified: Vec2b,
auto_bounds: Vec2b,
}

#[derive(Default, Clone)]
Expand Down Expand Up @@ -183,7 +183,7 @@ pub struct Plot {
allow_scroll: bool,
allow_double_click_reset: bool,
allow_boxed_zoom: bool,
auto_bounds: Vec2b,
default_auto_bounds: Vec2b,
min_auto_bounds: PlotBounds,
margin_fraction: Vec2,
boxed_zoom_pointer_button: PointerButton,
Expand Down Expand Up @@ -225,7 +225,7 @@ impl Plot {
allow_scroll: true,
allow_double_click_reset: true,
allow_boxed_zoom: true,
auto_bounds: false.into(),
default_auto_bounds: false.into(),
min_auto_bounds: PlotBounds::NOTHING,
margin_fraction: Vec2::splat(0.05),
boxed_zoom_pointer_button: PointerButton::Secondary,
Expand Down Expand Up @@ -501,14 +501,14 @@ impl Plot {
/// Expand bounds to fit all items across the x axis, including values given by `include_x`.
#[inline]
pub fn auto_bounds_x(mut self) -> Self {
self.auto_bounds.x = true;
self.default_auto_bounds.x = true;
self
}

/// Expand bounds to fit all items across the y axis, including values given by `include_y`.
#[inline]
pub fn auto_bounds_y(mut self) -> Self {
self.auto_bounds.y = true;
self.default_auto_bounds.y = true;
self
}

Expand Down Expand Up @@ -711,8 +711,8 @@ impl Plot {
allow_scroll,
allow_double_click_reset,
allow_boxed_zoom,
boxed_zoom_pointer_button: boxed_zoom_pointer,
auto_bounds,
boxed_zoom_pointer_button,
default_auto_bounds,
min_auto_bounds,
margin_fraction,
width,
Expand Down Expand Up @@ -854,7 +854,7 @@ impl Plot {
PlotMemory::load(ui.ctx(), plot_id)
}
.unwrap_or_else(|| PlotMemory {
bounds_modified: false.into(),
auto_bounds: true.into(),
hovered_entry: None,
hidden_items: Default::default(),
last_plot_transform: PlotTransform::new(
Expand All @@ -867,7 +867,7 @@ impl Plot {
});

let PlotMemory {
mut bounds_modified,
mut auto_bounds,
mut hovered_entry,
mut hidden_items,
last_plot_transform,
Expand Down Expand Up @@ -963,45 +963,45 @@ impl Plot {
if let Some(linked_bounds) = link_groups.0.get(id) {
if axes.x {
bounds.set_x(&linked_bounds.bounds);
bounds_modified.x = linked_bounds.bounds_modified.x;
auto_bounds.x = linked_bounds.auto_bounds.x;
}
if axes.y {
bounds.set_y(&linked_bounds.bounds);
bounds_modified.y = linked_bounds.bounds_modified.y;
auto_bounds.y = linked_bounds.auto_bounds.y;
}
};
});
};

// Allow double clicking to reset to the initial bounds.
// Allow double-clicking to reset to the initial bounds.
if allow_double_click_reset && response.double_clicked() {
bounds_modified = false.into();
auto_bounds = true.into();
}

// Apply bounds modifications.
for modification in bounds_modifications {
match modification {
BoundsModification::Set(new_bounds) => {
bounds = new_bounds;
bounds_modified = true.into();
auto_bounds = false.into();
}
BoundsModification::Translate(delta) => {
bounds.translate(delta);
bounds_modified = true.into();
auto_bounds = false.into();
}
}
}

// Reset bounds to initial bounds if they haven't been modified.
if !bounds_modified.x {
if auto_bounds.x {
bounds.set_x(&min_auto_bounds);
}
if !bounds_modified.y {
if auto_bounds.y {
bounds.set_y(&min_auto_bounds);
}

let auto_x = !bounds_modified.x && (!min_auto_bounds.is_valid_x() || auto_bounds.x);
let auto_y = !bounds_modified.y && (!min_auto_bounds.is_valid_y() || auto_bounds.y);
let auto_x = auto_bounds.x && (!min_auto_bounds.is_valid_x() || default_auto_bounds.x);
let auto_y = auto_bounds.y && (!min_auto_bounds.is_valid_y() || default_auto_bounds.y);

// Set bounds automatically based on content.
if auto_x || auto_y {
Expand Down Expand Up @@ -1031,7 +1031,7 @@ impl Plot {
if let Some((_, linked_axes)) = &linked_axes {
let change_x = linked_axes.y && !linked_axes.x;
transform.set_aspect_by_changing_axis(data_aspect as f64, change_x);
} else if auto_bounds.any() {
} else if default_auto_bounds.any() {
transform.set_aspect_by_expanding(data_aspect as f64);
} else {
transform.set_aspect_by_changing_axis(data_aspect as f64, false);
Expand All @@ -1049,22 +1049,22 @@ impl Plot {
delta.y = 0.0;
}
transform.translate_bounds(delta);
bounds_modified = allow_drag;
auto_bounds = !allow_drag;
}

// Zooming
let mut boxed_zoom_rect = None;
if allow_boxed_zoom {
// Save last click to allow boxed zooming
if response.drag_started() && response.dragged_by(boxed_zoom_pointer) {
if response.drag_started() && response.dragged_by(boxed_zoom_pointer_button) {
// it would be best for egui that input has a memory of the last click pos because it's a common pattern
last_click_pos_for_zoom = response.hover_pos();
}
let box_start_pos = last_click_pos_for_zoom;
let box_end_pos = response.hover_pos();
if let (Some(box_start_pos), Some(box_end_pos)) = (box_start_pos, box_end_pos) {
// while dragging prepare a Shape and draw it later on top of the plot
if response.dragged_by(boxed_zoom_pointer) {
if response.dragged_by(boxed_zoom_pointer_button) {
response = response.on_hover_cursor(CursorIcon::ZoomIn);
let rect = epaint::Rect::from_two_pos(box_start_pos, box_end_pos);
boxed_zoom_rect = Some((
Expand Down Expand Up @@ -1096,7 +1096,7 @@ impl Plot {
};
if new_bounds.is_valid() {
transform.set_bounds(new_bounds);
bounds_modified = true.into();
auto_bounds = false.into();
}
// reset the boxed zoom state
last_click_pos_for_zoom = None;
Expand All @@ -1120,14 +1120,14 @@ impl Plot {
}
if zoom_factor != Vec2::splat(1.0) {
transform.zoom(zoom_factor, hover_pos);
bounds_modified = allow_zoom;
auto_bounds = !allow_zoom;
}
}
if allow_scroll {
let scroll_delta = ui.input(|i| i.scroll_delta);
if scroll_delta != Vec2::ZERO {
transform.translate_bounds(-scroll_delta);
bounds_modified = true.into();
auto_bounds = false.into();
}
}
}
Expand Down Expand Up @@ -1220,14 +1220,14 @@ impl Plot {
*id,
LinkedBounds {
bounds: *transform.bounds(),
bounds_modified,
auto_bounds,
},
);
});
}

let memory = PlotMemory {
bounds_modified,
auto_bounds,
hovered_entry,
hidden_items,
last_plot_transform: transform,
Expand Down
14 changes: 13 additions & 1 deletion crates/emath/src/vec2b.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// Two bools, one for each axis (X and Y).
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Vec2b {
pub x: bool,
Expand Down Expand Up @@ -58,3 +58,15 @@ impl std::ops::IndexMut<usize> for Vec2b {
}
}
}

impl std::ops::Not for Vec2b {
type Output = Self;

#[inline]
fn not(self) -> Self::Output {
Self {
x: !self.x,
y: !self.y,
}
}
}
Loading