fix(sim3d): re-derive slider position when the playback range shrinks - #392
Open
knipknap wants to merge 2 commits into
Open
fix(sim3d): re-derive slider position when the playback range shrinks#392knipknap wants to merge 2 commits into
knipknap wants to merge 2 commits into
Conversation
The playback slider could stay pinned at 100% while the 3D view showed a fresh, barely-started playhead (issue #370 follow-up). Gtk.Range.set_range() clamps the stored value into the new range, so whenever a regenerated job produced a smaller G-code extent, the slider from the previous (larger or further-advanced) job was clamped to the new upper bound: 100%. The re-sync in _refresh_slider_range() relied on _set_slider_for_op(), which silently no-ops exactly in the cases where it was needed: a fresh player sits on the first LAYER_START (a command with no G-code output, span count 0), and a playhead from the old job can be out of range in the new map (IndexError). The bogus 100% therefore persisted while the toolpath reveal was reset to the beginning. - _refresh_slider_range() now re-derives the slider value from the playhead after every range change, falling back to the start of the job for a pristine playhead or an output-less command. - Clearing the player (set_player(None)) now pins the disabled slider explicitly at 0 instead of letting the stale value clamp to 1 of [0, 1] - which renders as 100%. Regression tests reproduce all three paths on the old code: map shrink with an out-of-range playhead, map shrink with an output-less current command, and player cleared with a stale map. Fixes #370
In case the slider fix does not resolve the reported issue, add debug-level diagnostics that make a failing session visible in the log without flooding it: - player and op map swaps (set/cleared, with command and line counts) - a mismatched pair is the prime suspect for desync; - the range-shrink correction itself, logging the clamped value, the new extent, and the re-derived position; - playback start (sim time, total, extent, speed) and every stop with an explicit reason (finished, user pause, canvas unrealized, player lost, destroy) plus wall-clock duration; - a one-shot warning when the playhead target regresses during forward playback; - a heartbeat every ~5 s of playback with sim time, target, slider value, and speed (~0.2 lines/s, DEBUG only). All events are rare or strictly rate-limited; nothing logs per tick.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #370
Problem
Follow-up report from the issue: the 3D playback slider sits all the way to the right at 100% while the toolpath reveal is still at the beginning of the job ("not all ops are drawn yet").
Root cause
Not a time-model or stall problem: reconstructing the reported job from the debug archive and driving the actual pipeline headlessly shows the playhead, laser interpolation, vertex reveal, and op map are all correctly aligned and advance smoothly.
The defect is slider bookkeeping in
PlaybackOverlayacross job regenerations:set_op_map()/set_player()). When a job regenerates (any edit; the reported session shows the job shrinking repeatedly, e.g. 332 -> 318 -> 190 commands), the new extent is often smaller than the current slider value.Gtk.Range.set_range()clamps the stored value into the new range, silently pinning the slider at the new upper bound - visually exactly 100%._refresh_slider_range()(_set_slider_for_op(current_index)) silently no-ops exactly when it is needed: a freshly built player sits on the firstLAYER_START(a command with no G-code output,span_for_op()count 0 ->None), and a playhead carried over from the old job can be out of range in the new map (IndexError). The bogus 100% therefore persists while the reveal is reset to the beginning.set_player(None)): the range shrinks to[0, 1], any prior value clamps to 1 = 100%, and the subsequent_set_slider_for_op(0)computes value 2, which clamps right back to 1.Changes
_refresh_slider_range()re-derives the slider value from the playhead after every range change, falling back to the start of the job for a pristine playhead or an output-less command.update_ops_range()pins the disabled slider (no player) explicitly at 0 instead of letting the stale value clamp to 1 of[0, 1].Bounded debug diagnostics for the case where this does not resolve the users issue (second commit):
finished,user-pause,canvas-unrealized,player-lost,destroy) plus wall-clock duration;All events are rare or strictly rate-limited; nothing logs per tick.
Testing
tests/ui_gtk/sim3d/test_playback_overlay.py, all failing on the old code (one reproducesvalue == 1on range[0, 1], i.e. the reported 100% slider) and passing with the fix: