use oxideav_core::{Error, Result};
use crate::duration::TimeStamp;
use crate::ops::ExportOp;
use crate::scene::Scene;
#[derive(Clone, Debug, Default)]
pub struct RenderedFrame {
pub video: Option<oxideav_core::VideoFrame>,
pub audio: Vec<f32>,
pub operations: Vec<ExportOp>,
}
pub trait SceneRenderer {
fn prepare(&mut self, scene: &Scene) -> Result<()>;
fn render_at(&mut self, scene: &Scene, t: TimeStamp) -> Result<RenderedFrame>;
fn seek(&mut self, t: TimeStamp) -> Result<()>;
}
pub trait SceneSampler {
fn sample(&mut self, t: TimeStamp) -> Result<Option<SampleOutput>>;
fn natural_size(&self) -> (f32, f32);
}
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum SampleOutput {
Frame(oxideav_core::VideoFrame),
Audio(Vec<f32>),
StructuredOp(ExportOp),
}
#[derive(Default)]
pub struct StubRenderer;
impl SceneRenderer for StubRenderer {
fn prepare(&mut self, _scene: &Scene) -> Result<()> {
Err(Error::unsupported(
"oxideav-scene: renderer is a scaffold — real renderer lands as a separate crate",
))
}
fn render_at(&mut self, _scene: &Scene, _t: TimeStamp) -> Result<RenderedFrame> {
Err(Error::unsupported(
"oxideav-scene: renderer is a scaffold — real renderer lands as a separate crate",
))
}
fn seek(&mut self, _t: TimeStamp) -> Result<()> {
Err(Error::unsupported(
"oxideav-scene: renderer is a scaffold — real renderer lands as a separate crate",
))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn stub_renderer_returns_unsupported() {
let scene = Scene::default();
let mut r = StubRenderer;
let err = r.prepare(&scene).unwrap_err();
assert!(matches!(err, Error::Unsupported(_)));
let err = r.render_at(&scene, 0).unwrap_err();
assert!(matches!(err, Error::Unsupported(_)));
}
}