Render R2: persist named render setups without re-evaluating geometry (#667)

render.settings.set saves validated named render setups (camera, output size, exposure, environment) as one undo step, and render.settings.get reads them back without applying a camera. When validated render settings are the only change, the engine keeps the evaluated model instead of rebuilding it. Setups are saved under design format 21; format-20 designs read as having none. Fixes #658; refs #620.

Contributed by @0xlillith.

Co-authored-by: lillith <35337584+0xlillith@users.noreply.github.com>
This commit is contained in:
selune authored and GitHub committed 2026-10-14 17:11:39 -04:00
1 parent 771a11feab
commit 289b521a65
22 files changed
+641 -16

No files matched your search

+30
View File
@@ -28,6 +28,14 @@ fn child() {
s.execute("document.inspect", &json!({})).unwrap();
}
match mode.as_str() {
"render" => {
s.execute("render.settings.set", &json!({"name":"Studio","set":{"exposure_ev":2}})).unwrap();
s.execute("render.settings.get", &json!({"name":"Studio"})).unwrap();
s.execute("render.settings.set", &json!({"name":"Studio","set":{"exposure_ev":3}})).unwrap();
s.execute("edit.undo", &json!({})).unwrap();
s.execute("edit.redo", &json!({})).unwrap();
let _ = s.execute("diagnostics.crash_test", &json!({"mode":"abort"}));
}
"command" => {
for _ in 0..3 {
let r = s.execute("diagnostics.crash_test", &json!({"mode": "panic"}));
@@ -157,6 +165,28 @@ fn an_abort_is_reported_at_the_next_start_with_a_replay() {
let _ = fs::remove_dir_all(&d);
}
#[test]
fn render_settings_survive_unclean_exit_and_journal_replay() {
let d = fresh_dir("render");
assert!(!run_child(&d, "render").1);
assert!(run_child(&d, "none").1);
let (_, report) = only_report(&d);
let replay: Value = serde_json::from_slice(&fs::read(report["replay_path"].as_str().unwrap()).unwrap()).unwrap();
let commands = replay["commands"].as_array().unwrap();
assert!(!commands.iter().any(|c| c["command"] == "render.settings.get"));
assert_eq!(commands.iter().filter(|c| c["command"] == "render.settings.set").count(), 2);
let mut recovered = Session::default();
for command in commands {
let id = command["command"].as_str().unwrap();
if id != "diagnostics.crash_test" {
recovered.execute(id, &command["params"]).unwrap();
}
}
assert_eq!(recovered.doc.features.len(), 1);
assert_eq!(recovered.doc.render.setups["Studio"].exposure_ev, 3.0);
let _ = fs::remove_dir_all(&d);
}
#[test]
fn a_journal_reads_back_its_base_commands_and_the_one_in_flight() {
let d = fresh_dir("journal");