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

Improve VisualBounds2D behavior in graph view #8438

Merged
merged 4 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
14 changes: 10 additions & 4 deletions crates/viewer/re_ui/src/zoom_pan_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! * `view`-space: The space where the pan-and-zoom area is drawn.
//! * `scene`-space: The space where the actual content is drawn.
use egui::{emath::TSTransform, Area, Rect, Response, Ui, UiKind};
use egui::{emath::TSTransform, Area, Rect, Response, Ui, UiKind, Vec2};

/// Helper function to handle pan and zoom interactions on a response.
fn register_pan_and_zoom(ui: &Ui, resp: &Response, ui_from_scene: &mut TSTransform) {
Expand All @@ -19,16 +19,22 @@ fn register_pan_and_zoom(ui: &Ui, resp: &Response, ui_from_scene: &mut TSTransfo
let zoom_delta = ui.ctx().input(|i| i.zoom_delta());
let pan_delta = ui.ctx().input(|i| i.smooth_scroll_delta);

// Most of the time we can return early. This is also important to
// avoid `ui_from_scene` to change slightly due to floating point errors.
if zoom_delta == 1.0 && pan_delta == Vec2::ZERO {
return;
}

// Zoom in on pointer, but only if we are not zoomed out too far.
if zoom_delta < 1.0 || ui_from_scene.scaling < 1.0 {
*ui_from_scene = *ui_from_scene
* TSTransform::from_translation(pointer_in_scene.to_vec2())
* TSTransform::from_scaling(zoom_delta)
* TSTransform::from_translation(-pointer_in_scene.to_vec2());
}

// We clamp the resulting scaling to avoid zooming out too far.
ui_from_scene.scaling = ui_from_scene.scaling.min(1.0);
// We clamp the resulting scaling to avoid zooming out too far.
ui_from_scene.scaling = ui_from_scene.scaling.min(1.0);
}

// Pan:
*ui_from_scene = TSTransform::from_translation(pan_delta) * *ui_from_scene;
Expand Down
5 changes: 2 additions & 3 deletions crates/viewer/re_view_graph/src/ui/state.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use egui::{emath::TSTransform, Rect};
use egui::Rect;
use re_format::format_f32;
use re_types::blueprint::components::VisualBounds2D;
use re_ui::UiExt;
Expand All @@ -16,7 +16,6 @@ pub struct GraphViewState {
pub show_debug: bool,

pub visual_bounds: Option<VisualBounds2D>,
pub ui_from_world: Option<TSTransform>,
pub rect_in_ui: Option<Rect>,
}

Expand All @@ -25,7 +24,7 @@ impl GraphViewState {
let Some(rect) = self.layout_state.bounding_rect() else {
return;
};
ui.grid_left_hand_label("Layout")
ui.grid_left_hand_label("Bounding box")
.on_hover_text("The bounding box encompassing all entities in the view right now");
ui.vertical(|ui| {
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend);
Expand Down
19 changes: 5 additions & 14 deletions crates/viewer/re_view_graph/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,22 +183,14 @@ Display a graph of nodes and edges.
let layout = state.layout_state.get(request, params);

// Prepare the view and the transformations.
let prev_rect_in_ui = state.rect_in_ui;
let rect_in_ui = *state.rect_in_ui.insert(ui.max_rect());

let ui_from_world = state
.ui_from_world
.get_or_insert_with(|| fit_to_rect_in_scene(rect_in_ui, rect_in_scene.into()));
let mut ui_from_world = fit_to_rect_in_scene(rect_in_ui, rect_in_scene.into());

// We ensure that the view's center is kept during resizing.
if let Some(prev) = prev_rect_in_ui {
if prev != rect_in_ui {
let delta = rect_in_ui.center() - prev.center();
ui_from_world.translation += delta;
}
}
// We store a copy o the transformation to see if it has changed.
grtlr marked this conversation as resolved.
Show resolved Hide resolved
let ui_from_world_ref = ui_from_world;

let resp = zoom_pan_area(ui, rect_in_ui, ui_from_world, |ui| {
let resp = zoom_pan_area(ui, rect_in_ui, &mut ui_from_world, |ui| {
let mut world_bounding_rect = egui::Rect::NOTHING;

for graph in &graphs {
Expand All @@ -217,8 +209,7 @@ Display a graph of nodes and edges.
blueprint::components::VisualBounds2D::from(ui_from_world.inverse() * rect_in_ui);
if resp.double_clicked() {
bounds_property.reset_blueprint_component::<blueprint::components::VisualBounds2D>(ctx);
state.ui_from_world = None;
} else if rect_in_scene != updated_rect_in_scene {
} else if ui_from_world != ui_from_world_ref {
bounds_property.save_blueprint_component(ctx, &updated_rect_in_scene);
}
// Update stored bounds on the state, so visualizers see an up-to-date value.
Expand Down
Loading