mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 21:48:20 -06:00
Merge pull request #2517 from MatejKozlovsky/crypto-pick-probe
Cryptomatte pick: keep a hover probe, built off the UI thread (#473)
This commit is contained in:
@@ -91,6 +91,8 @@ impl Session {
|
||||
|
||||
pub fn bump(&mut self) {
|
||||
self.revision += 1;
|
||||
// A Cryptomatte probe is keyed by the revision: an older one never answers again.
|
||||
self.drop_crypto_probe();
|
||||
// Back at the saved state (undo, redo, a history jump or a rolled-back batch).
|
||||
if Arc::ptr_eq(&self.project, &self.saved_project) {
|
||||
self.saved_revision = self.revision;
|
||||
@@ -166,12 +168,14 @@ impl Session {
|
||||
pub fn undo(&mut self) -> bool {
|
||||
let Some((label, p)) = self.history.undo.pop() else { return false };
|
||||
let edited = commands::text_edit::active_editor_snapshot(self);
|
||||
let probe = commands::kept_crypto_probe(self);
|
||||
let cur = std::mem::replace(&mut self.project, p);
|
||||
self.keep_view_settings(&cur);
|
||||
self.history.redo.push((label, cur));
|
||||
self.history.merge_key = None;
|
||||
self.sanitize_after_replacement(edited.as_ref());
|
||||
self.bump();
|
||||
commands::keep_crypto_probe(self, probe, &cur);
|
||||
self.history.redo.push((label, cur));
|
||||
true
|
||||
}
|
||||
|
||||
@@ -182,12 +186,14 @@ impl Session {
|
||||
pub fn redo(&mut self) -> bool {
|
||||
let Some((label, p)) = self.history.redo.pop() else { return false };
|
||||
let edited = commands::text_edit::active_editor_snapshot(self);
|
||||
let probe = commands::kept_crypto_probe(self);
|
||||
let cur = std::mem::replace(&mut self.project, p);
|
||||
self.keep_view_settings(&cur);
|
||||
self.history.undo.push((label, cur));
|
||||
self.history.merge_key = None;
|
||||
self.sanitize_after_replacement(edited.as_ref());
|
||||
self.bump();
|
||||
commands::keep_crypto_probe(self, probe, &cur);
|
||||
self.history.undo.push((label, cur));
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{EngineError, Image, ItemId, RenderOpts, Renderer, Result, Session, ThumbnailJob, Tick};
|
||||
use super::{EngineError, Image, ItemId, RenderOpts, Renderer, Result, Session, ThumbnailJob, Tick, Value, commands};
|
||||
|
||||
impl Session {
|
||||
/// Render a comp frame with the session's footage + expression hosts.
|
||||
@@ -9,14 +9,54 @@ impl Session {
|
||||
/// The renderer [`Session::render`] uses: the session's footage, expressions, layer cache and
|
||||
/// accelerator, and the render prefs (nested switches, draft shadows) over `opts`.
|
||||
pub fn renderer(&self, opts: RenderOpts) -> Renderer<'_> {
|
||||
let opts = RenderOpts { nested_switches: self.prefs.general.switches_affect_nested_comps, draft_shadows: self.prefs.three_d.realtime_shadows, ..opts };
|
||||
let mut r = Renderer::new(&self.project, self.footage.as_ref(), opts);
|
||||
let mut r = Renderer::new(&self.project, self.footage.as_ref(), self.render_opts(opts));
|
||||
r.expr = self.expr.as_deref();
|
||||
r.cache = Some(&self.layer_cache);
|
||||
r.accel = self.accel.as_deref();
|
||||
r
|
||||
}
|
||||
|
||||
/// `opts` with the render prefs (nested switches, draft shadows), as [`Session::renderer`].
|
||||
pub fn render_opts(&self, opts: RenderOpts) -> RenderOpts {
|
||||
RenderOpts { nested_switches: self.prefs.general.switches_affect_nested_comps, draft_shadows: self.prefs.three_d.realtime_shadows, ..opts }
|
||||
}
|
||||
|
||||
/// Whether `effect.cryptomatteAt` with params `p` answers from the kept probe (a few array
|
||||
/// reads; `probeOnly` queries answer `pending` until then). Changes nothing: ask it every
|
||||
/// frame, and start [`Session::crypto_probe_job`] only when a build will actually run.
|
||||
pub fn crypto_probe_ready(&self, p: &Value) -> Result<bool> {
|
||||
commands::crypto_probe_ready(self, p)
|
||||
}
|
||||
|
||||
/// For the Cryptomatte eyedropper: `None` when `effect.cryptomatteAt` with params `p` answers
|
||||
/// from the kept probe, else a job that builds that probe (it may render a precomp's ID pass)
|
||||
/// off the UI thread, for the next query to use. Asking for a job supersedes a build in
|
||||
/// flight for another probe (it then stores nothing): ask only to run it.
|
||||
pub fn crypto_probe_job(&self, p: &Value) -> Result<Option<commands::CryptoProbeJob>> {
|
||||
commands::crypto_probe_job(self, p)
|
||||
}
|
||||
|
||||
/// Let go of the kept Cryptomatte probe (and its aux channels), and cancel a build in
|
||||
/// flight: the eyedropper was disarmed. Edits, footage changes and Open / New do it too.
|
||||
pub fn drop_crypto_probe(&self) {
|
||||
if let Ok(mut slot) = self.crypto_probe.lock() {
|
||||
slot.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether a Cryptomatte probe is kept, and how many were built so far (for tests).
|
||||
#[doc(hidden)]
|
||||
pub fn crypto_probe_stats(&self) -> (bool, u64) {
|
||||
self.crypto_probe.lock().map_or((false, 0), |s| (s.kept(), s.builds().1))
|
||||
}
|
||||
|
||||
/// How many probe jobs ran so far, built or cancelled before they began (for tests: each
|
||||
/// is a thread in the eyedropper).
|
||||
#[doc(hidden)]
|
||||
pub fn crypto_probe_jobs(&self) -> u64 {
|
||||
self.crypto_probe.lock().map_or(0, |s| s.builds().0)
|
||||
}
|
||||
|
||||
/// Render a comp frame (comp time `t`) as opaque 8-bit RGBA over the comp background, scaled
|
||||
/// so the longest side is at most `max_side` pixels (0 = full size). Returns (width, height, rgba).
|
||||
pub fn render_rgba8(&self, comp: ItemId, t: Tick, max_side: u32) -> Result<(u32, u32, Vec<u8>)> {
|
||||
@@ -95,5 +135,6 @@ impl Session {
|
||||
self.footage.forget(p);
|
||||
}
|
||||
self.layer_cache.clear();
|
||||
self.drop_crypto_probe();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user