Slide show: transitions show the old slide instead of the new one twice (#33) (#46)

On a slide change the show kept a clone of the old slide's texture handle
as the transition's "old" picture, then rendered the new slide into that
same texture with set(). Old and new were the same image, so every
transition (except Morph, which renders into its own texture) blended the
new slide with itself and looked like an instant cut. The old texture is
now taken out of show.tex, so the new slide gets a texture of its own.

generated with Claude Code
This commit is contained in:
alexanderalber 2026-10-10 12:17:32 +02:00 committed by GitHub
parent 322d85074e
commit c543ef350e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 30 additions and 2 deletions

View File

@ -121,8 +121,10 @@ impl Show {
.and_then(|s| s.transition.as_ref())
.map(|t| (t.kind.clone(), t.option.clone(), t.duration_ms as f64 / 1000.0))
.unwrap_or(("none".into(), String::new(), 0.0));
let old = self.tex.as_ref().map(|(_, t)| t.clone());
let from = self.tex.as_ref().map(|(k, _)| k.slide);
// Take the old slide's texture rather than cloning its handle: the new slide is
// otherwise rendered into the same texture, and the transition blends the new
// slide with itself (#33).
let (from, old) = self.tex.take().map(|(k, t)| (k.slide, t)).unzip();
self.trans = if kind != "none" && dur > 0.0 && !doc.show.without_animation {
Some(Transition { old, from, morph: None, start: now, kind, option, dur })
} else {
@ -736,3 +738,29 @@ fn presenter_window(ctx: &egui::Context, show: &mut Show, doc: &Presentation, no
}
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::*;
#[test]
fn a_transition_keeps_the_old_slide_in_its_own_texture() {
// #33: the old slide's handle was cloned, so the new slide was rendered into the same
// texture and every transition blended the new slide with itself.
let mut s = deckcraft_engine::Session::with_new();
s.execute("slide.new", &json!({})).unwrap();
s.execute("transition.set", &json!({"kind": "fade", "index": 1})).unwrap();
let doc = s.active().unwrap().doc.clone();
let ctx = egui::Context::default();
let red = ctx.load_texture("show", egui::ColorImage::filled([1, 1], Color32::RED), egui::TextureOptions::LINEAR);
let mut show = Show::new(&doc, 0, false, false);
show.tex = Some((Key { slide: 0, step: 0, size: (1, 1), doc: 0, hidden: vec![] }, red.clone()));
assert!(show.apply(ShowAction::Slide(1), &doc, 0.0));
let tr = show.trans.as_ref().expect("the fade plays");
assert_eq!(tr.old.as_ref().map(TextureHandle::id), Some(red.id()));
assert_eq!(tr.from, Some(0));
assert!(show.tex.is_none(), "the new slide gets a texture of its own instead of overwriting the old one");
}
}