|
|
@@ -22,6 +22,7 @@ use darkfi_serial::{
|
|
|
};
|
|
|
use parking_lot::RwLock;
|
|
|
use std::{
|
|
|
+ cell::RefCell,
|
|
|
collections::HashMap,
|
|
|
io::Write,
|
|
|
sync::{
|
|
|
@@ -32,11 +33,14 @@ use std::{
|
|
|
|
|
|
use super::{BufferId, DrawCall, GfxDrawCall, TextureId};
|
|
|
|
|
|
+macro_rules! t { ($($arg:tt)*) => { trace!(target: "gfx::anim", $($arg)*); } }
|
|
|
+
|
|
|
#[derive(Debug, Clone)]
|
|
|
pub struct SeqAnim {
|
|
|
oneshot: bool,
|
|
|
frames: Vec<Option<Frame>>,
|
|
|
recv_frames: async_channel::Receiver<(usize, Frame)>,
|
|
|
+ state: State,
|
|
|
}
|
|
|
|
|
|
impl SeqAnim {
|
|
|
@@ -44,8 +48,9 @@ impl SeqAnim {
|
|
|
oneshot: bool,
|
|
|
frames: Vec<Option<Frame>>,
|
|
|
recv_frames: async_channel::Receiver<(usize, Frame)>,
|
|
|
+ state: State,
|
|
|
) -> Self {
|
|
|
- Self { oneshot, frames, recv_frames }
|
|
|
+ Self { oneshot, frames, recv_frames, state }
|
|
|
}
|
|
|
|
|
|
pub(super) fn compile(
|
|
|
@@ -63,7 +68,7 @@ impl SeqAnim {
|
|
|
let dc = frame.dc.compile(textures, buffers, 0).unwrap();
|
|
|
frames.push(Some(GfxFrame { duration, dc }));
|
|
|
}
|
|
|
- GfxSeqAnim::new(self.oneshot, frames, self.recv_frames)
|
|
|
+ GfxSeqAnim::new(self.oneshot, frames, self.recv_frames, self.state)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -138,15 +143,37 @@ impl AsyncEncodable for Frame {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#[derive(Debug)]
|
|
|
+struct InternalState {
|
|
|
+ /// Timer between frames
|
|
|
+ timer: std::time::Instant,
|
|
|
+ current_idx: usize,
|
|
|
+}
|
|
|
+
|
|
|
+type InternalStatePtr = Arc<RefCell<InternalState>>;
|
|
|
+
|
|
|
+#[derive(Debug, Clone)]
|
|
|
+pub struct State(InternalStatePtr);
|
|
|
+
|
|
|
+impl State {
|
|
|
+ pub fn new() -> Self {
|
|
|
+ Self(Arc::new(RefCell::new(InternalState {
|
|
|
+ timer: std::time::Instant::now(),
|
|
|
+ current_idx: 0,
|
|
|
+ })))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+unsafe impl Send for State {}
|
|
|
+unsafe impl Sync for State {}
|
|
|
+
|
|
|
#[derive(Debug, Clone)]
|
|
|
pub(super) struct GfxSeqAnim {
|
|
|
oneshot: bool,
|
|
|
frames: Vec<Option<GfxFrame>>,
|
|
|
/// Stream frames in
|
|
|
recv_frames: async_channel::Receiver<(usize, Frame)>,
|
|
|
- /// Timer between frames
|
|
|
- timer: std::time::Instant,
|
|
|
- current_idx: usize,
|
|
|
+ state: State,
|
|
|
}
|
|
|
|
|
|
impl GfxSeqAnim {
|
|
|
@@ -154,8 +181,9 @@ impl GfxSeqAnim {
|
|
|
oneshot: bool,
|
|
|
frames: Vec<Option<GfxFrame>>,
|
|
|
recv_frames: async_channel::Receiver<(usize, Frame)>,
|
|
|
+ state: State,
|
|
|
) -> Self {
|
|
|
- Self { oneshot, frames, recv_frames, timer: std::time::Instant::now(), current_idx: 0 }
|
|
|
+ Self { oneshot, frames, recv_frames, state }
|
|
|
}
|
|
|
|
|
|
pub fn tick(
|
|
|
@@ -163,33 +191,42 @@ impl GfxSeqAnim {
|
|
|
textures: &HashMap<TextureId, miniquad::TextureId>,
|
|
|
buffers: &HashMap<BufferId, miniquad::BufferId>,
|
|
|
) -> Option<GfxDrawCall> {
|
|
|
+ t!("tick");
|
|
|
while let Ok((frame_idx, frame)) = self.recv_frames.try_recv() {
|
|
|
let duration = std::time::Duration::from_millis(frame.duration as u64);
|
|
|
let dc = frame.dc.compile(textures, buffers, 0).unwrap();
|
|
|
self.frames[frame_idx] = Some(GfxFrame { duration, dc });
|
|
|
+ t!("got frame {frame_idx}");
|
|
|
+ for i in 0..self.frames.len() {
|
|
|
+ if self.frames[i].is_none() {
|
|
|
+ t!("frame {i} is none");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- let elapsed = self.timer.elapsed();
|
|
|
- assert!(self.current_idx < self.frames.len());
|
|
|
- let frame = &self.frames[self.current_idx];
|
|
|
+ let mut state = self.state.0.borrow_mut();
|
|
|
+
|
|
|
+ let elapsed = state.timer.elapsed();
|
|
|
+ assert!(state.current_idx < self.frames.len());
|
|
|
+ let frame = &self.frames[state.current_idx];
|
|
|
let Some(frame) = frame else {
|
|
|
- assert_eq!(self.current_idx, 0);
|
|
|
+ assert_eq!(state.current_idx, 0);
|
|
|
return None
|
|
|
};
|
|
|
|
|
|
let curr_duration = frame.duration;
|
|
|
if elapsed >= curr_duration {
|
|
|
- let next_idx = (self.current_idx + 1) % self.frames.len();
|
|
|
+ let next_idx = (state.current_idx + 1) % self.frames.len();
|
|
|
// Only advance when the next frame is Some
|
|
|
// Otherwise stay on the same frame
|
|
|
if self.frames[next_idx].is_some() {
|
|
|
- self.current_idx = next_idx;
|
|
|
+ state.current_idx = next_idx;
|
|
|
// Reset the timer now we changed frame
|
|
|
- self.timer = std::time::Instant::now();
|
|
|
+ state.timer = std::time::Instant::now();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- let curr_frame = self.frames[self.current_idx].clone().unwrap();
|
|
|
+ let curr_frame = self.frames[state.current_idx].clone().unwrap();
|
|
|
Some(curr_frame.dc)
|
|
|
}
|
|
|
}
|