删掉回放的五个转发、重复的空格快捷键与重复的等待循环。
回放调用点直接走 replay_ctl,场景工具的路径引导收敛到 _paths,panel_snapshot 复用 panel_check 的 _wait_for,report_from 收成模块私有的 _report_from。
This commit is contained in:
@@ -15,6 +15,12 @@ import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# The wait loop lives with the checker; this tool used to carry its own copy.
|
||||
if str(Path(__file__).resolve().parent) not in sys.path:
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
|
||||
from panel_check import _wait_for # noqa: E402
|
||||
|
||||
APP_ROOT = Path(__file__).resolve().parents[1]
|
||||
for path in (APP_ROOT / "src", APP_ROOT.parents[1] / "shared" / "src"):
|
||||
if str(path) not in sys.path:
|
||||
@@ -151,17 +157,5 @@ def _render_every_tab(window, app, args, width: int, height: int) -> int:
|
||||
return 1 if failures else 0
|
||||
|
||||
|
||||
def _wait_for(app, predicate, timeout: float) -> bool:
|
||||
import time
|
||||
|
||||
deadline = time.monotonic() + timeout
|
||||
while time.monotonic() < deadline:
|
||||
app.processEvents()
|
||||
if predicate():
|
||||
return True
|
||||
time.sleep(0.02)
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
重算是否在跑)与 2D 渲染属于窗口级的 `ReplayController`(见
|
||||
`docs/architecture/studio-architecture.md` 建议 1)。
|
||||
- **选视频即选录制**:状态轨的「选择录制视频…」(`toolbar.btn_replay_video`)与
|
||||
「文件 → 打开视频…」都走 `_load_replay_video(path)`——视频所在目录就是录制目录,
|
||||
「文件 → 打开视频…」都走 `ReplayController.load_video(path)`——视频所在目录就是录制目录,
|
||||
于是曲线自动配对同目录的 `forces.csv`。视频与 CSV 仍然同时记录(录制格式不变)。
|
||||
- 曲线:`ForcePlotsPanel.set_recording_source(reader)` 用 `RecordingCurveSource` 直接读
|
||||
录制目录(区间按需读盘 + 缓存包络),所以全程总览、拖动、缩放、框选都在同一套曲线上;
|
||||
@@ -92,7 +92,7 @@
|
||||
- **数值卡读游标处的那一帧**(`ForcePlotsPanel._readout_at_cursor`)。浏览历史或回放时,
|
||||
三个大数字是播放头所指的样本;跟随实时时"最新样本就是游标",不额外读盘。旧写法在回放
|
||||
时显示实时采集的最后一个样本,于是一张 7.5e5 原始计数的曲线旁边写着实时的 `0.0`。
|
||||
- **2D 面板归当前视图的来源所有**(`_replay_owns_image()`):回放视图打开录制后,采集线程
|
||||
- **2D 面板归当前视图的来源所有**(`ReplayController.owns_image()`):回放视图打开录制后,采集线程
|
||||
仍然在跑,但 `_on_run_tick` / `_on_preview_tick` 不再把实时帧画进 2D 面板,
|
||||
`_render_run_image` 直接返回,否则回放画面会被摄像头帧一帧一帧盖掉。切回实时视图才把
|
||||
面板交还给实时帧。
|
||||
|
||||
@@ -65,7 +65,7 @@ class AnalysisReport:
|
||||
)
|
||||
|
||||
|
||||
def report_from(outcome: AnalysisOutcome | None, *, cancelled: bool) -> AnalysisReport:
|
||||
def _report_from(outcome: AnalysisOutcome | None, *, cancelled: bool) -> AnalysisReport:
|
||||
"""Turn a service outcome into the surface's report."""
|
||||
if outcome is None:
|
||||
return AnalysisReport(
|
||||
@@ -178,7 +178,7 @@ class AnalysisWorker(QObject):
|
||||
with self._lock:
|
||||
self._service = None
|
||||
cancelled = self._cancel.is_set()
|
||||
report = report_from(outcome, cancelled=cancelled)
|
||||
report = _report_from(outcome, cancelled=cancelled)
|
||||
if outcome is None and not cancelled:
|
||||
report = AnalysisReport(
|
||||
outcome=None,
|
||||
|
||||
@@ -65,7 +65,7 @@ from orisys_app_shared.scene3d.visual_policy import (
|
||||
policy_for_settings,
|
||||
select_flow_samples,
|
||||
)
|
||||
from orisys_studio.analysis_worker import AnalysisWorker, report_from
|
||||
from orisys_studio.analysis_worker import AnalysisWorker, _report_from
|
||||
from orisys_studio.replay import MODE_ANALYSIS, MODE_RECORDING
|
||||
from orisys_studio.replay_analysis import (
|
||||
AnalysisSession,
|
||||
@@ -1342,7 +1342,7 @@ def test_the_worker_reports_progress_and_a_cancelled_outcome():
|
||||
report = reports[-1][1]
|
||||
assert report.cancelled is True and report.complete is False
|
||||
assert report.frames_written == 2
|
||||
assert report_from(None, cancelled=True).cancelled is True
|
||||
assert _report_from(None, cancelled=True).cancelled is True
|
||||
|
||||
|
||||
# ------------------------------------------------------------------ the depth view
|
||||
|
||||
@@ -1109,7 +1109,7 @@ def test_the_replay_view_shows_the_pane_and_says_where_the_field_comes_from(
|
||||
"""
|
||||
window = _show(make_window(sensor_type="finger"), (1440, 880))
|
||||
try:
|
||||
assert window._load_recording(Path(replay_recording))
|
||||
assert window.replay_ctl.load_recording(Path(replay_recording))
|
||||
assert window._view_preset == "replay"
|
||||
pane = window.mesh3d_panel
|
||||
assert pane.isVisible(), "the 3D pane is hidden in the replay view"
|
||||
|
||||
@@ -2084,9 +2084,9 @@ def main() -> int:
|
||||
app.processEvents()
|
||||
pane_window.brand_bar.btn_playback.click()
|
||||
app.processEvents()
|
||||
check(pane_window._load_recording(recording), "the replay could not open the recording")
|
||||
check(pane_window.replay_ctl.load_recording(recording), "the replay could not open the recording")
|
||||
app.processEvents()
|
||||
check(pane_window._replay_owns_image(), "the replay does not own the 2D pane")
|
||||
check(pane_window.replay_ctl.owns_image(), "the replay does not own the 2D pane")
|
||||
# The recording has no calibrated axis, so newton would be an empty chart.
|
||||
check(
|
||||
pane_window.force_plots.unit() == "raw",
|
||||
@@ -2139,7 +2139,7 @@ def main() -> int:
|
||||
pane_window.brand_bar.btn_live.click()
|
||||
app.processEvents()
|
||||
check(
|
||||
not pane_window._replay_owns_image(),
|
||||
not pane_window.replay_ctl.owns_image(),
|
||||
"the live view still hands the 2D pane to the replay",
|
||||
)
|
||||
pane_window._on_run_tick()
|
||||
@@ -3187,7 +3187,7 @@ def main() -> int:
|
||||
"the replay view still offers the camera picker",
|
||||
)
|
||||
check(
|
||||
replay_window._load_recording(recording),
|
||||
replay_window.replay_ctl.load_recording(recording),
|
||||
"the replay view could not open the recording",
|
||||
)
|
||||
app.processEvents()
|
||||
@@ -3238,7 +3238,7 @@ def main() -> int:
|
||||
_prompt_module.VideoAnalysisDialog.exec = _answer_prompt
|
||||
try:
|
||||
check(
|
||||
other_window._load_replay_video(bare_video) is True,
|
||||
other_window.replay_ctl.load_video(bare_video) is True,
|
||||
"a playable video with no recording beside it was refused",
|
||||
)
|
||||
app.processEvents()
|
||||
@@ -3652,7 +3652,7 @@ def main() -> int:
|
||||
# Leaving the replay view returns the charts to the live session and hides
|
||||
# the bar: the replay stays available, it just stops being on screen.
|
||||
check(
|
||||
replay_window._load_recording(recording),
|
||||
replay_window.replay_ctl.load_recording(recording),
|
||||
"the replay view could not be re-opened",
|
||||
)
|
||||
app.processEvents()
|
||||
|
||||
@@ -91,7 +91,7 @@ def _run_scene(window, app, scene: str):
|
||||
for _ in range(4):
|
||||
app.processEvents()
|
||||
recording = _replay_data(window, app)
|
||||
window._load_recording(recording)
|
||||
window.replay_ctl.load_recording(recording)
|
||||
# Park the playhead where the bar and the charts show a real position.
|
||||
window.replay.set_position(window.replay.duration_s() * 0.4)
|
||||
window.arrow_panel.set_view_mode("recorded")
|
||||
|
||||
Reference in New Issue
Block a user