From 8fd95153fe4dbf60ee51134329caaec3f794d8d8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 5 May 2020 19:41:49 +0200 Subject: [PATCH] Nice foldable animations --- emigui/src/containers/collapsing_header.rs | 29 +++++++++++----------- emigui/src/region.rs | 8 ++++-- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/emigui/src/containers/collapsing_header.rs b/emigui/src/containers/collapsing_header.rs index 3271a598..77b672e5 100644 --- a/emigui/src/containers/collapsing_header.rs +++ b/emigui/src/containers/collapsing_header.rs @@ -7,6 +7,9 @@ pub(crate) struct State { #[serde(skip)] // Times are relative, and we don't want to continue animations anyway toggle_time: f64, + + /// Height open the region when open. Used for animations + open_height: Option, } impl Default for State { @@ -14,6 +17,7 @@ impl Default for State { Self { open: false, toggle_time: -f64::INFINITY, + open_height: None, } } } @@ -61,7 +65,7 @@ impl CollapsingHeader { Some(id), ); - let state = { + let mut state = { let mut memory = region.memory(); let mut state = memory.collapsing_headers.entry(id).or_insert(State { open: default_open, @@ -95,23 +99,16 @@ impl CollapsingHeader { let animation_time = region.style().animation_time; let time_since_toggle = (region.input().time - state.toggle_time) as f32; + let time_since_toggle = time_since_toggle + region.input().dt; // Instant feedback let animate = time_since_toggle < animation_time; if animate { region.indent(id, |child_region| { let max_height = if state.open { - remap( - time_since_toggle, - 0.0..=animation_time, - // Get instant feedback, and we don't expect to get bigger than this - 100.0..=1500.0, - ) + let full_height = state.open_height.unwrap_or(1000.0); + remap(time_since_toggle, 0.0..=animation_time, 0.0..=full_height) } else { - remap_clamp( - time_since_toggle, - 0.0..=animation_time, - // TODO: state.open_height - 50.0..=0.0, - ) + let full_height = state.open_height.unwrap_or_default(); + remap_clamp(time_since_toggle, 0.0..=animation_time, full_height..=0.0) }; let mut clip_rect = child_region.clip_rect(); @@ -121,15 +118,19 @@ impl CollapsingHeader { let top_left = child_region.top_left(); add_contents(child_region); + state.open_height = Some(child_region.bounding_size().y); + // Pretend children took up less space: let mut child_bounds = child_region.child_bounds(); child_bounds.max.y = child_bounds.max.y.min(top_left.y + max_height); child_region.force_set_child_bounds(child_bounds); }); } else if state.open { - region.indent(id, add_contents); + let full_size = region.indent(id, add_contents).rect.size(); + state.open_height = Some(full_size.y); } + region.memory().collapsing_headers.insert(id, state); region.response(interact) } } diff --git a/emigui/src/region.rs b/emigui/src/region.rs index aef1fb7d..580b482e 100644 --- a/emigui/src/region.rs +++ b/emigui/src/region.rs @@ -513,7 +513,11 @@ impl Region { } /// Create a child region which is indented to the right - pub fn indent(&mut self, id_source: impl Hash, add_contents: impl FnOnce(&mut Region)) { + pub fn indent( + &mut self, + id_source: impl Hash, + add_contents: impl FnOnce(&mut Region), + ) -> InteractInfo { assert!( self.dir == Direction::Vertical, "You can only indent vertical layouts" @@ -538,7 +542,7 @@ impl Region { width: self.style.line_width, }); - self.reserve_space(indent + size, None); + self.reserve_space(indent + size, None) } pub fn left_column(&mut self, width: f32) -> Region {