feat(oakplugin): GL render bridge, color picker, push-button action, worker progress, Interact host

- gl_bridge: macOS CGL offscreen context (process-wide singleton,
  serialized GlGuard), real GL output textures/FBOs, glReadPixels
  readback with vertical flip and format conversion; use_opengl now
  really engages for OpenGLRenderSupported plugins (verified with real
  GL rendering: C smoke 11/11, unit tests, GL e2e).
- OfxColor: color params get a swatch button plus a real picker popup
  (RGBA sliders, live preview, hex input, undoable commit) replacing
  the four spinboxes.
- Push buttons route kOfxActionInstanceChanged (UserEdited) per the
  OFX contract; test plugin asserts the callback.
- Worker-side plugin progress flows to the main-process progress
  dialog over the NDJSON control channel, with cancel propagation.
- OFX Interact host: NewInteract/Describe lifecycle, Draw/Pen/Key/Idle
  action surface with proper in-args, DrawSuite v1 host implementation
  sharing the gl_bridge context; interact test plugin verifies the
  event stream and real GL drawing.
This commit is contained in:
2026-08-19 22:14:54 +08:00
parent 29696479b5
commit b4ceaa9cab
28 changed files with 5481 additions and 161 deletions
+11
View File
@@ -39,6 +39,9 @@ use std::sync::{Arc, Mutex, OnceLock};
pub trait UiProgressReporter: Send {
/// 上报进度(0.0..=1.0);false = 取消。
fn update(&mut self, progress: f64) -> bool;
/// progressEnd 通知(默认 no-opapp 可据此关闭进度 UI / 把完成
/// 事件转发过 IPC——worker 侧的进度回传依赖它)。
fn end(&mut self) {}
}
/// 报告器工厂:progressStart 携 (label, message) 调用,现造一个
@@ -160,4 +163,12 @@ impl ProgressReporter {
pub(crate) fn is_cancelled(&self) -> bool {
self.cancelled.load(Ordering::Relaxed)
}
/// progressEnd 钩子:转发给 UI 报告器(无报告器时 no-op)。
pub(crate) fn end_ui(&self) {
let mut slot = self.ui.lock().unwrap_or_else(|e| e.into_inner());
if let Some(ui) = slot.as_mut() {
ui.end();
}
}
}