Skip to content

Commit

Permalink
Auto-size Scene on what is available
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed Jan 28, 2025
1 parent 1cd5132 commit f101d39
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 28 deletions.
22 changes: 6 additions & 16 deletions crates/egui/src/containers/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
use core::f32;

use emath::{GuiRounding, Pos2};
use emath::{GuiRounding, NumExt as _, Pos2};

use crate::{
emath::TSTransform, load, LayerId, Rangef, Rect, Response, Sense, Ui, UiBuilder, Vec2,
};
use crate::{emath::TSTransform, LayerId, Rangef, Rect, Response, Sense, Ui, UiBuilder, Vec2};

/// Creates a transformation that fits a given scene rectangle into the available screen size.
///
Expand All @@ -24,7 +22,8 @@ pub fn fit_to_rect_in_scene(rect_in_ui: Rect, rect_in_scene: Rect) -> TSTransfor
let scale_y = available_size_in_ui.y / rect_in_scene.height();

// Use the smaller of the two scales to ensure the whole rectangle fits on the screen.
let scale = scale_x.min(scale_y).min(1.0);
const MAX_SCALE: f32 = 1.0;
let scale = f32::min(scale_x, scale_y).at_most(MAX_SCALE);

// Compute the translation to center the bounding rect in the screen.
let center_screen = rect_in_ui.center();
Expand All @@ -40,15 +39,13 @@ pub fn fit_to_rect_in_scene(rect_in_ui: Rect, rect_in_scene: Rect) -> TSTransfor
pub struct Scene {
zoom_range: Rangef,
max_inner_size: Vec2,
fit_rect: Option<Rect>,
}

impl Default for Scene {
fn default() -> Self {
Self {
zoom_range: Rangef::new(f32::EPSILON, 1.0),
max_inner_size: Vec2::splat(1000.0),
fit_rect: None,
}
}
}
Expand Down Expand Up @@ -84,20 +81,13 @@ impl Scene {
.ctx()
.set_sublayer(parent_ui.layer_id(), scene_layer_id);

// let size = parent_ui.available_size_before_wrap(); // TODO: let user control via builder
let size = Vec2::splat(440.0);
let desired_outer_size = parent_ui.available_size_before_wrap();
let (global_view_bounds, _outer_response) =
parent_ui.allocate_exact_size(size, Sense::hover());
parent_ui.allocate_exact_size(desired_outer_size, Sense::hover());

let global_from_parent = TSTransform::from_translation(global_view_bounds.min.to_vec2());
let mut to_global = global_from_parent * *to_parent;

// Optionally change the transformation so that a scene rect is
// contained in the view, potentially with letter boxing.
if let Some(rect_in_scene) = self.fit_rect {
// *to_parent = fit_to_rect_in_scene(global_view_bounds, rect_in_scene);
}

let mut local_ui = parent_ui.new_child(
UiBuilder::new()
.layer_id(scene_layer_id)
Expand Down
29 changes: 17 additions & 12 deletions crates/egui_demo_lib/src/demo/scene.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use egui::emath::TSTransform;
use egui::scene::{fit_to_rect_in_scene, Scene};
use egui::{Pos2, Rect, Sense, UiBuilder, Vec2};
use egui::{Pos2, Rect, Vec2};

use super::widget_gallery;

Expand Down Expand Up @@ -53,26 +53,31 @@ impl crate::View for SceneDemo {
egui::Frame::group(ui.style())
.inner_margin(0.0)
.show(ui, |ui| {
let scene = Scene::new().max_inner_size([500.0, 1000.0]);
let scene = Scene::new().max_inner_size([350.0, 1000.0]);

let mut reset_view = false;
let mut inner_rect = Rect::NAN;
let response = scene.show(ui, &mut self.parent_from_child, |ui| {
reset_view = ui.button("Reset view").clicked();

ui.add_space(16.0);

self.widget_gallery.ui(ui);

// ui.put(
// Rect::from_min_size(Pos2::ZERO, Vec2::splat(64.0)),
// egui::Button::new("Button"),
// );
// ui.put(
// Rect::from_min_size(Pos2::ZERO + 72.0 * Vec2::DOWN, Vec2::new(500.0, 64.0)),
// egui::Label::new(format!("Inner ui min_rect: {:?}", ui.min_rect())),
// );
ui.put(
Rect::from_min_size(Pos2::new(0.0, -64.0), Vec2::new(200.0, 16.0)),
egui::Label::new("You can put a widget anywhere").selectable(false),
);

reset_view = ui.button("Reset view").clicked();
inner_rect = ui.min_rect();
});

if reset_view || response.double_clicked() {
self.parent_from_child = TSTransform::from_scaling(0.5);
// TODO: auto-call this on first frame?
self.parent_from_child = fit_to_rect_in_scene(
Rect::from_min_size(Pos2::ZERO, ui.min_size()),
inner_rect,
);
}
});
}
Expand Down

0 comments on commit f101d39

Please sign in to comment.