Skip to content

Pan camera mouse pan#22859

Open
Sigma-dev wants to merge 1 commit intobevyengine:mainfrom
Sigma-dev:feat/pan-camera-mouse-pan
Open

Pan camera mouse pan#22859
Sigma-dev wants to merge 1 commit intobevyengine:mainfrom
Sigma-dev:feat/pan-camera-mouse-pan

Conversation

@Sigma-dev
Copy link
Contributor

@Sigma-dev Sigma-dev commented Feb 7, 2026

Objective

The current PanCamera only supports keyboard panning, when a common use case is mouse panning.

Solution

Add optional mouse panning with some settings

Testing

I ran the Pan Camera example with the new settings

Additional notes

I added settings for setting the exact mouse button that triggers the panning, and whether or not to grab the cursor when panning.

I am unsure about the cursor grab part of this design as it may mess with the app's existing cursor options and the window part may not work for some setups.

It may be wiser to just omit grabbing for now, or maybe keep grabbing but don't change visibility idk

As always I am open to any and all feedback.

@laundmo
Copy link
Contributor

laundmo commented Feb 7, 2026

I personally always use a implementation based on observers, and think this should be done that way as well (alongside the scroll)

The issue is that a very common and useful pattern is to use picking observers like On<Pointer<Drag>> on meshes or sprites to allow dragging them. By using the underlying MouseMotion messages, it becomes way harder to handle that, as now dragging an entity using picking will also at the same time drag the pancam. If this was using a On<Pointer<Drag>> observer on the window (render target of the camera) it would inherently allow the pancam to only recieve drag events when no picking object is covering it.

@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible A-Dev-Tools Tools used to debug Bevy applications. S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Feb 8, 2026
@alice-i-cecile
Copy link
Member

I prefer the observers-based design from @laundmo as well:

// assuming 1 window
fn setup(mut commands: Commands, window: Single<Entity, With<Window>>) {
    commands.entity(*window).observe(camera_drag);
}
fn camera_drag(
    drag: On<Pointer<Drag>>,
    mut cam: Single<(&Camera, &GlobalTransform, &mut Transform)>,
) {
    if let Ok(cam_viewport) = cam.0.world_to_viewport(cam.1, cam.2.translation)
        && let cam_viewport = cam_viewport + drag.delta * -1. // inverted feels more natural
        && let Ok(world_changed) = cam.0.viewport_to_world_2d(cam.1, cam_viewport)
    {
        cam.2.translation = world_changed.extend(cam.2.translation.z);
    }
}

I think this is going to be easier to adapt and handle.

}

/// Settings for mouse panning for the [`PanCamera`] controller.
pub struct MousePanSettings {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs an enabled bool as well.

/// [`KeyCode`] for clockwise rotation.
pub key_rotate_cw: Option<KeyCode>,
/// Mouse pan settings.
pub mouse_pan_settings: Option<MousePanSettings>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the use of an Option here isn't very clear. Making this always present but having an enabled bool feels more reasonable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Dev-Tools Tools used to debug Bevy applications. C-Feature A new feature, making something new possible S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants