Files
orisys-app/apps/studio/tests
ykcheungab 0b309e7edf 三维显示骨架:可执行合同 + 模块签名 + 分阶段计划 - What: 按 docs/architecture/studio-3d-design.md 与 studio-3d-contracts.pyi 搭建骨架(阶段 0)。shared/src/orisys_app_shared/scene3d/:contracts.py 把 .pyi 的规格变成可执行代码——全部 DTO/枚举(FrameIdentity/FieldDescriptor/SurfaceFieldFrame/MeshPart/SurfaceBinding/CameraPreset/ExpectedGeometry/SceneAssets/ColorScale/DisplaySettings/VertexFields/RenderFrame/CameraMatrices/GLCapabilities/RenderStats/CompileOptions/CompileReport)、标准诊断码表(DIAGNOSTIC_SEVERITY,含 stale_frame=info、field_unavailable=warning 等)、ThreeDError、freeze()(拥有数据 + C 连续 + 只读)、五个校验器(validate_surface_frame/validate_binding/validate_mesh_part/validate_assets/validate_display_settings/validate_render_frame)、LatestFrameMailbox(容量 1、替换计数、锁内只换引用)、UNAVAILABLE_DESCRIPTOR/rest_descriptor() 与 summarize_parts(),以及全部 Protocol;该模块不 import Qt/OpenGL/SDK。assets.py/sampling.py/composer.py 为签名骨架(未实现处抛 NotImplementedError 并写明归属阶段)。apps/studio/src/orisys_studio/scene3d/:camera/adapters/coordinator/gl_backend/widget/panel 签名骨架,其中 configure_surface_format() 已实现(QApplication 之前调用,desktop33=GL3.3 Core / gles30=GLES3.0,深度 24、无 MSAA);模块级一律不 import GL 绑定,PyOpenGL 只在 GLDispatch.bind_current_context 里加载。tools/scene_assets/{probe_gl,validate_scene,compile_scene}.py 提供入口与参数,未实现时输出 not_implemented 并返回 2(避免被 CI 当成通过)。docs/architecture/studio-3d-stages.md:阶段 0-5 的产出、每阶段的验收矩阵、并行度与回归门。测试:shared/tests/test_scene3d_contracts.py 26 项(freeze 拥有数据、可写/非连续数组被拒、scalar 与 valid 形状一致、位移缺 quality 被拒、非有限 scalar 标为 valid 只报警不静默、绑定越界/-1 约定/权重和为 1、三角形索引越界、感知法线单位长度、恰好一个 sensing part、binding 必须属于 sensing part、设备几何/域/尺寸不符被拒、色标 lower<upper、邮箱替换计数与多线程不阻塞生产者、身份区分 source/generation、骨架可导入且不引入 PyOpenGL);apps/studio/tests/test_scene3d_skeleton.py 4 项(骨架不 import OpenGL、surface format 两个 profile、widget 构造不需要 context、各 stub 报出归属阶段)。 - Why: 用户要求"先从骨架搭起,然后计划功能实现顺序,最后逐阶段实现与验收"。骨架阶段的价值在于把接口变成可执行的(.pyi 本身无法被测试),并把"数组只读、单位与质量必须声明、近似位移不得当毫米、参考帧不得冒充测量、显示丢帧不得计入记录丢帧"这些容易在实现时被绕过的规则先固定下来;同时明确不 import Qt/OpenGL 的边界,使采集线程与 CI 能在无 GPU 环境导入它。 - Verification: shared 全量 187 passed(原 161 + 26);studio 95 passed(原 91 + 4);ui_check 554 项检查 0 失败;compileall 通过;probe_gl --profile desktop33 在未实现时返回 2 并说明将产出什么报告。 - Not in this change: 三维功能本身(阶段 1 起);app_window/main.py 未接线,骨架对现有应用完全惰性(无任何模块被应用导入)。
2026-09-14 14:32:38 +08:00
..
2026-09-12 14:03:00 +08:00
2026-09-13 14:01:24 +08:00
三维显示骨架:可执行合同 + 模块签名 + 分阶段计划 - What: 按 docs/architecture/studio-3d-design.md 与 studio-3d-contracts.pyi 搭建骨架(阶段 0)。shared/src/orisys_app_shared/scene3d/:contracts.py 把 .pyi 的规格变成可执行代码——全部 DTO/枚举(FrameIdentity/FieldDescriptor/SurfaceFieldFrame/MeshPart/SurfaceBinding/CameraPreset/ExpectedGeometry/SceneAssets/ColorScale/DisplaySettings/VertexFields/RenderFrame/CameraMatrices/GLCapabilities/RenderStats/CompileOptions/CompileReport)、标准诊断码表(DIAGNOSTIC_SEVERITY,含 stale_frame=info、field_unavailable=warning 等)、ThreeDError、freeze()(拥有数据 + C 连续 + 只读)、五个校验器(validate_surface_frame/validate_binding/validate_mesh_part/validate_assets/validate_display_settings/validate_render_frame)、LatestFrameMailbox(容量 1、替换计数、锁内只换引用)、UNAVAILABLE_DESCRIPTOR/rest_descriptor() 与 summarize_parts(),以及全部 Protocol;该模块不 import Qt/OpenGL/SDK。assets.py/sampling.py/composer.py 为签名骨架(未实现处抛 NotImplementedError 并写明归属阶段)。apps/studio/src/orisys_studio/scene3d/:camera/adapters/coordinator/gl_backend/widget/panel 签名骨架,其中 configure_surface_format() 已实现(QApplication 之前调用,desktop33=GL3.3 Core / gles30=GLES3.0,深度 24、无 MSAA);模块级一律不 import GL 绑定,PyOpenGL 只在 GLDispatch.bind_current_context 里加载。tools/scene_assets/{probe_gl,validate_scene,compile_scene}.py 提供入口与参数,未实现时输出 not_implemented 并返回 2(避免被 CI 当成通过)。docs/architecture/studio-3d-stages.md:阶段 0-5 的产出、每阶段的验收矩阵、并行度与回归门。测试:shared/tests/test_scene3d_contracts.py 26 项(freeze 拥有数据、可写/非连续数组被拒、scalar 与 valid 形状一致、位移缺 quality 被拒、非有限 scalar 标为 valid 只报警不静默、绑定越界/-1 约定/权重和为 1、三角形索引越界、感知法线单位长度、恰好一个 sensing part、binding 必须属于 sensing part、设备几何/域/尺寸不符被拒、色标 lower<upper、邮箱替换计数与多线程不阻塞生产者、身份区分 source/generation、骨架可导入且不引入 PyOpenGL);apps/studio/tests/test_scene3d_skeleton.py 4 项(骨架不 import OpenGL、surface format 两个 profile、widget 构造不需要 context、各 stub 报出归属阶段)。 - Why: 用户要求"先从骨架搭起,然后计划功能实现顺序,最后逐阶段实现与验收"。骨架阶段的价值在于把接口变成可执行的(.pyi 本身无法被测试),并把"数组只读、单位与质量必须声明、近似位移不得当毫米、参考帧不得冒充测量、显示丢帧不得计入记录丢帧"这些容易在实现时被绕过的规则先固定下来;同时明确不 import Qt/OpenGL 的边界,使采集线程与 CI 能在无 GPU 环境导入它。 - Verification: shared 全量 187 passed(原 161 + 26);studio 95 passed(原 91 + 4);ui_check 554 项检查 0 失败;compileall 通过;probe_gl --profile desktop33 在未实现时返回 2 并说明将产出什么报告。 - Not in this change: 三维功能本身(阶段 1 起);app_window/main.py 未接线,骨架对现有应用完全惰性(无任何模块被应用导入)。
2026-09-14 14:32:38 +08:00
按"硬件问题、配置不变"收尾:记录里写下实测帧率,探针加逐颗验收模式 - What: worker 把本会话实测到的采集速率记进 self._measured_capture_fps(box 与 finger 两条循环都算:finger 的帧率也从"1 秒窗口内计数"改成 (n-1)/span 的速率,两条视图对 fps 的含义必须一致),capture_status() 因此多出 measured_fps —— session.json 的 capture 块现在同时有 requested / negotiated / measured_fps / dropped_frames,一颗摄像头到底交付了多少 fps 由记录自证。status.capture_slow 的中英文案改写:删掉已被实测否证的"降低分辨率/换格式"建议,改成"这是采集端(摄像头/驱动)的问题、软件改不了,换一颗真能交付 30 fps 的(并先确认线材/端口没把它降速)再测"。tools/camera_probe.py 新增 --check 验收模式:只测 bundle 用的那一个格式(MJPG 1920x1080@30,120 帧),按**实测**速率打印一行 PASS/FAIL 并给出退出码,用于逐颗过检;无摄像头时报 "No camera answered on index N (is the app closed?)" 并返回 1。tests:假设备用上 capture_status() 的 measured_fps(0.05 s 粒度等它出现,断言 20–35 fps)、探针 --check 的无摄像头路径。 - Why: 用户判定这是驱动/硬件问题(同型号产品此前能跑 30 fps),决定**配置不变**、以后用能到 30 fps 的产品,并在之后逐颗检测。配置不变意味着应用继续按 30 fps 申请(这是对的:申请 15 只会把问题上移),但由此产生两件必须收尾的事:(1) 提示语里"降低分辨率/换格式"是错的建议——探针已经证明 720p MJPG 一样是 15 fps、YUYV 只有 1 fps;(2) 既然要逐颗检测,就必须有一个能回答"这一颗交付了多少"的权威数字,而驱动自报值不可信(DSHOW 回读),所以把实测值写进记录并给探针一个单行验收模式。 - Verification: shared 全量 161 passed;studio 91 passed;ui_check 554 项检查 0 失败;locale_check 中英键集一致;探针 --check 在无摄像头时打印指定文案并返回 1,--help 列出该选项。 - Not in this change: 未改任何采集配置(resolution_raw/fps/fourcc 都不动);未做自动降级;frames.csv 仍未记录 process_ms/capture_fps(留到加未滤波 17 列、记录格式升版时一起)。
2026-09-14 13:48:08 +08:00