git.lucas.co / cce-designer
graphic design tool
git clone https://git.lucas.co/cce-designer.git

commit8630dd5fe8aa14b853616ee8cceaa2855dd8f662
parent2d8237dc78
authorLucas Galante <[email protected]>
date2026-08-26 15:10
fix: a transport press while playing always pauses

Redirect-without-stopping is gone: Up or Down during playback pauses in
place, and direction only chooses what starts from a stop.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/app.rs  | 23 +++++++----------------
 src/main.rs | 19 ++++++++++---------
 2 files changed, 17 insertions(+), 25 deletions(-)

diff --git a/src/app.rs b/src/app.rs
index 5ef009d..5f71c6e 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -4244,26 +4244,17 @@ pub(crate) fn geometry_to_spreadsheet_data(geom: &Geometry) -> (Vec<String>, Vec
                 );
                 self.sync_pane_focus();
             }
-            // The two play toggles are per-direction: a press in the OTHER
-            // direction while playing redirects instead of pausing (Up while
-            // reverse-playing plays forward, and vice versa) — matching the
-            // usual up/down transport feel.
-            Action::PlayPause => {
+            // Either play toggle PAUSES while anything is playing — direction
+            // only chooses what starts from a stop. (Redirect-without-stopping
+            // was tried and rejected: a moving timeline should always stop on
+            // the first transport press.)
+            Action::PlayPause | Action::PlayPauseReverse => {
                 let pb = self.slots.playbar.inner_mut();
-                if pb.playing && !pb.reversed {
+                if pb.playing {
                     pb.playing = false;
                 } else {
                     pb.playing = true;
-                    pb.reversed = false;
-                }
-            }
-            Action::PlayPauseReverse => {
-                let pb = self.slots.playbar.inner_mut();
-                if pb.playing && pb.reversed {
-                    pb.playing = false;
-                } else {
-                    pb.playing = true;
-                    pb.reversed = true;
+                    pb.reversed = action == Action::PlayPauseReverse;
                 }
             }
             // Whole-frame stepping off the ROUNDED current frame: during
diff --git a/src/main.rs b/src/main.rs
index c1be6ba..a4f2656 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -656,9 +656,9 @@ mod tests {
         assert_eq!(m.match_action(&plain, &Key::Named(NamedKey::ArrowDown)), Some(Action::PlayPauseReverse));
     }
 
-    /// The two play toggles are per-direction: same-direction press pauses,
-    /// other-direction press redirects without stopping — and the reverse
-    /// tick runs the frame counter down, wrapping start→end.
+    /// Either play toggle pauses a moving timeline; direction only chooses
+    /// what starts from a stop — and the reverse tick runs the frame counter
+    /// down, wrapping start→end.
     #[test]
     fn test_reverse_playback_semantics_and_wrap() {
         let mut state = State::new(false);
@@ -669,17 +669,18 @@ mod tests {
             assert!(pb.playing && pb.reversed, "Down from stopped plays in reverse");
         }
         state.execute_action(Action::PlayPause);
+        assert!(!state.slots.playbar.inner().playing, "Up while reverse-playing pauses");
+        state.execute_action(Action::PlayPause);
         {
             let pb = state.slots.playbar.inner();
-            assert!(pb.playing && !pb.reversed, "Up while reversed redirects forward, not pause");
+            assert!(pb.playing && !pb.reversed, "Up from stopped plays forward");
         }
         state.execute_action(Action::PlayPauseReverse);
-        {
-            let pb = state.slots.playbar.inner();
-            assert!(pb.playing && pb.reversed, "Down while forward redirects to reverse");
-        }
+        assert!(!state.slots.playbar.inner().playing, "Down while forward-playing pauses");
+        state.execute_action(Action::PlayPauseReverse);
+        assert!(state.slots.playbar.inner().reversed, "Down from stopped is reverse again");
         state.execute_action(Action::PlayPauseReverse);
-        assert!(!state.slots.playbar.inner().playing, "Down while reversed pauses");
+        assert!(!state.slots.playbar.inner().playing, "same-direction press pauses");
 
         {
             let pb = state.slots.playbar.inner_mut();