Skip to content

Commit

Permalink
Layout caching, Lerp underflow fix, label fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ecton committed Nov 14, 2023
1 parent cc7d4ba commit a04619a
Show file tree
Hide file tree
Showing 16 changed files with 439 additions and 183 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/containers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use gooey::Run;

fn main() -> gooey::Result {
let theme_mode = Dynamic::default();
set_of_containers(1, theme_mode.clone())
set_of_containers(3, theme_mode.clone())
.centered()
.into_window()
.with_theme_mode(theme_mode)
Expand Down
25 changes: 15 additions & 10 deletions src/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use std::fmt::{Debug, Display};
use std::ops::{ControlFlow, Deref, Div, Mul};
use std::panic::{RefUnwindSafe, UnwindSafe};
use std::str::FromStr;
use std::sync::{Arc, Condvar, Mutex, MutexGuard, OnceLock, PoisonError};
use std::sync::{Arc, Condvar, Mutex, MutexGuard, OnceLock};
use std::thread;
use std::time::{Duration, Instant};

Expand All @@ -54,7 +54,8 @@ use kludgine::figures::Ranged;
use kludgine::Color;

use crate::animation::easings::Linear;
use crate::styles::Component;
use crate::styles::{Component, RequireInvalidation};
use crate::utils::IgnorePoison;
use crate::value::Dynamic;

static ANIMATIONS: Mutex<Animating> = Mutex::new(Animating::new());
Expand All @@ -65,19 +66,15 @@ fn thread_state() -> MutexGuard<'static, Animating> {
THREAD.get_or_init(|| {
thread::spawn(animation_thread);
});
ANIMATIONS
.lock()
.map_or_else(PoisonError::into_inner, |g| g)
ANIMATIONS.lock().ignore_poison()
}

