Selaa lähdekoodia

app: video/anim preserve state between draw call updates so a screen resize wont restart animations

darkfi 11 kuukautta sitten
vanhempi
sitoutus
38927314f8
2 muutettua tiedostoa jossa 58 lisäystä ja 18 poistoa
  1. 51 14
      bin/app/src/gfx/anim.rs
  2. 7 4
      bin/app/src/ui/video.rs

+ 51 - 14
bin/app/src/gfx/anim.rs

@@ -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)
     }
 }

+ 7 - 4
bin/app/src/ui/video.rs

@@ -30,7 +30,7 @@ use std::{
 
 use crate::{
     gfx::{
-        anim::{Frame, SeqAnim},
+        anim::{Frame, SeqAnim, State as AnimState},
         gfxtag, DrawCall, DrawInstruction, DrawMesh, ManagedTexturePtr, Rectangle, RenderApi,
     },
     mesh::{MeshBuilder, MeshInfo, COLOR_WHITE},
@@ -57,6 +57,7 @@ pub struct Video {
     stop_load: Arc<AtomicBool>,
     dc_key: u64,
 
+    anim_state: AnimState,
     textures_pub: async_broadcast::Sender<(usize, ManagedTexturePtr)>,
     textures_sub: async_broadcast::Receiver<(usize, ManagedTexturePtr)>,
     textures: Arc<SyncMutex<Vec<Option<ManagedTexturePtr>>>>,
@@ -96,6 +97,7 @@ impl Video {
             stop_load: Arc::new(AtomicBool::new(false)),
             dc_key: OsRng.gen(),
 
+            anim_state: AnimState::new(),
             textures_pub,
             textures_sub,
             textures: Arc::new(SyncMutex::new(vec![])),
@@ -171,6 +173,8 @@ impl Video {
                     {
                         let mut textures = textures.lock();
                         // set texture slot
+                        // panic here? hows that possible
+                        // happened on app close
                         textures[frame_idx] = Some(texture.clone());
                         // broadcast
                         textures_pub.try_broadcast((frame_idx, texture)).unwrap();
@@ -316,15 +320,14 @@ impl Video {
             };
             frames.push(Some(Frame::new(40, dc)));
         }
-        let anim = SeqAnim::new(false, frames, recv_frames);
+        let anim = SeqAnim::new(false, frames, recv_frames, self.anim_state.clone());
 
         Some(DrawUpdate {
             key: self.dc_key,
             draw_calls: vec![(
                 self.dc_key,
                 DrawCall::new(
-                    //vec![DrawInstruction::Move(rect.pos()), DrawInstruction::Animation(anim)],
-                    vec![],
+                    vec![DrawInstruction::Move(rect.pos()), DrawInstruction::Animation(anim)],
                     vec![],
                     self.z_index.get(),
                     "vid",