use bevy::post_process::effect_stack::Vignette;
use bevy::prelude::*;
use bevy_director::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, DirectorPlugin))
.add_systems(Startup, setup)
.add_systems(Update, (play_on_space, report_cuts))
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(60.0, 1.0, 60.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.24, 0.26, 0.3),
..Default::default()
})),
Transform::from_xyz(0.0, -0.5, 0.0),
));
let block = meshes.add(Cuboid::new(2.0, 6.0, 2.0));
for i in -3..=3 {
commands.spawn((
Mesh3d(block.clone()),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::hsl(24.0 + i as f32 * 14.0, 0.45, 0.52),
..Default::default()
})),
Transform::from_xyz(i as f32 * 5.0, 3.0, -6.0),
));
}
commands.spawn((
Name::new("mark"),
Mesh3d(meshes.add(Sphere::new(0.8))),
MeshMaterial3d(materials.add(StandardMaterial {
emissive: LinearRgba::rgb(6.0, 3.0, 1.0),
..Default::default()
})),
Transform::from_xyz(0.0, 2.0, 4.0),
));
commands.spawn((
DirectionalLight::default(),
Transform::from_xyz(18.0, 32.0, 14.0).looking_at(Vec3::ZERO, Vec3::Y),
));
commands.spawn((
Camera3d::default(),
Camera {
clear_color: ClearColorConfig::Custom(Color::srgb(0.05, 0.07, 0.12)),
..Default::default()
},
Transform::from_xyz(0.0, 4.0, 20.0).looking_at(Vec3::new(0.0, 2.0, 0.0), Vec3::Y),
));
commands.spawn((
Name::new("crane"),
CineCamera,
Camera3d::default(),
Camera {
is_active: false,
clear_color: ClearColorConfig::Custom(Color::srgb(0.05, 0.07, 0.12)),
..Default::default()
},
Transform::from_xyz(-12.0, 9.0, 8.0).looking_at(Vec3::new(0.0, 2.0, 0.0), Vec3::Y),
));
commands.spawn((
Name::new("dolly"),
CineCamera,
Camera3d::default(),
Camera {
is_active: false,
clear_color: ClearColorConfig::Custom(Color::srgb(0.12, 0.05, 0.05)),
..Default::default()
},
Vignette {
intensity: 0.85,
..Default::default()
},
Transform::from_xyz(9.0, 2.0, 7.0).looking_at(Vec3::new(0.0, 2.0, 0.0), Vec3::Y),
));
info!("space plays the take; watch the cuts between gameplay, crane, and dolly");
}
fn play_on_space(
keys: Res<ButtonInput<KeyCode>>,
mut assets: ResMut<Assets<SequenceAsset>>,
mut commands: Commands,
) {
if !keys.just_pressed(KeyCode::Space) {
return;
}
let look_at_mark = Look::At {
target: TargetRef::Entity("mark".into()),
damping: None,
};
let take = SequenceAsset {
name: "coverage".into(),
shots: vec![
Shot::keys(
0.0,
3.0,
vec![
Key::at(0.0).pos(Vec3::new(0.0, 4.0, 20.0)),
Key::at(3.0).pos(Vec3::new(0.0, 3.5, 13.0)),
],
)
.look(look_at_mark.clone())
.blend_in(1.0, EaseFunction::SmoothStep),
Shot::keys(
3.0,
3.0,
vec![
Key::at(0.0).pos(Vec3::new(-12.0, 9.0, 8.0)),
Key::at(3.0).pos(Vec3::new(-6.0, 3.0, 7.0)),
],
)
.look(look_at_mark.clone())
.camera("crane"),
Shot::keys(
6.0,
3.0,
vec![
Key::at(0.0).pos(Vec3::new(9.0, 2.0, 7.0)),
Key::at(3.0).pos(Vec3::new(4.0, 2.2, 5.0)),
],
)
.look(look_at_mark)
.camera("dolly"),
],
markers: vec![],
texts: vec![
TextBlock::at(0.2, 2.6, "COVERAGE")
.anchor(TextAnchor::Center)
.fades(0.4, 0.6),
TextBlock::at(3.1, 2.8, "crane").anchor(TextAnchor::LowerThird),
TextBlock::at(6.1, 2.8, "dolly — its own vignette").anchor(TextAnchor::LowerThird),
],
actors: vec![],
blend_out: None,
};
let handle = assets.add(take);
commands.play_sequence(handle);
}
fn report_cuts(mut cuts: MessageReader<SequenceCut>) {
for cut in cuts.read() {
info!(
"cut to shot {} ({:?} -> {:?})",
cut.shot + 1,
cut.from,
cut.to
);
}
}