use std::hash::Hash;
use crate::dyn_compare::{DynEq, DynHash};
use crate::geometry::{Rect, Vec2};
use crate::layer::composite_children;
use crate::raster::{RasterComponent, RasterImage, RasterResidency, Resolution};
use crate::render_context::RenderContext;
use super::*;
pub trait TimelineComponent: TimelineComponentClone + DynEq + DynHash {
fn duration(&self) -> Option<f64> {
None
}
fn measure(&self) -> Option<f64> {
self.duration()
}
fn resolve(&self, abs_start: f64, out: &mut ResolveCtx) -> f64 {
let _ = (abs_start, out);
self.duration().unwrap_or(0.0)
}
fn frame(
&self,
clock: Clock<'_>,
canvas: Vec2,
target: Resolution,
residency: RasterResidency,
ctx: &mut dyn RenderContext,
) -> Option<RasterImage> {
let _ = (clock, canvas, target, residency, ctx);
None
}
fn render_audio_block(&self, mut block: AudioBlockMut<'_>, _ctx: &mut AudioRenderContext) {
block.clear();
}
fn cues(&self, offset: f64) -> Vec<Cue> {
let _ = offset;
Vec::new()
}
fn arrangement(&self, offset: f64) -> Arrangement;
fn structural_any(&self) -> &dyn std::any::Any {
self.as_any()
}
}
const _: Option<&dyn TimelineComponent> = None;
const _: Option<&(dyn TimelineComponent + Send)> = None;
pub trait TimelineComponentClone {
fn clone_box(&self) -> Box<dyn TimelineComponent>;
#[doc(hidden)]
fn clone_box_send(&self) -> Box<dyn TimelineComponent + Send>
where
Self: Send;
}
impl<T: TimelineComponent + Clone + 'static> TimelineComponentClone for T {
fn clone_box(&self) -> Box<dyn TimelineComponent> {
Box::new(self.clone())
}
fn clone_box_send(&self) -> Box<dyn TimelineComponent + Send>
where
Self: Send,
{
Box::new(self.clone())
}
}
impl Clone for Box<dyn TimelineComponent> {
fn clone(&self) -> Self {
self.clone_box()
}
}
impl Clone for Box<dyn TimelineComponent + Send> {
fn clone(&self) -> Self {
self.clone_box_send()
}
}
impl PartialEq for dyn TimelineComponent + Send {
fn eq(&self, other: &Self) -> bool {
DynEq::dyn_eq(self, other.as_any())
}
}
impl Eq for dyn TimelineComponent + Send {}
impl Hash for dyn TimelineComponent + Send {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
DynHash::dyn_hash(self, state);
}
}
impl<C> TimelineComponent for C
where
C: RasterComponent + Clone + 'static,
{
fn duration(&self) -> Option<f64> {
None
}
fn frame(
&self,
clock: Clock<'_>,
canvas: Vec2,
target: Resolution,
residency: RasterResidency,
ctx: &mut dyn RenderContext,
) -> Option<RasterImage> {
let _ = clock;
let canvas_rect = Rect {
origin: Vec2::ZERO,
size: canvas,
};
if self.paint_bounds(canvas) == canvas_rect {
return Some(ctx.render(self, canvas, target, residency));
}
Some(composite_children(
canvas_rect,
target,
&[(Vec2::ZERO, canvas, self as &dyn RasterComponent)],
residency,
ctx,
))
}
fn cues(&self, _offset: f64) -> Vec<Cue> {
Vec::new()
}
fn arrangement(&self, offset: f64) -> Arrangement {
Arrangement {
kind: NodeKind::Video,
label: String::new(),
name: self.arrangement_name(),
source: None,
start: offset,
end: offset + self.duration().unwrap_or(0.0),
trim: None,
triggers: Vec::new(),
children: Vec::new(),
}
}
}
pub trait TimelineBuilder: Sized {
type Output: TimelineComponent + PartialEq + Hash + 'static;
fn build_component(self) -> Self::Output;
}