Skip to content

Commit

Permalink
[awm2] Initial animations support
Browse files Browse the repository at this point in the history
  • Loading branch information
codyd51 committed Dec 20, 2022
1 parent 5cc6bfc commit 792994b
Show file tree
Hide file tree
Showing 5 changed files with 308 additions and 96 deletions.
141 changes: 141 additions & 0 deletions rust_programs/awm2/src/animations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use crate::println;
use crate::utils::get_timestamp;
use crate::window::Window;
use agx_definitions::{Point, Rect, Size};
use alloc::rc::Rc;
use alloc::vec;
use alloc::vec::Vec;
use num_traits::One;

fn lerp(a: f64, b: f64, percent: f64) -> f64 {
a + (percent * (b - a))
}

fn interpolate_window_frame(from: Rect, to: Rect, percent: f64) -> Rect {
/*
// Don't let the window get too small
// TODO(PT): Pull this out into a MIN_WINDOW_SIZE?
let to = Size::new(
isize::max(to.size.width, 1),
isize::max(to.size.height, (Window::TITLE_BAR_HEIGHT as isize) + 1)
);
*/
Rect::from_parts(
Point::new(
lerp(from.min_x() as f64, to.min_x() as f64, percent) as isize,
lerp(from.min_y() as f64, to.min_y() as f64, percent) as isize,
),
Size::new(
lerp(from.width() as f64, to.width() as f64, percent) as isize,
lerp(from.height() as f64, to.height() as f64, percent) as isize,
),
)
}

/*
}
*/

pub struct WindowOpenAnimationParams {
start_time: usize,
end_time: usize,
pub window: Rc<Window>,
pub duration_ms: usize,
pub frame_from: Rect,
pub frame_to: Rect,
}

impl WindowOpenAnimationParams {
pub fn new(
desktop_size: Size,
window: &Rc<Window>,
duration_ms: usize,
frame_to: Rect,
) -> Self {
let from_size = Size::new(desktop_size.width / 10, desktop_size.height / 10);
let frame_from = Rect::from_parts(
Point::new(
((desktop_size.width as f64 / 2.0) - (from_size.width as f64 / 2.0)) as isize,
desktop_size.height - from_size.height,
),
from_size,
);
let start_time = get_timestamp() as usize;
Self {
start_time,
end_time: start_time + duration_ms,
window: Rc::clone(window),
duration_ms,
frame_from,
frame_to,
}
}
}

pub struct AnimationDamage {
pub area_to_recompute_drawable_regions: Rect,
pub rects_needing_composite: Vec<Rect>,
}

impl AnimationDamage {
pub fn new(
area_to_recompute_drawable_regions: Rect,
rects_needing_composite: Vec<Rect>,
) -> Self {
Self {
area_to_recompute_drawable_regions,
rects_needing_composite,
}
}
}

pub enum Animation {
WindowOpen(WindowOpenAnimationParams),
//WindowClose(Rc<Window>),
}

impl Animation {
pub fn start(&self) {
match self {
Animation::WindowOpen(params) => {
*params.window.frame.borrow_mut() = params.frame_from;
}
}
}

pub fn step(&self, now: u64) -> AnimationDamage {
match self {
Animation::WindowOpen(params) => {
let update_region = {
let mut window_frame = params.window.frame.borrow_mut();
let old_frame = *window_frame;
let elapsed = now - (params.start_time as u64);
let percent = f64::min(1.0, elapsed as f64 / params.duration_ms as f64);
println!("Window open animation step {percent:.2}%");
let new_frame =
interpolate_window_frame(params.frame_from, params.frame_to, percent);
*window_frame = new_frame;
old_frame.union(new_frame)
};
params.window.redraw_title_bar();
AnimationDamage::new(update_region, vec![update_region])

//_window_resize(window, window->frame.size, should_inform_window_of_new_size);
/*
Rect total_update_frame = rect_union(current_frame, new_frame);
// Only queueing redraws for the difference between the frames is more efficient,
// but can cause artifacts where on some frames a few window pixels aren't cleaned up.
compositor_queue_rect_to_redraw(total_update_frame);
windows_invalidate_drawable_regions_in_rect(total_update_frame);
AnimationDamage::new(update_region, vec![update_region])
*/
}
}
}

pub fn is_complete(&self, now: u64) -> bool {
match self {
Animation::WindowOpen(params) => now as usize >= params.end_time,
}
}
}
51 changes: 50 additions & 1 deletion rust_programs/awm2/src/desktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use core::cmp::{max, min};
use core::fmt::{Display, Formatter};
use mouse_driver_messages::MousePacket;

