1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

Shrink the byte-size of Response slightly (#8011)

Small optimization! 96 -> 88 bytes, so no huge win.
This commit is contained in:
Emil Ernerfeldt
2026-03-24 15:46:56 +01:00
committed by GitHub
parent 5ed92c3011
commit a1af9abe70
7 changed files with 57 additions and 23 deletions

View File

@@ -318,8 +318,9 @@ impl<'a> AtomLayout<'a> {
let (_, rect) = ui.allocate_space(frame_size);
let mut response = ui.interact(rect, id, sense);
response.intrinsic_size =
Some((Vec2::new(intrinsic_width, intrinsic_height) + margin.sum()).at_least(min_size));
response.set_intrinsic_size(
(Vec2::new(intrinsic_width, intrinsic_height) + margin.sum()).at_least(min_size),
);
AllocatedAtomLayout {
sized_atoms: sized_items,

View File

@@ -1378,8 +1378,8 @@ impl Context {
interact_rect,
sense,
flags: Flags::empty(),
interact_pointer_pos: None,
intrinsic_size: None,
interact_pointer_pos_or_nan: Pos2::NAN,
intrinsic_size_or_nan: Vec2::NAN,
};
res.flags.set(Flags::ENABLED, enabled);
@@ -1470,14 +1470,11 @@ impl Context {
|| res.long_touched()
|| clicked
|| res.drag_stopped();
if is_interacted_with {
res.interact_pointer_pos = input.pointer.interact_pos();
if let (Some(to_global), Some(pos)) = (
memory.to_global.get(&res.layer_id),
&mut res.interact_pointer_pos,
) {
*pos = to_global.inverse() * *pos;
if is_interacted_with && let Some(mut pos) = input.pointer.interact_pos() {
if let Some(to_global) = memory.to_global.get(&res.layer_id) {
pos = to_global.inverse() * pos;
}
res.interact_pointer_pos_or_nan = pos;
}
if input.pointer.any_down() && !is_interacted_with {

View File

@@ -55,7 +55,7 @@ pub struct Response {
/// Where the pointer (mouse/touch) were when this widget was clicked or dragged.
/// `None` if the widget is not being interacted with.
#[doc(hidden)]
pub interact_pointer_pos: Option<Pos2>,
pub interact_pointer_pos_or_nan: Pos2,
/// The intrinsic / desired size of the widget.
///
@@ -67,12 +67,22 @@ pub struct Response {
/// At the time of writing, this is only used by external crates
/// for improved layouting.
/// See for instance [`egui_flex`](https://github.com/lucasmerlin/hello_egui/tree/main/crates/egui_flex).
pub intrinsic_size: Option<Vec2>,
#[doc(hidden)]
pub intrinsic_size_or_nan: Vec2,
#[doc(hidden)]
pub flags: Flags,
}
#[test]
fn test_response_size() {
assert_eq!(
std::mem::size_of::<Response>(),
88,
"Keep Response small, because we create them often, and we want to keep it lean and fast"
);
}
/// A bit set for various boolean properties of `Response`.
#[doc(hidden)]
#[derive(Copy, Clone, Debug)]
@@ -489,7 +499,26 @@ impl Response {
/// `None` if the widget is not being interacted with.
#[inline]
pub fn interact_pointer_pos(&self) -> Option<Pos2> {
self.interact_pointer_pos
let pos = self.interact_pointer_pos_or_nan;
if pos.any_nan() { None } else { Some(pos) }
}
/// The intrinsic / desired size of the widget.
///
/// This is the size that a non-wrapped, non-truncated, non-justified version of the widget
/// would have.
///
/// If this is `None`, use [`Self::rect`] instead.
#[inline]
pub fn intrinsic_size(&self) -> Option<Vec2> {
let size = self.intrinsic_size_or_nan;
if size.any_nan() { None } else { Some(size) }
}
/// Set the intrinsic / desired size of the widget.
#[inline]
pub fn set_intrinsic_size(&mut self, size: Vec2) {
self.intrinsic_size_or_nan = size;
}
/// If it is a good idea to show a tooltip, where is pointer?
@@ -1007,8 +1036,10 @@ impl Response {
interact_rect: self.interact_rect.union(other.interact_rect),
sense: self.sense.union(other.sense),
flags: self.flags | other.flags,
interact_pointer_pos: self.interact_pointer_pos.or(other.interact_pointer_pos),
intrinsic_size: None,
interact_pointer_pos_or_nan: self
.interact_pointer_pos()
.unwrap_or(other.interact_pointer_pos_or_nan),
intrinsic_size_or_nan: Vec2::NAN,
}
}
}

View File

@@ -1281,7 +1281,7 @@ impl Ui {
pub fn allocate_response(&mut self, desired_size: Vec2, sense: Sense) -> Response {
let (id, rect) = self.allocate_space(desired_size);
let mut response = self.interact(rect, id, sense);
response.intrinsic_size = Some(desired_size);
response.set_intrinsic_size(desired_size);
response
}

View File

@@ -220,7 +220,7 @@ impl Label {
.rect_without_leading_space()
.translate(pos.to_vec2());
let mut response = ui.allocate_rect(rect, sense);
response.intrinsic_size = Some(galley.intrinsic_size());
response.set_intrinsic_size(galley.intrinsic_size());
for placed_row in galley.rows.iter().skip(1) {
let rect = placed_row.rect().translate(pos.to_vec2());
response |= ui.allocate_rect(rect, sense);
@@ -256,7 +256,7 @@ impl Label {
let galley = ui.fonts_mut(|fonts| fonts.layout_job(layout_job));
let (rect, mut response) = ui.allocate_exact_size(galley.size(), sense);
response.intrinsic_size = Some(galley.intrinsic_size());
response.set_intrinsic_size(galley.intrinsic_size());
let galley_pos = match galley.job.halign {
Align::LEFT => rect.left_top(),
Align::Center => rect.center_top(),

View File

@@ -119,6 +119,11 @@ impl Pos2 {
/// Same as `Pos2::default()`.
pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
pub const NAN: Self = Self {
x: f32::NAN,
y: f32::NAN,
};
#[inline(always)]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }

View File

@@ -92,17 +92,17 @@ fn test_intrinsic_size() {
if let Some(current_intrinsic_size) = intrinsic_size {
assert_eq!(
Some(current_intrinsic_size),
response.intrinsic_size,
response.intrinsic_size(),
"For wrapping: {wrapping:?}"
);
}
assert!(
response.intrinsic_size.is_some(),
response.intrinsic_size().is_some(),
"intrinsic_size should be set for `Button`"
);
intrinsic_size = response.intrinsic_size;
intrinsic_size = response.intrinsic_size();
if wrapping == TextWrapMode::Extend {
assert_eq!(Some(response.rect.size()), response.intrinsic_size);
assert_eq!(Some(response.rect.size()), response.intrinsic_size());
}
});
}