Skip to content

Commit

Permalink
Add Renderer::animated method and improve frame rate
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Sep 24, 2023
1 parent c818415 commit 0f0f8a4
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 53 deletions.
63 changes: 17 additions & 46 deletions examples/animation.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,27 @@
use std::time::{Duration, Instant};

use skia_safe::Color4f;
use taffy::{
prelude::Size,
style::{AlignItems, JustifyContent},
};
use viewbuilder::{render::UserEvent, Context, Element, Renderer};
use taffy::prelude::Size;
use viewbuilder::{Context, Element, Renderer};

#[tokio::main]
async fn main() {
// TODO this is really early stage, an animation frame should be requested

let mut tree = Context::default();
let root = Element::new()
.align_items(AlignItems::Center)
.justify_content(JustifyContent::Center)
let mut cx = Context::default();
let animated = Element::new()
.size(Size::from_points(100., 100.))
.background_color(Color4f::new(0., 0., 1., 1.))
.build(&mut tree);

let renderer = Renderer::new();
let tx = renderer.tx.clone();
let notify = renderer.notify.clone();

let mut is_forward = true;
.build(&mut cx);

tokio::spawn(async move {
let mut start = Instant::now();
loop {
let _min = 0.;
let max = 500.;

let elapsed = Instant::now() - start;
let millis = elapsed.as_millis() as f32;
let (begin, end) = if is_forward { (0., max) } else { (max, 0.) };
let interpolated: f32 = interpolation::lerp(&begin, &end, &(millis / 500.));
let size = interpolated.min(max).max(0.);

if elapsed >= Duration::from_secs(1) {
start = Instant::now();
is_forward = !is_forward;
}

tx.send(UserEvent(Box::new(move |tree| {
tree.node(root)
.set_size(Size::from_points(size as f32, size as f32))
})))
.unwrap();
let root = Element::new()
.size(Size::from_points(1000., 200.))
.child(cx.insert("Hello"))
.child(animated)
.child(cx.insert("World"))
.build(&mut cx);

notify.notified().await;
}
});
let renderer = Renderer::new();
tokio::spawn(renderer.animation(animated, 0., 100., move |cx, size| {
cx.node(animated)
.set_size(Size::from_points(size as f32, size as f32))
}));

renderer.run(tree, root)
renderer.run(cx, root)
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//! It supports layout, drawing, and accessability.

pub mod node;

pub use node::Node;

pub mod tree;
Expand Down
41 changes: 39 additions & 2 deletions src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use skia_safe::{

use std::{
ffi::CString,
future::Future,
num::NonZeroU32,
sync::{mpsc, Arc},
time::{Duration, Instant},
Expand Down Expand Up @@ -179,6 +180,43 @@ impl Renderer {
}
}

pub fn animation(
&self,
_key: NodeKey,
min: f32,
max: f32,
f: impl Fn(&mut Context, f32) + Send + Sync + 'static,
) -> impl Future<Output = ()> {
let tx = self.tx.clone();
let notify = self.notify.clone();

let mut is_forward = true;
let mut start = Instant::now();

async move {
let f = Arc::new(f);
loop {
let elapsed = Instant::now() - start;
let millis = elapsed.as_millis() as f32;

let (begin, end) = if is_forward { (min, max) } else { (max, min) };
let interpolated: f32 = interpolation::lerp(&begin, &end, &(millis / max));
let size = interpolated.min(max).max(min);

if elapsed >= Duration::from_secs(1) {
start = Instant::now();
is_forward = !is_forward;
}

let f2 = f.clone();
tx.send(UserEvent(Box::new(move |cx| f2(cx, size))))
.unwrap();

notify.notified().await;
}
}
}

pub fn run(mut self, mut tree: Context, root: NodeKey) {
let mut previous_frame_start = Instant::now();

Expand Down Expand Up @@ -321,9 +359,8 @@ impl Renderer {
Event::UserEvent(UserEvent(update)) => update(&mut tree),
_ => (),
}
let expected_frame_length_seconds = 1.0 / 20.0;
let frame_duration = Duration::from_secs_f32(expected_frame_length_seconds);

let frame_duration = Duration::from_millis(10);
if frame_start - previous_frame_start > frame_duration {
draw_frame = true;
previous_frame_start = frame_start;
Expand Down
10 changes: 5 additions & 5 deletions src/tree/node_ref.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::borrow::Cow;

use crate::{element::ElementData, node::NodeData, Context, Node, NodeKey};
use skia_safe::Color4f;
use std::borrow::Cow;
use taffy::{prelude::Size, style::Dimension};

/// Reference to an element in a tree.
Expand All @@ -13,6 +12,7 @@ pub struct NodeRef<'a> {
}

impl<'a> NodeRef<'a> {
/// Create a new node reference.
pub(crate) fn new(key: NodeKey, tree: &'a mut Context) -> Self {
Self { key, tree }
}
Expand Down Expand Up @@ -42,7 +42,7 @@ impl<'a> NodeRef<'a> {
}
}

/// Update the text of a text node.
/// Update the text of a node.
///
/// ## Panics
/// This function will panic if the current reference is to an element,
Expand All @@ -55,13 +55,13 @@ impl<'a> NodeRef<'a> {
}
}

/// Update the background color.
/// Update the background color of the element.
pub fn set_background_color(&mut self, color: Color4f) {
self.as_mut().background_color = Some(color);
self.tree.inner.changes.push(self.key);
}

/// Update the background color.
/// Update the size of the element.
pub fn set_size(&mut self, size: Size<Dimension>) {
self.as_mut().size = Some(size);
self.tree.inner.changes.push(self.key);
Expand Down

0 comments on commit 0f0f8a4

Please sign in to comment.