Early days: oxframe is under very active development. The API is not stable yet and may change from version to version. Pin the exact version in your Cargo.toml and check the changelog before upgrading.

11. Scenes and transitions

A video is several scenes in a row. One render plays them in order and blends one into the next.

Loading live preview…

Source of learn_11_scenes — edit in the playground
//! Lesson 11 — Scenes and transitions.
//!
//! A project is a list of scenes, played in order. A scene that starts with
//! `transition(...)` blends in over the one before it, so one render gives
//! the whole video without cutting it together elsewhere.

use oxframe::prelude::*;

#[oxframe::scene]
pub async fn first(view: View) {
    let title = view.add(TitleCard::new("Scene one").subtitle("a title card"));
    title.enter().await;
    wait_for(0.6).await;
}

#[oxframe::scene]
pub async fn second(view: View) {
    // The previous scene holds its last frame while this one slides in.
    // The call waits out the blend; its length comes from the theme.
    transition(Transition::slide(Dir::Left)).await;
    let list = view.add(BulletList::new([
        "Each scene is an async function",
        "Project::scene adds it in order",
        "transition blends it in",
    ]));
    list.enter().await;
    list.next().await;
    list.next().await;
    wait_for(0.4).await;
}

#[oxframe::scene]
pub async fn third(view: View) {
    transition(Transition::fade().duration(0.8)).await;
    let end = view.add(EndCard::new("Three scenes, one video"));
    end.enter().await;
}

// Try: `Transition::wipe(Dir::Up)` or `Transition::zoom_in()` in `second`.

pub fn project() -> Project {
    Project::new("scenes")
        .scene(first())
        .scene(second())
        .scene(third())
}

A project is a list of scenes

Each #[oxframe::scene] function is one scene. Project::new(..) takes them with .scene(first()).scene(second()) and plays them in that order. Every scene starts with an empty view, so it only holds what it needs. oxframe render --scene second renders one scene on its own.

Blend into the next one

transition(Transition::slide(Dir::Left)).await at the start of a scene blends it in over the one before. The call waits out the blend: nodes added before it are on screen while it runs, nodes added after appear when it ends. Without .duration(..) the length comes from the theme, and the editor can drag it afterwards.

The built-ins are fade, slide(dir), wipe(dir), zoom_in and zoom_out. The previous scene holds its last frame; .overlap() lets it keep playing. Lesson 13 adds one painted by a shader.