Skip to content

Commit

Permalink
Make pivot_pos an option too, for a little bit nicer code
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed Jul 1, 2024
1 parent 7856d4d commit e32c76e
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 29 deletions.
65 changes: 42 additions & 23 deletions crates/egui/src/containers/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::*;
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct AreaState {
/// Last known position of the pivot.
pub pivot_pos: Pos2,
pub pivot_pos: Option<Pos2>,

/// The anchor point of the area, i.e. where on the area the [`Self::pivot_pos`] refers to.
pub pivot: Align2,
Expand All @@ -36,6 +36,18 @@ pub struct AreaState {
pub last_became_visible_at: Option<f64>,
}

impl Default for AreaState {
fn default() -> Self {
Self {
pivot_pos: None,
pivot: Align2::LEFT_TOP,
size: None,
interactable: true,
last_became_visible_at: None,
}
}
}

impl AreaState {
/// Load the state of an [`Area`] from memory.
pub fn load(ctx: &Context, id: Id) -> Option<Self> {
Expand All @@ -45,20 +57,21 @@ impl AreaState {

/// The left top positions of the area.
pub fn left_top_pos(&self) -> Pos2 {
let pivot_pos = self.pivot_pos.unwrap_or_default();
let size = self.size.unwrap_or_default();
pos2(
self.pivot_pos.x - self.pivot.x().to_factor() * size.x,
self.pivot_pos.y - self.pivot.y().to_factor() * size.y,
pivot_pos.x - self.pivot.x().to_factor() * size.x,
pivot_pos.y - self.pivot.y().to_factor() * size.y,
)
}

/// Move the left top positions of the area.
pub fn set_left_top_pos(&mut self, pos: Pos2) {
let size = self.size.unwrap_or_default();
self.pivot_pos = pos2(
self.pivot_pos = Some(pos2(
pos.x + self.pivot.x().to_factor() * size.x,
pos.y + self.pivot.y().to_factor() * size.y,
);
));
}

/// Where the area is on screen.
Expand Down Expand Up @@ -377,28 +390,24 @@ impl Area {

let layer_id = LayerId::new(order, id);

let state = AreaState::load(ctx, id).map(|mut state| {
// override the saved state with the correct value
state.pivot = pivot;
state
});
let state = AreaState::load(ctx, id);
let mut sizing_pass = state.is_none();
let mut state = state.unwrap_or_else(|| AreaState {
pivot_pos: default_pos.unwrap_or_else(|| automatic_area_position(ctx)),
let mut state = state.unwrap_or(AreaState {
pivot_pos: None,
pivot,
size: None,
interactable,
last_became_visible_at: None,
});
state.pivot_pos = new_pos.unwrap_or(state.pivot_pos);
state.pivot = pivot;
state.interactable = interactable;

// TODO(emilk): if last frame was sizing pass, it should be considered invisible for smoother fade-in
let visible_last_frame = ctx.memory(|mem| mem.areas().visible_last_frame(&layer_id));

if !visible_last_frame || state.last_became_visible_at.is_none() {
state.last_became_visible_at = Some(ctx.input(|i| i.time));
if let Some(new_pos) = new_pos {
state.pivot_pos = Some(new_pos);
}
state.pivot_pos.get_or_insert_with(|| {
default_pos.unwrap_or_else(|| automatic_area_position(ctx, layer_id))
});
state.interactable = interactable;

let size = *state.size.get_or_insert_with(|| {
sizing_pass = true;
Expand All @@ -421,6 +430,13 @@ impl Area {
size
});

// TODO(emilk): if last frame was sizing pass, it should be considered invisible for smoother fade-in
let visible_last_frame = ctx.memory(|mem| mem.areas().visible_last_frame(&layer_id));

if !visible_last_frame || state.last_became_visible_at.is_none() {
state.last_became_visible_at = Some(ctx.input(|i| i.time));
}

if let Some((anchor, offset)) = anchor {
state.set_left_top_pos(
anchor
Expand Down Expand Up @@ -453,7 +469,9 @@ impl Area {
});

if movable && move_response.dragged() {
state.pivot_pos += move_response.drag_delta();
if let Some(pivot_pos) = &mut state.pivot_pos {
*pivot_pos += move_response.drag_delta();
}
}

if (move_response.dragged() || move_response.clicked())
Expand Down Expand Up @@ -585,12 +603,13 @@ fn pointer_pressed_on_area(ctx: &Context, layer_id: LayerId) -> bool {
}
}

fn automatic_area_position(ctx: &Context) -> Pos2 {
fn automatic_area_position(ctx: &Context, layer_id: LayerId) -> Pos2 {
let mut existing: Vec<Rect> = ctx.memory(|mem| {
mem.areas()
.visible_windows()
.into_iter()
.map(AreaState::rect)
.filter(|(id, _)| id != &layer_id) // ignore ourselves
.filter(|(_, state)| state.pivot_pos.is_some() && state.size.is_some())
.map(|(_, state)| state.rect())
.collect()
});
existing.sort_by_key(|r| r.left().round() as i32);
Expand Down
4 changes: 2 additions & 2 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ impl ContextImpl {
self.memory.areas_mut().set_state(
LayerId::background(),
AreaState {
pivot_pos: screen_rect.left_top(),
pivot_pos: Some(screen_rect.left_top()),
pivot: Align2::LEFT_TOP,
size: Some(screen_rect.size()),
interactable: true,
Expand Down Expand Up @@ -2209,7 +2209,7 @@ impl Context {
pub fn used_rect(&self) -> Rect {
self.write(|ctx| {
let mut used = ctx.viewport().frame_state.used_by_panels;
for window in ctx.memory.areas().visible_windows() {
for (_id, window) in ctx.memory.areas().visible_windows() {
used = used.union(window.rect());
}
used
Expand Down
8 changes: 4 additions & 4 deletions crates/egui/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1027,12 +1027,12 @@ impl Areas {
.collect()
}

pub(crate) fn visible_windows(&self) -> Vec<&area::AreaState> {
pub(crate) fn visible_windows(&self) -> impl Iterator<Item = (LayerId, &area::AreaState)> {
self.visible_layer_ids()
.iter()
.into_iter()
.filter(|layer| layer.order == crate::Order::Middle)
.filter_map(|layer| self.get(layer.id))
.collect()
.filter(|&layer| !self.is_sublayer(&layer))
.filter_map(|layer| Some((layer, self.get(layer.id)?)))
}

pub fn move_to_top(&mut self, layer_id: LayerId) {
Expand Down

0 comments on commit e32c76e

Please sign in to comment.