#![allow(clippy::type_complexity)] //! Renders two cameras to the same window to accomplish "split screen". use bevy::{ prelude::*, render::camera::Viewport, window::{PrimaryWindow, WindowResized}, }; use bevy_dolly::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems( Update, ( Dolly::::update_active, Dolly::::update_active, set_camera_viewports, update_camera_1, update_camera_2, ), ) .run(); } #[derive(Component)] struct LeftCamera; #[derive(Component)] struct RightCamera; /// set up a simple 3D scene fn setup( mut commands: Commands, asset_server: Res, mut meshes: ResMut>, mut materials: ResMut>, ) { // plane commands.spawn(PbrBundle { mesh: meshes.add(Plane3d::default().mesh().size(100., 100.)), material: materials.add(Color::srgb(0.3, 0.5, 0.3)), ..default() }); commands.spawn(SceneBundle { scene: asset_server.load("poly_fox.glb#Scene0"), ..default() }); commands.spawn(SceneBundle { scene: asset_server.load("poly_dolly.gltf#Scene0"), ..default() }); // Light commands.spawn(DirectionalLightBundle { transform: Transform::from_rotation(Quat::from_euler( EulerRot::ZYX, 0.0, 1.0, -std::f32::consts::FRAC_PI_4, )), directional_light: DirectionalLight { shadows_enabled: true, ..default() }, ..default() }); // camera commands.spawn(( LeftCamera, Camera3dBundle { transform: Transform::from_xyz(0.0, 200.0, -100.0).looking_at(Vec3::ZERO, Vec3::Y), ..default() }, )); commands.spawn(( LeftCamera, Rig::builder() .with(YawPitch::new().yaw_degrees(45.0).pitch_degrees(-30.0)) .with(Smooth::new_rotation(1.5)) .with(Arm::new(Vec3::Z * 4.0)) .build(), )); commands.spawn(( RightCamera, Rig::builder() .with(YawPitch::new().yaw_degrees(45.0).pitch_degrees(-30.0)) .with(Smooth::new_rotation(1.5)) .with(Arm::new(Vec3::Z * 200.0)) .build(), )); // camera commands .spawn(Camera3dBundle { transform: Transform::from_xyz(100.0, 100., 150.0).looking_at(Vec3::ZERO, Vec3::Y), camera: Camera { clear_color: ClearColorConfig::None, order: 1, ..default() }, ..default() }) .insert(RightCamera); } fn set_camera_viewports( windows: Query<(Entity, &Window), With>, mut resize_events: EventReader, mut left_camera: Query<&mut Camera, (With, Without)>, mut right_camera: Query<&mut Camera, With>, ) { for resize_event in resize_events.read() { if let Ok((entity, window)) = windows.get_single() { if resize_event.window == entity { let mut left_camera = left_camera.single_mut(); left_camera.viewport = Some(Viewport { physical_position: UVec2::new(0, 0), physical_size: UVec2::new( window.physical_width() / 2, window.physical_height(), ), depth: 0.0..1.0, }); let mut right_camera = right_camera.single_mut(); right_camera.viewport = Some(Viewport { physical_position: UVec2::new(window.physical_width() / 2, 0), physical_size: UVec2::new( window.physical_width() / 2, window.physical_height(), ), depth: 0.0..1.0, }); } } } } fn update_camera_1(mut query: Query<&mut Rig, (With, Without)>) { let mut rig = query.single_mut(); let camera_driver = rig.driver_mut::(); camera_driver.rotate_yaw_pitch(1.0, 0.0); } fn update_camera_2( time: Res