Presentations
The same scenes that render to a video become a talk: the presentation stops where you mark it and waits for the next click.
Loading live preview…
Source of slides — edit in the playground
//! A talk: `oxframe present` stops at every `slide_break` and at the end
//! of each scene, and shows the notes in the presenter window. Rendered,
//! the same scenes play straight through as a video.
use oxframe::prelude::*;
#[oxframe::scene]
pub async fn opening(view: View) {
notes("Introduce yourself. One line on why video from code.");
let title = view.add(TitleCard::new("Video as code").subtitle("A talk in three stops"));
title.enter().await;
title.next().await;
// The video plays through the stops, so hold before each one: in the
// presentation the hold is a still frame before it stops anyway.
wait_for(1.5).await;
slide_break().await;
notes("Each point appears on the next click.");
title.exit().await;
let points = view.add(BulletList::new([
"Scenes are async Rust",
"Every value is a signal",
"The agent checks its own frames",
]));
points.enter().await;
// The last point ends the scene, so its stop is the scene's end; the
// fade into the next scene takes the list away.
for _ in 0..3 {
points.next().await;
wait_for(1.5).await;
slide_break().await;
}
}
#[oxframe::scene]
pub async fn closing(view: View) {
transition(Transition::fade()).await;
notes("Point to the docs and take questions.");
let end = view.add(EndCard::new("Questions?").note("oxframe.dev"));
end.enter().await;
end.next().await;
wait_for(0.5).await;
}
pub fn project() -> Project {
Project::new("slides").scene(opening()).scene(closing())
}Stops and notes
#[oxframe::scene]
pub async fn opening(view: View) {
notes("Introduce yourself.");
let title = view.add(TitleCard::new("Video as code"));
title.enter().await;
wait_for(1.5).await;
slide_break().await;
notes("Each point appears on the next click.");
let points = view.add(BulletList::new(["Scenes are async Rust", "Every value is a signal"]));
points.enter().await;
for _ in 0..2 {
points.next().await;
wait_for(1.5).await;
slide_break().await;
}
} slide_break().await marks a stop. A render plays straight through it, so the project
is still a video; the presentation pauses there. The last frame of every scene is a stop too, and
a break at the very end of a scene is the same stop. notes("…") are speaker notes for the
part that ends at the next stop; several calls before one stop are joined.
Hold before each break with wait_for. The video plays straight through the stops, and
without a hold the text is gone before anyone reads it — oxframe check reports that
as too_fast. In the presentation the hold is a still frame just before the stop, so
nobody sees it.
Presenting
oxframe present oxframe present builds the project and opens it full screen in the browser, without the
editor around it. → , space, Page Down and a click go to the next stop: the scene plays up to it and
stops. Pressed while it plays, the next key jumps straight to the stop. ← and Page Up go back one stop,
Home to the start. Slide clickers send these keys, so they work as they are. F toggles full screen.
N opens the presenter window: the notes for the current part and the next one, the stop number and
a timer. Put it on your laptop screen and the presentation on the projector; its keys and buttons
move the presentation as well. Going back is safe even with spawn and random values: the
state of a scene depends only on its frame.
The presentation is the live project: saving a source file rebuilds it, as in oxframe dev. The playground on this site plays the scenes straight through.
Slides as a PDF
oxframe render --slides talk.pdf render --slides talk.pdf writes one page per stop, the frame the presentation shows
there, for handouts or a fallback. It needs no ffmpeg; --size and --cpu work as for a video.