/bevy_mod_picking

Unofficial 3D mouse picking plugin for Bevy

Primary LanguageRustMIT LicenseMIT

3D Mouse Picking for Bevy

This is a 3D mouse picking plugin for Bevy. The plugin will cast a ray into the scene and check for intersection against all meshes tagged with the PickableMesh component. The built-in highlighting and selection state, as well as the debug cursor, are opt-in.

Out of the box, the plugin provides: pick depth, pick coordinates, and surface normal of the picked mesh triangle.

Expect Breaking Changes in master - Contributions Welcome

Picking demo

Getting Started

To run the 3d_scene example - a modified version of the Bevy example of the same name - clone this repository and run:

cargo run --example 3d_scene

Usage

Setup

Add the plugin to your dependencies in Cargo.toml

bevy_mod_picking = { git = "https://https://github.com/aevyrie/bevy_mod_picking", branch = "master" }
#bevy_mod_picking = "0.1.2"

Import the plugin:

use bevy_mod_picking::*;

Add it to your App::build() in the plugins section of your Bevy app:

.add_plugin(PickingPlugin)

Marking Entities for Picking

For simple use cases, you will probably be using the mouse to pick items in a 3d scene. You will need to mark your camera with a component:

.with(PickingSource::default())

Now all you have to do is mark any mesh entities with the PickableMesh component:

.with(PickableMesh::default())

If you want it to highlight when you hover, add the HighlightablePickMesh component:

.with(HighlightablePickMesh::new())

If you also want to select meshes and keep them highlighted with the left mouse button, add the SelectablePickMesh component:

.with(SelectablePickMesh::new())

Pick Groups

Pick groups allow you to associate meshes with a ray casting sources. For simple use cases, such as a single 3d view and camera, you can ignore this.

For these simple cases, you can just use PickingGroup::default() any time a PickingGroup is required. This will assign the PickableMesh or PickingSource to picking group 0.

Details

  • Only one PickingSource can be assigned to a PickingGroup
  • A PickableMesh can be assigned to one or many PickingGroups
  • The result of running the picking system is an ordered list of all intersections of each PickingSource with the PickableMeshs in its PickingGroup. The ordered list of intersections are stored by PickingGroup HashMap<PickingGroup, Vec<PickIntersection>>

Getting Pick Data

Pick Intersections Under the Cursor

Mesh picking intersection are reported in world coordinates. You can use the PickState resource to either get the topmost entity, or a list of all entities sorted by distance (near -> far) under the cursor:

fn get_picks(
    pick_state: Res<PickState>,
) {
    println!("All entities:\n{:?}", pick_state.list(PickingGroup::default()));
    println!("Top entity:\n{:?}", pick_state.top(PickingGroup::default()));
}

Pick Interactions

A InteractableMesh Plugin has been provided that will provide events such as mouse_entered, mouse_exited, mouse_down(MouseButton), mouse_just_pressed / mouse_just_released. You can view the implementations in interactable_cube.rs

Selection State

If you're using the SelectablePickMesh component for selection, you can access the selection state by querying all selectable entities and accessing the .selected() function.

Plugin Parameters

If you're using the built in HighlightablePickMash component for highlighting, you can change the colors by accessing the PickHighlightParams and setting the colors:

fn set_highlight_params(
    mut highlight_params: ResMut<PickHighlightParams>,
) {
    highlight_params.set_hover_color(Color::rgb(1.0, 0.0, 0.0));
    highlight_params.set_selection_color(Color::rgb(1.0, 0.0, 1.0));
}

Debug

You can also enable a debug cursor that will place a sphere at the intersection, with a tail pointing normal to the surface. Just add the DebugPickingPlugin to the App::build() in your Bevy program:

.add_plugin(DebugPickingPlugin)