-
-
Notifications
You must be signed in to change notification settings - Fork 181
Sprite picking support #7
Comments
Would be really nice to have 2D support and be able to pick sprites. |
I think the only way to do this will be with a color picking shader, which is still way over my head. Because sprites don't have a mesh that match the shape of the underlying sprite, I don't think there is any way to use the current ray casting method that won't have problems with alpha and z-ordering. That said, the color picking shader is really the last big thing I want to tackle. |
I did not take a look at the code, but would the approach used for the current bevy ui be feasible? It can correlate the mouse cursor / screen coordinates to the sprite of a button. I'm just thinking out loud and poking around in the dark...so ¯\_(ツ)_/¯ |
This is now working, to some extent, with 2d Ortho cameras. However this still only works with actual meshes. |
Hi there! I am using bevy_prototype_lyon to create a tile bundle: #[derive(Bundle, Default)]
pub struct TileBundle {
pub position: XY<f32>,
pub walkable: Walkable
#[bundle]
sprite: ShapeBundle
}
impl TileBundle {
pub fn new(position: XY<f32>, walkable: Walkable) -> TileBundle {
let tile_size = 108.;
let tile_half_width = tile_size.clone() / 2.;
let tile_half_height = &tile_half_width / 2.;
let transform = Transform::from_xyz(
(position.clone().x - position.clone().y) * &tile_half_width,
(position.clone().x + position.clone().y) * &tile_half_height,
0.
);
TileBundle {
position,
walkable,
sprite: ShapeBundle {
path: {
let mut path = PathBuilder::new();
path.move_to(Vec2::new(tile_half_width.clone(), 0.));
path.line_to(Vec2::new(tile_size.clone(), tile_half_height.clone()));
path.line_to(Vec2::new(tile_half_width.clone(), tile_half_width.clone()));
path.line_to(Vec2::new(0., tile_half_height.clone()));
path.close();
path.build()
},
transform,
colors: ShapeColors {
main: Color::RED,
outline: Color::rgba(255.,255.,255.,0.5)
},
mode: DrawMode::Fill(Default::default()),
visible: Visible::default(),
..Default::default()
}
}
}
} But when I insert the PickableBundle, it throws me a panic:
I just wanted to know if my issue was related to this one? Just to stop to hit my head on a wall haha :) I would love to help but this is definitely out of my knowledge so all I can ask is the basic "any ETA on this one?" Thanks :) |
If lyon is generating meshes, it should work. Note this is unrelated to sprites, as far as I can tell. :) The error you see comes from the mesh not having the If you follow up with this, could you post it in an issue over here: https://github.com/aevyrie/bevy_mod_raycast/issues Thanks! |
Thanks for the details, I don't fully understand all of that stuff works atm. I already had the advice to add PickableBundler after the mesh is initialized, this didn't solve the problem: impl Plugin for GridPlugin {
fn build(&self, app: &mut AppBuilder) {
app
.add_plugin(ShapePlugin)
.add_startup_system(setup.system())
.add_stage("GridStage", SystemStage::parallel().with_system(add_pickable_bundle.system()));
}
}
fn setup(mut commands: Commands) {
commands.spawn_bundle(TileGridBundle::default())
.with_children(|parent| {
for (x, &row) in GridPlugin::GRID_MATRIX.iter().enumerate() {
for (y, &walkable) in row.iter().enumerate() {
if walkable == 1 {
parent.spawn_bundle(TileBundle::new(
XY { x: x as f32, y: y as f32},
Default::default()
));
println!("Spawn {};{}", x, y)
}
}
}
});
}
fn add_pickable_bundle(mut commands:Commands, query:Query<Entity,(With<Walkable>,With<Uninitiated>)>) {
println!("init pickable");
for entity in query.iter(){
commands.entity(entity).insert_bundle(PickableBundle::default()).remove::<Uninitiated>();
}
} The console confirm that I'm adding the I may have found some inconsistency into lyon that could cause the problem, I will investigate furthermore before opening an issue elsewhere. |
I attempted this as well, expecting this to work: use bevy::prelude::*;
use bevy::sprite::MaterialMesh2dBundle;
use bevy_mod_picking::{DefaultPickingPlugins, PickableBundle, PickingCameraBundle, PickingEvent};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(DefaultPickingPlugins)
.add_startup_system(setup)
.add_system_to_stage(CoreStage::PostUpdate, print_events)
.run();
}
pub fn print_events(mut events: EventReader<PickingEvent>) {
for event in events.iter() {
match event {
PickingEvent::Selection(e) => info!("A selection event happened: {:?}", e),
PickingEvent::Hover(e) => info!("Egads! A hover event!? {:?}", e),
PickingEvent::Clicked(e) => info!("Gee Willikers, it's a click! {:?}", e),
}
}
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands
.spawn_bundle(MaterialMesh2dBundle {
mesh: meshes.add(Mesh::from(shape::Quad::default())).into(),
transform: Transform::default().with_scale(Vec3::splat(128.)),
material: materials.add(ColorMaterial::from(Color::PURPLE)),
..Default::default()
})
.insert_bundle(PickableBundle::default());
commands
.spawn_bundle(OrthographicCameraBundle::new_2d())
.insert_bundle(PickingCameraBundle::default());
} But no such luck, currently debugging to figure out why. |
Note that lyon support has been enabled upstream by aevyrie/bevy_mod_raycast#38. The tracking issue for 2d meshes (not sprites) for mod_picking is here: #130 |
Is there any WIP on this, or anyone have an idea how to tackle it? I'm digging around in Do sprites somehow get their quads generated that aren't assigned as a mesh component? |
I'm working on a refactor right now that should make it much easier to do this. There is no ETA, though I'm hoping to get this library upstreamed for bevy 0.9. |
One workaround is to add a mesh to the sprite bundle. For instance, the following works: for i in 0..16 {
for j in 0..16 {
commands.spawn((
SpriteBundle {
texture: asset_server.load("blob.png"),
sprite: Sprite {
custom_size: Some(Vec2::new(16.0, 16.0)),
..default()
},
transform: Transform::from_translation(Vec3::new(i as f32 * 16.0, j as f32 * 16.0, 0.0)),
..default()
},
meshes.add(Mesh::from(shape::Quad::new(Vec2::splat(16.0)))),
PickableBundle::default()
));
}
} Instead of doing fancy shader picking for 2D shapes, you could generate a mesh for your sprite and use that instead. This is analogous to the |
Note that there is now a sprite backend in the This will only check the bounds of the sprite, there isn't really a good way to check the alpha at a specific pixel in an image on the CPU (that I am aware of). This should work with alpha channel once we have GPU picking support in-engine: bevyengine/bevy#6991 |
I'm getting some issues with the sprite backend in the beta branch, it seems to only work with one sprite. As a workaround if you clone the beta branch and comment out backends/bevy_picking_sprite/src/lib.rs Line 60 to disable the focus policy stuff. I imagine this breaks other behaviour though and is in no way a permanent fix but it works for my use case. |
Thanks for the heads up. I'll take a look. |
I think this could be closed as the sprite picking works fine in the currently published version? |
Support picking non-meshes. This is probably just adding an extensible API to #3.
The text was updated successfully, but these errors were encountered: