mirror of
https://github.com/storytold/photocraft.git
synced 2026-11-10 12:22:22 +00:00
Scope Actions tool recording guard to the active take
This commit is contained in:
1 parent
cfda1d893b
commit
2e210c0aae
3 files changed
+38
-8
No files matched your search
@@ -148,7 +148,10 @@ fn source_wire_identity_is_retained_only_for_unchanged_geometry() {
|
||||
#[test]
|
||||
fn unknown_and_unrepresented_settings_are_not_silently_lost() {
|
||||
let base = fixture("Sbtr", false, false);
|
||||
for d in [base.clone().with("extra", D::Boolean(true)), base.clone().with("T ", D::List(Vec::new())), fixture("Intr", false, false)] {
|
||||
let mut empty_components = base.clone();
|
||||
let (_, components) = empty_components.items.iter_mut().find(|(key, _)| key.is("T ")).unwrap();
|
||||
*components = D::List(Vec::new());
|
||||
for d in [base.clone().with("extra", D::Boolean(true)), empty_components, fixture("Intr", false, false)] {
|
||||
assert!(matches!(from(&d), Mapped::Unsupported { harmless: false }));
|
||||
}
|
||||
let p = params(&base);
|
||||
|
||||
@@ -507,9 +507,9 @@ struct Running {
|
||||
label: String,
|
||||
params: Value,
|
||||
journal: bool,
|
||||
/// The recording (`ActionState::take`) running when the job started, if any (set by
|
||||
/// `dispatch`, once recording resumes). Only that recording gets the job's step: one started
|
||||
/// later must not pick up an edit made before it.
|
||||
/// The take active at dispatch, including strokes started with tool recording off.
|
||||
started_in_take: Option<u64>,
|
||||
/// The take eligible to receive this job's step under the mode at dispatch.
|
||||
recorded_by: Option<u64>,
|
||||
pre_selected: Option<Vec<LayerId>>,
|
||||
before: crate::actions_record::Before,
|
||||
@@ -863,6 +863,7 @@ fn new_job<T: Send + 'static>(
|
||||
label: label.to_string(),
|
||||
params: Value::Null,
|
||||
journal: true,
|
||||
started_in_take: None,
|
||||
recorded_by: None,
|
||||
pre_selected: None,
|
||||
before: crate::actions_record::Before::capture(s),
|
||||
@@ -1031,9 +1032,9 @@ pub struct PendingPsdPreflight {
|
||||
}
|
||||
|
||||
impl Session {
|
||||
/// A recording mode change must not reclassify a painting job that is still in flight.
|
||||
/// A recording mode change must not reclassify an in-flight stroke from this take.
|
||||
pub(crate) fn tool_stroke_job_running(&self) -> bool {
|
||||
self.jobs.running.iter().any(|job| crate::actions_cmds::tool_stroke(&job.command))
|
||||
self.jobs.running.iter().any(|job| job.started_in_take == Some(self.actions.take) && crate::actions_cmds::tool_stroke(&job.command))
|
||||
}
|
||||
|
||||
/// Run the heavy part of inline (not background) job commands under `ctx`, so another thread
|
||||
@@ -1816,8 +1817,8 @@ impl Session {
|
||||
job.command = id.to_string();
|
||||
job.params = params;
|
||||
job.journal = spec.journal;
|
||||
job.recorded_by =
|
||||
self.actions.recording.filter(|_| self.actions.record_tools || !crate::actions_cmds::tool_stroke(id)).map(|_| self.actions.take);
|
||||
job.started_in_take = self.actions.recording.map(|_| self.actions.take);
|
||||
job.recorded_by = job.started_in_take.filter(|_| self.actions.record_tools || !crate::actions_cmds::tool_stroke(id));
|
||||
job.pre_selected = pre_selected.clone();
|
||||
job.before = std::mem::take(&mut record_before);
|
||||
let jid = job.id;
|
||||
|
||||
@@ -67,6 +67,32 @@ fn background_stroke_ownership_does_not_suppress_ordinary_filter_jobs() {
|
||||
}
|
||||
}
|
||||
|
||||
/// A Remove job started outside the current take neither blocks its toggle nor joins its steps.
|
||||
#[test]
|
||||
fn background_strokes_from_outside_the_current_take_do_not_block_the_toggle() {
|
||||
for previous_take in [false, true] {
|
||||
let mut s = session();
|
||||
stroke(&mut s, "#bb3300");
|
||||
if previous_take {
|
||||
s.execute("actions.record", json!({"action":"A"})).unwrap();
|
||||
s.execute("actions.allowToolRecording", json!({"enabled":true})).unwrap();
|
||||
}
|
||||
let Started::Job(job) = s.start("paint.remove", json!({"points":[[20,15],[21,15]],"size":3})).unwrap() else {
|
||||
panic!("expected the real Remove job");
|
||||
};
|
||||
if previous_take {
|
||||
s.execute("actions.stop", json!({})).unwrap();
|
||||
s.execute("actions.allowToolRecording", json!({"enabled":false})).unwrap();
|
||||
}
|
||||
s.execute("actions.record", json!({"action":"A"})).unwrap();
|
||||
assert_eq!(s.execute("actions.allowToolRecording", json!({"enabled":true})).unwrap()["enabled"], true);
|
||||
s.wait_job(job).unwrap();
|
||||
s.execute("actions.stop", json!({})).unwrap();
|
||||
assert!(s.actions.list[0].steps.is_empty());
|
||||
assert_eq!(s.journal.iter().filter(|step| step.0 == "paint.remove").count(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Interleaved membership and numeric calls expose incorrect folder placement or target rewriting.
|
||||
#[test]
|
||||
fn set_duplication_preserves_metadata_call_targets_and_empty_folder_order() {
|
||||
|
||||
Reference in new issue
Block a user