1use bevy::input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll};
4use bevy::prelude::Projection::Orthographic;
5use bevy::prelude::{
6 Bundle, ButtonInput, Camera2d, Commands, Component, Local, MouseButton, Name, Projection, Res,
7 Single, Transform, With,
8};
9use bevy_egui::PrimaryEguiContext;
10
11#[derive(Default, Component)]
13pub struct UICamera;
14
15#[derive(Default)]
17pub(crate) struct UICameraState {
18 pub moving: bool,
20}
21
22impl UICamera {
23 #[must_use]
25 pub fn bundle() -> impl Bundle {
26 (Name::new("UI Camera"), Self, PrimaryEguiContext, Camera2d)
27 }
28}
29
30#[utils::bevy_system]
32pub(crate) fn setup_ui_camera(mut commands: Commands) {
33 commands.spawn(UICamera::bundle());
34}
35
36#[utils::bevy_system]
40pub(crate) fn camera_control_system(
41 mut state: Local<UICameraState>,
42 mouse_input: Res<ButtonInput<MouseButton>>,
43 mut camera: Single<(&mut Transform, &mut Projection), With<UICamera>>,
44 mouse_motion: Res<AccumulatedMouseMotion>,
45 mouse_scroll: Res<AccumulatedMouseScroll>,
46) {
47 if mouse_input.just_pressed(MouseButton::Right) {
48 state.moving = true;
49 } else if mouse_input.just_released(MouseButton::Right) {
50 state.moving = false;
51 }
52
53 let (transform, projection) = &mut *camera;
54
55 if state.moving {
56 transform.translation.x -= mouse_motion.delta.x;
57 transform.translation.y += mouse_motion.delta.y;
58 }
59
60 if let Orthographic(projection) = &mut **projection {
61 projection.scale /= 1.0 + mouse_scroll.delta.y * 0.01;
62 }
63}