feat: Camera control

This commit is contained in:
Rendo 2026-08-03 03:07:31 +05:00
commit 8373b10ac1
3 changed files with 112 additions and 35 deletions

108
src/camera.rs Normal file
View file

@ -0,0 +1,108 @@
use bevy::{input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll}, prelude::*};
use crate::grid::Grid;
use std::{f32::consts::FRAC_PI_2,ops::Range};
pub struct GameCameraPlugin;
impl Plugin for GameCameraPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, scene.spawn())
.add_systems(Update, orbit);
}
}
#[derive(Clone,Component)]
pub struct CameraOrbit {
pub distance: f32,
pub pitch_speed: f32,
pub pitch_range: Range<f32>,
pub yaw_speed: f32,
pub center_offset: Vec3,
pub vertical_offset_speed: f32,
pub horizontal_offset_speed: f32,
}
impl Default for CameraOrbit {
fn default() -> Self {
let limit = FRAC_PI_2 - 0.01;
Self {
distance: 20.,
yaw_speed: 0.004,
pitch_speed: 0.004,
pitch_range: -limit..limit,
center_offset: Vec3::ZERO,
vertical_offset_speed: 0.05,
horizontal_offset_speed: 0.05,
}
}
}
pub fn scene() -> impl SceneList {
bsn_list![
camera(),
sun()
]
}
pub fn camera() -> impl Scene {
bsn! {
Camera3d
template(
|ctx| {
let grid = ctx.resource::<Grid>();
let center = grid.size.as_vec3() * 0.5;
Ok(Transform::from_xyz(
center.x + grid.size.x as f32 * 1.2,
grid.size.y as f32 * 1.2,
center.z + grid.size.z as f32 * 1.2).looking_at(center, Vec3::Y))
}
)
CameraOrbit
}
}
pub fn sun() -> impl Scene {
bsn!{
DirectionalLight {
illuminance: 8_000.0,
shadow_maps_enabled: false,
}
template_value(Transform::from_xyz(10.0, 30.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y))
}
}
pub fn orbit(
camera: Single<(&mut Transform,&mut CameraOrbit)>,
mouse_buttons: Res<ButtonInput<MouseButton>>,
mouse_motion: Res<AccumulatedMouseMotion>,
mouse_scroll: Res<AccumulatedMouseScroll>,
grid: Res<Grid>) {
let (mut transform, mut orbit) = camera.into_inner();
if mouse_buttons.pressed(MouseButton::Right) {
let delta = mouse_motion.delta;
let (yaw, pitch, roll) = transform.rotation.to_euler(EulerRot::YXZ);
let pitch = (pitch - delta.y * orbit.pitch_speed).clamp(orbit.pitch_range.start, orbit.pitch_range.end);
let yaw = yaw - delta.x * orbit.yaw_speed;
transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
}
if mouse_buttons.pressed(MouseButton::Middle) {
let delta = mouse_motion.delta;
let new_offset = transform.up() * delta.y * orbit.vertical_offset_speed - transform.right() * delta.x * orbit.horizontal_offset_speed;
orbit.center_offset += new_offset;
}
let center = grid.size.as_vec3() * 0.5;
let min_distance = vec3(
center.x + grid.size.x as f32 * 1.2,
grid.size.y as f32 * 1.2,
center.z + grid.size.z as f32 * 1.2).length();
orbit.distance = (orbit.distance-mouse_scroll.delta.y).max(min_distance);
transform.translation = center + orbit.center_offset -transform.forward() * orbit.distance;
}

View file

@ -1,4 +1,5 @@
use bevy::prelude::*;
use crate::camera::GameCameraPlugin;
use crate::grid::Grid;
use crate::simulation::SimulationPlugin;
@ -7,12 +8,12 @@ use crate::view::ViewPlugin;
pub mod simulation;
pub mod view;
pub mod grid;
pub mod camera;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(ViewPlugin)
.add_plugins(SimulationPlugin)
.add_plugins((ViewPlugin,SimulationPlugin,GameCameraPlugin))
.insert_resource(Grid::cube(16))
.run();
}

View file

@ -11,7 +11,7 @@ impl Plugin for GameViewPlugin {
app.add_systems(PreStartup, debug_setup_grid)
.init_resource::<CubeStages>()
.init_resource::<TileMaterials>()
.add_systems(Startup, (setup_view_cubes, scene.spawn()))
.add_systems(Startup, setup_view_cubes)
.add_systems(Update, update_cubes);
}
}
@ -84,38 +84,6 @@ pub fn setup_view_cubes(
}
}
pub fn scene() -> impl SceneList {
bsn_list![
camera(),
sun()
]
}
pub fn camera() -> impl Scene {
bsn! {
Camera3d
template(
|ctx| {
let grid = ctx.resource::<Grid>();
let center = grid.size.as_vec3() * 0.5;
Ok(Transform::from_xyz(
center.x + grid.size.x as f32 * 1.5,
grid.size.y as f32 * 1.5,
center.z + grid.size.z as f32 * 1.5).looking_at(center, Vec3::Y))
}
)
}
}
pub fn sun() -> impl Scene {
bsn!{
DirectionalLight {
illuminance: 8_000.0,
shadow_maps_enabled: false,
}
template_value(Transform::from_xyz(10.0, 30.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y))
}
}
pub fn cube(position: Vec3,index: usize,mesh: Handle<Mesh>) -> impl Scene {