use crate::animations::{Animation, WindowOpenAnimationParams};
use file_manager_messages::str_from_u8_nul_utf8_unchecked;
use kb_driver_messages::{KeyEventType, KeyboardPacket};
use lazy_static::lazy_static;
Expand Down Expand Up @@ -396,6 +397,7 @@ pub struct Desktop {
next_desktop_element_id: usize,
windows_to_render_remote_layers_this_cycle: Vec<Rc<Window>>,
frame_render_logs: Vec<String>,
ongoing_animations: Vec<Animation>,
}

impl Desktop {
Expand Down Expand Up @@ -427,6 +429,7 @@ impl Desktop {
next_desktop_element_id: 0,
windows_to_render_remote_layers_this_cycle: vec![],
frame_render_logs: vec![],
ongoing_animations: vec![],
}
}

Expand Down Expand Up @@ -704,13 +707,15 @@ impl Desktop {

Self::copy_rect(buffer, vmem, mouse_rect);

/*
let end = get_timestamp();
logs.push(format!("Finished frame in {}ms", end - start));
if end - start >= 10 {
for l in logs.into_iter() {
println!("\t{l}");
}
}
*/
}

fn copy_rect(src: &mut dyn LikeLayerSlice, dst: &mut dyn LikeLayerSlice, rect: Rect) {
Expand Down Expand Up @@ -842,7 +847,13 @@ impl Desktop {
self.windows.insert(0, Rc::clone(&new_window));
self.compositor_state
.track_element(Rc::clone(&new_window) as Rc<dyn DesktopElement>);
self.recompute_drawable_regions_in_rect(window_frame);
//self.recompute_drawable_regions_in_rect(window_frame);
self.start_animation(Animation::WindowOpen(WindowOpenAnimationParams::new(
desktop_size,
&new_window,
200,
window_frame,
)));

// TODO(PT): Testing
/*
Expand All @@ -854,6 +865,40 @@ impl Desktop {
new_window
}

fn start_animation(&mut self, animation: Animation) {
animation.start();
self.ongoing_animations.push(animation);
}

pub fn step_animations(&mut self) {
// Don't bother fetching a timestamp (which is a syscall) if not necessary
if self.ongoing_animations.len() == 0 {
return;
}

let now = get_timestamp();
let mut rects_to_recompute_drawable_regions = vec![];
for animation in self.ongoing_animations.iter() {
let animation_damage = animation.step(now);
for damaged_rect in animation_damage.rects_needing_composite.iter() {
self.compositor_state.queue_full_redraw(*damaged_rect);
}
rects_to_recompute_drawable_regions
.push(animation_damage.area_to_recompute_drawable_regions);
/*
match animation {
Animation::WindowOpen(params) => params.window.redraw_title_bar(),
};
*/
}
for r in rects_to_recompute_drawable_regions.drain(..) {
self.recompute_drawable_regions_in_rect(r);
}
// Drop animations that are now complete
self.ongoing_animations
.retain(|anim| !anim.is_complete(now));
}

fn window_containing_point(&self, p: Point) -> Option<Rc<Window>> {
// Iterate from the topmost window to further back ones,
// so if windows are overlapping the topmost window will receive it
Expand Down Expand Up @@ -1281,6 +1326,10 @@ impl Desktop {
slice.fill(random_color());
}
}

pub fn has_ongoing_animations(&self) -> bool {
self.ongoing_animations.len() > 0
}
}

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions rust_programs/awm2/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#![feature(btree_drain_filter)]
#![cfg_attr(target_os = "axle", no_std)]
#![cfg_attr(target_os = "axle", feature(start))]
#![cfg_attr(target_os = "axle", feature(format_args_nl))]
#![cfg_attr(target_os = "axle", feature(default_alloc_error_handler))]
// PT: For the test suite
#![cfg_attr(not(target_os = "axle"), feature(iter_zip))]

mod animations;
mod desktop;
mod effects;
mod utils;
Expand Down
Loading

0 comments on commit 792994b

Please sign in to comment.