fn animation_thread() {
let mut state = thread_state();
loop {
if state.running.is_empty() {
state.last_updated = None;
state = NEW_ANIMATIONS
.wait(state)
.map_or_else(PoisonError::into_inner, |g| g);
state = NEW_ANIMATIONS.wait(state).ignore_poison();
} else {
let start = Instant::now();
let last_tick = state.last_updated.unwrap_or(start);
Expand Down Expand Up @@ -641,9 +638,9 @@ macro_rules! impl_lerp_for_uint {
fn lerp(&self, target: &Self, percent: f32) -> Self {
let percent = $float::from(percent);
if let Some(delta) = target.checked_sub(*self) {
*self + (delta as $float * percent).round() as $type
self.saturating_add((delta as $float * percent).round() as $type)
} else {
*self - ((*self - *target) as $float * percent).round() as $type
self.saturating_sub(((*self - *target) as $float * percent).round() as $type)
}
}
}
Expand Down Expand Up @@ -701,8 +698,10 @@ impl PercentBetween for bool {
fn integer_lerps() {
#[track_caller]
fn test_lerps<T: LinearInterpolate + Debug + Eq>(a: &T, b: &T, mid: &T) {
assert_eq!(&b.lerp(a, 1.), a);
assert_eq!(&a.lerp(b, 1.), b);
assert_eq!(&a.lerp(b, 0.), a);
assert_eq!(&b.lerp(a, 0.), b);
assert_eq!(&a.lerp(b, 0.5), mid);
}

Expand Down Expand Up @@ -1012,6 +1011,12 @@ impl TryFrom<Component> for EasingFunction {
}
}

impl RequireInvalidation for EasingFunction {
fn requires_invalidation(&self) -> bool {
false
}
}

/// Performs easing for value interpolation.
pub trait Easing: Debug + Send + Sync + RefUnwindSafe + UnwindSafe + 'static {
/// Eases a value ranging between zero and one. The resulting value does not
Expand Down
68 changes: 59 additions & 9 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! Types that provide access to the Gooey runtime.
use std::borrow::Cow;
use std::hash::Hash;
use std::ops::{Deref, DerefMut};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::sync::{Arc, Mutex, MutexGuard};

use kempt::Set;
use kludgine::app::winit::event::{
DeviceId, Ime, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase,
};
Expand All @@ -15,6 +17,7 @@ use kludgine::{Color, Kludgine};
use crate::graphics::Graphics;
use crate::styles::components::{HighlightColor, WidgetBackground};
use crate::styles::{ComponentDefinition, Styles, Theme, ThemePair, VisualOrder};
use crate::utils::IgnorePoison;
use crate::value::{Dynamic, IntoValue, Value};
use crate::widget::{EventHandling, ManagedWidget, WidgetId, WidgetInstance, WidgetRef};
use crate::window::sealed::WindowCommand;
Expand Down Expand Up @@ -572,14 +575,23 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> LayoutContext<'context, 'window, 'cl
/// context's widget and returns the result.
pub fn layout(&mut self, available_space: Size<ConstraintLimit>) -> Size<UPx> {
if self.persist_layout {
self.graphics.current_node.reset_child_layouts();
if let Some(cached) = self.graphics.current_node.begin_layout(available_space) {
return cached;
}
}
self.graphics
let result = self
.graphics
.current_node
.clone()
.lock()
.as_widget()
.layout(available_space, self)
.layout(available_space, self);
if self.persist_layout {
self.graphics
.current_node
.persist_layout(available_space, result);
}
result
}

/// Sets the layout for `child` to `layout`.
Expand Down Expand Up @@ -664,7 +676,7 @@ impl<'window> AsEventContext<'window> for GraphicsContext<'_, 'window, '_, '_, '
/// specific widget.
pub struct WidgetContext<'context, 'window> {
current_node: ManagedWidget,
redraw_status: &'context RedrawStatus,
redraw_status: &'context InvalidationStatus,
window: &'context mut RunningWindow<'window>,
theme: Cow<'context, ThemePair>,
pending_state: PendingState<'context>,
Expand All @@ -675,7 +687,7 @@ pub struct WidgetContext<'context, 'window> {
impl<'context, 'window> WidgetContext<'context, 'window> {
pub(crate) fn new(
current_node: ManagedWidget,
redraw_status: &'context RedrawStatus,
redraw_status: &'context InvalidationStatus,
theme: &'context ThemePair,
window: &'context mut RunningWindow<'window>,
theme_mode: ThemeMode,
Expand Down Expand Up @@ -755,6 +767,11 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
value.redraw_when_changed(self.handle());
}

/// Ensures that this widget will be redrawn when `value` has been updated.
pub fn invalidate_when_changed<T>(&self, value: &Dynamic<T>) {
value.invalidate_when_changed(self.handle(), self.current_node.id());
}

/// Returns the last layout of this widget.
#[must_use]
pub fn last_layout(&self) -> Option<Rect<Px>> {
Expand Down Expand Up @@ -963,7 +980,24 @@ impl<'context, 'window> WidgetContext<'context, 'window> {

pub(crate) struct WindowHandle {
kludgine: kludgine::app::WindowHandle<WindowCommand>,
redraw_status: RedrawStatus,
redraw_status: InvalidationStatus,
}

impl Eq for WindowHandle {}

impl PartialEq for WindowHandle {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(
&self.redraw_status.invalidated,
&other.redraw_status.invalidated,
)
}
}

impl Hash for WindowHandle {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.redraw_status.invalidated).hash(state);
}
}

impl WindowHandle {
Expand All @@ -972,6 +1006,12 @@ impl WindowHandle {
let _result = self.kludgine.send(WindowCommand::Redraw);
}
}

pub fn invalidate(&self, widget: WidgetId) {
if self.redraw_status.invalidate(widget) {
self.redraw();
}
}
}

impl dyn AsEventContext<'_> {}
Expand Down Expand Up @@ -1036,11 +1076,12 @@ impl DerefMut for PendingState<'_> {
}

#[derive(Default, Clone)]
pub(crate) struct RedrawStatus {
pub(crate) struct InvalidationStatus {
refresh_sent: Arc<AtomicBool>,
invalidated: Arc<Mutex<Set<WidgetId>>>,
}

impl RedrawStatus {
impl InvalidationStatus {
pub fn should_send_refresh(&self) -> bool {
self.refresh_sent
.compare_exchange(false, true, Ordering::Release, Ordering::Acquire)
Expand All @@ -1050,6 +1091,15 @@ impl RedrawStatus {
pub fn refresh_received(&self) {
self.refresh_sent.store(false, Ordering::Release);
}

pub fn invalidate(&self, widget: WidgetId) -> bool {
let mut invalidated = self.invalidated.lock().ignore_poison();
invalidated.insert(widget)
}

pub fn invalidations(&self) -> MutexGuard<'_, Set<WidgetId>> {
self.invalidated.lock().ignore_poison()
}
}

/// A type chat can convert to a [`ManagedWidget`] through a [`WidgetContext`].
Expand Down
Loading

0 comments on commit a04619a

Please sign in to comment.