What I have done is create a special 'background' picking backend which always returns a hit. It's configured to have an order lower than the camera order, so it always comes last: https://github.com/viridia/bevy_reactor/blob/main/crates/bevy_picking_backdrop/src/lib.rs
#bevy_mod_picking
3321 messages Β· Page 4 of 4 (latest)
oh yeah, mouse motion events seems to be what i'm looking for
I think that this wont work because I always click on some mesh. What I want to check if whether that mesh does something on click or not. But I already have a solution in mind now.
Either way, thanks for the help
Hello, any advice about how I should use bevy_mod_picking to resize sprites/mesh2D dragging its edges ? I can't find any example showcasing this, but this crate seems like the perfect solution for that, right?
You could always add pickable gadgets (e.g. small spheres) at the points where you want resizing to happen
If those gadget are only visible when the cursor is close that could get pretty sleek
Ohhh god idea! π€© thx!
im having some trouble getting picking working with avian2d. ive added PickableBundle to the entity that i want to be able to select, DefaultPickingPlugins to my app, and also the "backend_avian" feature in my toml. i feel like theres something small im missing but i have no clue what it is
there is only an avian 3d backend as far as I'm aware
ah i see
making a 2d backend would probably just be as simple as checking for point intersections right
I'm not familiar with avian, but I assume so, yes. It's likely you can copy past the 3d backend and only make small tweaks to get it working for 2d
yup, for sure
and i assume i wouldn't use the raymap right? because that seems to be geared towards 3d raycasts
Not sure, sorry! Sounds right though.
Q: Can you think of a way to make raycasting conditional based on the game state? So for example in flora-painting mode trees are pickable, in terrain sculpting mode trees are not pickable but heightmaps are, etc.
No built in solution. Historically I've either put checks inside the listener, or use one-shot systems to disable the listener component
For raycasting specifically, you can add query filters to the raycast. Depends on the backend though.
Hi, I'm new to picking (and bevy_ui tbh), but I'm a little confused about the behavior I'm seeing. I have a ButtonBundle (with the PickableBundle), and as a child I added a TextBundle (no Pickable). I want to highlight the button on hover and press, so I followed the many_buttons example and used the PickingInteraction component and switched to decide the color. However what I found is that when my cursor hovers the TextBundle, it doesn't highlight the button. I have some padding on my button, and hovering the padding does highlight the button, so it seems like the TextBundle is blocking the cursor even though it's not pickable.
Is this expected behavior? Do I need to add some sort of "ignore picking" component?
I also have a press event on the button, and it is triggering correctly even when I click through the TextBundle, so perhaps this is a problem isolated to PickingInteraction?
OK NEVERMIND I FOUND Pickable::IGNORE, NOW GO AHEAD AND IGNORE ME π
i think theres a "block below" field or something along those lines u could use too.
I think the other thing you can do is let the events bubble to the button. When you hover over the text, events sent to the text (target) that don't get handled bubble to the button (listener)
Yeah but that doesn't apply to the PickableInteraction. I could have probably worked around this by handling the particular events yeah
For another question, how would I handle a click that doesn't hit any pickable objects? For example, I might have an RTS UI where I can pick which building to place, but if clicking into the game world I want to trigger my own building placement code or something
I did find the implementation of bevy_picking_selection which seems to do this, but requires iterating through three different press events to figure out which presses have been handled π
why would the game world not be pickable
The text bundle itself is absorbing the hit.
https://docs.rs/bevy_mod_picking/latest/bevy_mod_picking/backend/prelude/struct.Pickable.html#structfield.should_block_lower
I'm picturing a 2D game where the background assets might not make sense to make pickable? I mean I suppose you could, so maybe that's the answer?
I mean, if you want to pick it, then it should be pickable. π
The weird part is I'm not trying to pick the background in particular (e.g., if there are multiple entities that compose the background). I just want to know if I missed everything I care about so I can run my custom code
Maybe then I should be marking my background with a Background component π
if clicking into the game world I want to trigger my own building placement code
sounds like you are describing "when I drag a building and drop it on the background, run some code"
the Pointer<Drop> event seems like exactly what you would want here, it tells you the entity being dropped, and the entity it was dropped on.
Not quite. If i'm playing an RTS, I don't want to drag my structure icon and then drop it into the world. I usually want to click the ui once to select which building to place (or press a hotkey), and then click again in the game world once I've placed the "ghost" structure properly
Ah, gotcha. Then it seems like you want to be able to click the game world, and track what building is currently selected. Either way, seems like you want the world/map to be pickable.
I agree for 3D games, I think that makes sense there. But for 2D, I think this makes less sense? Like if it's a side scroller like Terraria, It doesn't make as much sense to me to say the parallax background is pickable, and the tiles are pickable and anything else in the background is pickable. I'd rather just have them all be non-pickable, detect that and then do my "tile math" or whatever to figure out what tile to place or break or whatever
I hope this isn't coming across too negative, I am interested to understand how you approach this since I'm new to picking π
If you want to interact with this stuff with a pointer, why wouldn't you want it to be pickable? Pickable doesn't mean it highlights, selects, takes focus, etc, etc, it just means you get events with pointers.
detect that and then do my "tile math"
That just sounds like hand rolling your own picking thing. π
I think the thing that bothers me with the pickable component approach is that I have to remember to put it on everything even if I don't care to interact with that particular object. I never want to interact with parallax backgrounds, but if I want to use this approach, I need to add it there just so Pointer events are sent (which I can then filter through an EventReader).
As for the "tile math" thing, my concrete example is I have an object that is say 2x2 tiles wide. I want the cursor to be "rounded" to tiles, not floored. So picking a particular tile would not be desirable, since that would make the placed object be "skewed" relative to where the mouse is.
Unless I just do the "tile math" inside the pointer event handler, but then the actual entity I picked isn't relevant.
You don't need any components for picking to work. Pickable is entirely optional. π
But for 2D, I think this makes less sense
It's the same logic that is used for interacting with 2D UI. E.g. "if the user clicks on this 2D surface, run a system". You don't just want to know what coordinates the user clicked on, you want to know that the click wasn't blocked by something in front of it.
Hi! I have some ImageBundles that I'd like to drag, but they have transparency. My solution was returning in the On<Pointer<Drag> callback before changing the position of the ImageBundle, but this doesn't actually stop the drag event, so if the mouse moves over a non-transparent part, the ImageBundle is dragged without a new event
Recording a video to show
ignore the crash, that's a differnet issue
The backend needs to be updated to support transparency.
This would be in the sprite picking backend iirc
Hmm, this should be in follow-up work for upstreaming the sprite backend, I'll go add that
And not bevy_ui?
Oh, I thought you were just using sprites.
In that case, yes, it would need to be added in the bevy_ui backend.
Got it, thanks
hey! i use EventReader<MouseWheel> to zoom in my game. is there an easy way i can use mod_picking for the mouse wheel so that when im interacting with a scrollarea the wheel events arent passed through?
Yes! You can look up which entity the cursor is hovering over using the HoverMap
that works ty!
Once input management is upstreamed this sort of interaction with the (newly upstreamed picking) will probably be pretty common and painless.
very excited for that :D
I have an invisible parent entity with several PBR child entities. Currently I added PickableBundle on the parent entity. Now the child entities can be hovered, but no select event is fired on them. How to fix this?
hovering and clicking work just fine (the event gets fired for the child entity which has no PickableBundle, which is fine since I can just iter_ancestors)
but the select event never gets fired, no matter which entity I add the select hook on
Hello. I'm trying to add the drag and drop functionality to some entities. I have the Avian backend. When I add On::<Pointer<DragStart>>::target_insert(Pickable::IGNORE) to the entity an error says that Pointer should be <dyn Pointer>. Adding dyn then says dyn isn't implemented.
I'm not sure what I'm doing differently than the drag_and_drop example. The example doesn't need dyn.
update: I was importing std::fmt::pointer, not the picking pointer
this was an id10t error
bump
it sounds like a bug
I don't know how hierarchies are supposed to work with mod picking, but the inconsistent behavior between hovering and eslection sounds like a bug
I'm not sure I understand the issue.
basically I have entities like this
parent = spawn((
SpatialBundle,
PickableBundle,
On(Pointer<Over>), On(Pointer<Out>),
On(Pointer<Select>), On(Pointer<Deselect>),
))
child = parent.with_children(|b| b.spawn((
PbrBundle,
)))
when I hover over the child, the parent receives the Over event, but when I click, it doesn't receive the Select event
How can I make clicks pass through?
I'm developing a building system where I move objects based on a tilemap. The issue is that the building preview is a 2D sprite, which interferes with hovering over the tiles behind the sprite. For example, if I have a large building that occupies a 3x3 area, and I want to move it by one tile, I can't do that because the tile is obscured by the sprite
On::<Pointer<Over>>::run(
move |_: Listener<Pointer<Over>>,
mut preview_query: Query<(&mut Transform, &PreviewBuilding)>,
tilemap_query: Query<(
&TilemapGridSize,
&TilemapType,
&GlobalTransform,
)>| {
let (grid_size, map_type, tilemap_transform) = tilemap_query.single();
let world_pos = tile_pos.center_in_world(grid_size, map_type);
if let Ok((mut preview_transform, preview_building)) =
preview_query.get_single_mut()
{
preview_transform.translation = tilemap_transform
.transform_point(world_pos.extend(10.0))
+ preview_building.offset.extend(0.0);
}
},
),
Take a look at the pickable component. You can make picks pass through or be ignored completely
Is there a supported way to pick quadrilaterals (or a collection of intersecting lines) better than manually defining a TriangleList mesh made up of multiple triangles?
If I have a drag listener and I want to drag an object, what's the correct way to do that? Using the examples in the repo, I'm running into issues, since I allow zooming my camera. When I zoom the camera, the delta field no longer corresponds to world units.
This seems to be a limitation of the ListenerInput or Pointer events. They don't expose the camera that produced the hit.
As a workaround I can just look up my one camera, but in a multi-camera set up, that would not work
I'm getting Ord violation panics at this line: https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/backends/bevy_picking_sprite/src/lib.rs#L56-L61
I confirmed that it's because z is NaN and smallsort expects the comparison operator to be correct:
// We now should have consumed the full input exactly once. This can
// only fail if the comparison operator fails to be Ord, in which case
// we will panic and never access the inconsistent state in dst.
if left != left_end || right != right_end {
panic_on_ord_violation();
}
I'm surprised that Bevy lets me make a transform which is invalid in the first place, but nevertheless, is this something that should be fixed in bevy_picking_sprite to avoid comparing NaNs, or should this panic as it does and leave it up to callers to make sure they never set invalid transforms? I note that this has been upstreamed so would need to be fixed there actually: https://github.com/bevyengine/bevy/blob/b45d83ebda8f4956f59fa30cc6f03f5c11fc494f/crates/bevy_sprite/src/picking_backend.rs#L46-L51
Simply ban NaNs in floats π€
Getting an ordering issue due to bubbling π
So let's say there's an entity like this:
On::<Pointer<Over>>::run(/* set special bg color */),
On::<Pointer<Out>>::run(/* reset to default bg color */),
And let's say the entity contains children.
- Hover over a child.
- Event bubbles from child, triggering
Pointer<Over> - Move cursor over to the parent, away from the child
- Event bubbles from child, triggering
Pointer<Out> Pointer<Over>is triggered on parent
The issue here is that step 4 and 5 is not deterministic. If they are ordered like above, it works fine. But sometimes step 5 is triggered before step 4, causing the bg color to stay reset.
I guess it's kinda futile to mull over this since the bubbling mechanism is already replaced by an upstream solution. But I wonder if the upstream version suffers from the same issue.
It does, I think. But this can be fixed.
Or⦠actually
Over always precedes out now, within a single frame.
The new ordering is explained here: https://dev-docs.bevyengine.org/bevy/picking/prelude/fn.pointer_events.html
Iβll have to take a sec to look into this more. If you get the events on the same frame it will always be Over-parent then Out-child. If you get them across two frames (which could happen because we do a 2-frame diff for these events) then it will always be Out-child then next frame then Over-Parent.
Either way it should be deterministic in bevy_picking
Well, I guess it's technically deterministic but over->out wouldn't produce the desired result in this case. I think I'll test main myself later on.
when i wrote the ordering, I fired over first and out last, and put all the other events between. The reason for this is that you do want to receive Over before stuff like DragStart, and you do want to receive stuff like DragDrop before Out.
Because of how mod_picking works, we don't actually know when the transition between picked entities happens relative to the other events, so we just kind of have to pick something that makes sense.
Within a single frame, we can't have out precede over unless we want to break another case. Which is why I am sort of hoping that multi-frame stuff can sort this out.
I don't think it does though.
Until we do a significant refactor (to allow a pointer to exist at a sequence of locations within a single frame) you will have to hack around over->out.
I've got what I think is an ordering ambiguity: #1034547742262951966 message Basically I think lwim is resetting action states immediately after mod_picking is setting them. I don't know exactly which system set to order after lwim... I was thinking I could just do all of them, but that seems wasteful
Is there a specific set I could order lwim's action resetting against to make sure the handler gets called after? My first thought was EventListenerSet
Hello, I was wondering if anyone could help me with this (I'm kind of new to rust, bevy and bevy_mod_picking).
I'm trying to spawn a grid of cubes and whenever you click on a cube a bevy event gets sent containing the position of said cube. I'm not sure if this is the most correct or efficient way of doing it, so any advice would be really appreciated.
Here is my (not working) code so far:
level.pos_iter().for_each(|(pos, _tile)| {
println!("New tile at: {} {}", pos.x, pos.y);
commands.spawn(
(
PbrBundle {
transform: Transform::from_translation(Vec3::new(pos.x as f32, 0.0, pos.y as f32)),
mesh: meshes.add(Cuboid::new(0.9, 0.9, 0.9)),
material: materials.add(Color::srgb(1.0, 0.0, 0.0)),
..default()
},
On::<Pointer<Click>>::run(move || {
evw_handle_click.send(HandleClickEvent(pos));
})
)
);
});
If you need any more info on the code please let me know!
This approach should work fine but you can create an event and make it creatable from a mod_picking event. Then you could add a handler that looks like On::<Pointer<Click>>::send_event::<HandleClickEvent>()
What's not working about the code?
This works however I'm unable to pass the pos variable because it is outlived by the On:: call and I need to send said data with the event
You probably want to be querying for the current position of the cube within the callback system, and send that in the event.
Thanks, that helped me get what I wanted!
One more question if you dont mind. How can I perform two actions with one event listener? In my case I have inserted th following components to an entity:
On::<Pointer<Click>>::commands_mut(|event, commands| {
// Some code...
}),
On::<Pointer<Click>>::send_event::<HandleClickEvent>()
This produces an error saying that On::<Pointer<Click>> can't be duplicate.
You would use On::run, and put all the logic in there
commands_mut and send_event are just sugar and use On::run under the hood
It's equivalent to having two systems and combining them into one
Got it to work, thanks for your time :D
is it possible to make middle/right mouse button not trigger interaction?
Yes you can get button pressed from event
I can send an example later away from computer atm
I'm kinda micromanaging the Interaction component for specific interactions and I prefer not to use bevy_mod_picking's events
impl From<ListenerInput<Pointer<Down>>> for FleetClicked {
fn from(value: ListenerInput<Pointer<Down>>) -> Self {
FleetClicked {
entity: value.listener(),
button: value.button,
}
}
}```
#[derive(Event)]
pub struct FleetClicked {
entity: Entity,
button: PointerButton,
}
If this code doesn't give you the example you need then I will need to see what you are doing
for event in fleet_events.read() {
if event.button != PointerButton::Primary {
continue;
}
//And so on
}
Yeah events probably work but I really like working exclusively with PickingInteraction, since working with states is the better ECS pattern imo.
Fair enough I wouldn't know how to do it that way though
Anyway if I want to make a PR for this, do I do it on bevy_mod_picking or directly to the upstreaming process? Hasn't kept up with 0.15 development.
hello, whats the "refresh rate" of pointer event for bevy ui ? i have a grid of square, and a pointer<dragover> but when i move diagonally is misses a lot of times a grid item it has dragged over because the mouse was only briefly in a corner of the adjacent tile.
thanks ! i can do a demo if my explanation isn't clear
FYI for multi-line comments you can use ```rust and then a newline, ending with another ```
Thanks
Can also use ```rs shorthand
Heya!
I'm trying to use the drag events, but I noticed that while DragStart contains a HitData, the Drag and DragEnd events do not. While I'de love to use the HitData.position property while dragging, or at least have access to a worldspace ray, to determine where i'm dragging to in world space.
I could query for the right Camera that matches the pointer_location, and determine the ray again in my eventhandler system, but it seems like a dirty fix, as if i'm overlooking something.
what would be the best solution?
There is no gaurantee that the pointer will be hitting the target after you start dragging. It means that the pointer was hitting an entity when a drag started.
The only information you have is the drag delta as the pointer moves after it starts dragging an entity
If you want to know a world space position, you can look to see if the pointer is hitting anything while it is dragging.
But you are also not gauranteed to be hitting anything.
Is there a way to disable and enable pointers? I want to switch back and fourth between a virtual pointer (middle of the screen crosshairs) and the mouse pointer depending on the game state (i.e. UI vs in-game).
Or do I need to manually despawn and respawn the pointers?
I don't fully understand the use case, but can you just swap the PointerId component out on the entity?
I have picking events with a virtual pointer while in-game using the rapier backend. And also UI picking using the built-in mouse PointerId so I have two separate pointers in this case.
So you suggest querying the the PointerId::Mouse component and removing it when I'm not in a UI state and want to ignore the normal mouse pointer? Would that cause issues since they are normally spawned automatically?
You might need to customize that spawning logic. It sounds to me like you really just want a single pointer, but change whether it is driven by the mouse or locked to the center of the screen.
I was thinking you wouldn't remove it, just swap the same pointer entity between mouse and virtual pointer id
Hmm I'm also "changing" the backend though. With the virtual pointer I only care about meshes and want to ignore any UI elements or HUD elements
Might be a nice feature to add in the upstreamed version, being able to just disable a pointer's ability to interact seems handy.
Another option would be to customize the backends you are using to query for some pointer enable/disable component
I could also use require_markers and swap which elements are tagged on state change right?
Sure
Hmm nevermind I guess Bevy UI doesn't have that feature, only rapier and raycast, etc.
Anyways thanks for the ideas! I'll poke around more tomorrow.
This line here says "[DragEnd] Fires when a pointer is dragging the target entity" https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/crates/bevy_picking_core/src/events.rs#L144
But where is this behaviour actually implemented? Because if I search the whole repository for for "DragEnd", I only see an an example and the struct. https://github.com/search?q=repo%3Aaevyrie%2Fbevy_mod_picking DragEnd&type=code
I expected some code where all these events are "fired()" at the right time.
On::<Pointer<Down>>::target_commands_mut() is there a non mutable version I just want it for logging transfroms
I'd check the docs. If not, it won't make a difference anyway. You can also use On::run
How would one use bevy-inspector-egui combined with mod_picking, and have mod_picking not register an event when the mouse is over the inspector UI?
I can see the backend_egui feature, but that seems to do the opposite? But even if I don't enable that feature, a click in the inspector window still cascades down to whatever bevy UI element is below the inspector.
I suspect this is a bug / integration issue in bevy-inspector-egui. You want to configure those surfaces to not get picked somehow
That is what the egui backend is for. The examples should demonstrate this. The issue you are seeing is likely to do with the fact that neither bevy_ui nor egui use the Camera abstraction, so there is no good way of ordering them.
@marble pine this is why I want bevy_ui to explicitly be tied to a camera. Implicit ordering is a bit of a nightmare.
e.g. magically attaching the ui to a 3d camera makes no sense because you lose all control over where the UI is rendered, and you now have two entirely different behaviors depending entirely on how you happened to spawn your UI root.
It also makes the picking integration hacky. We add a 0.5 offset to the camera to make this function, but again, it's working around the UI being implicit (sometimes!)
Just give me a UiCamera and let me order it relative to every other camera.
Yeah, I think that the previous change was a mistake
Worth trying but...
I generally think all entities should have the same camera semantics. E.g. if you add a mesh with no 3d camera, well, nothing will render. Why should UI entities be any different? You don't see users complaining about DX because bevy doesn't auto-spawn a 3d camera when a mesh is present.
And we have a tool for picking what camera sees what entities: renderlayers
#ui-dev?
Changing the behavior across entities just makes learning harder, more concepts to do the same thing
I've already beat this drum and cart shot it down for DX reasons I disagree with. Not sure I can really do much tbh
Understood. So thereβs no solution to this atm?
You can fork the egui backend, and set the order to be higher than the hardcoded order used with bevy ui.
At least, that should do it
Maybe you could spawn a transparent UI node with a high global zindex at the same position as the egui panel to block any click events from reaching any other bevy UI elements
Ah, you know
the issue is probably that your UI interaction code is not using the picking primitives, which do respect the layer stuff
You might also need to make sure bevy_ui's built in focus system isn't also running.
This should all work correctly in the next version of bevy, assuming the code for Interaction is using the new picking stuff
Which primitives? The UI interaction purely used mod-picking logic.
I was thinking you might be using Interaction, and bevy uis built in focus system is obliterating the mod picking stuff
I'd use the debug pointer to see what entities are hovered. Our should just be egui when over egui
I checked (btw, I have a white background, it would be awesome if I could change the debug text to black), it's hovering my UI elements behind the inspector.
(doesn't matter if I enable backend_egui or not in this case)
Hello, Im testing minimal_2d.rs, But I have no idea why it not work.
I'm using ldtkentity to spawn PickableBundle
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, Component)]
pub struct PlaceAble;
#[derive( Default, Bundle, LdtkEntity)]
pub struct PlaceAbleBundle {
struct_id: PlaceAble,
pickable: PickableBundle,
}
And insert event for it:
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, Component)]
pub struct PlaceAbleEvent;
fn add_events(mut commands: Commands, q_placeable_rntity: Query<Entity, Added<PlaceAble>>) {
for e in &q_placeable_rntity {
commands.entity(e).insert(
On::<Pointer<Click>>::run(|| info!("I've been clicked!")),
);
}
}
The weird thing is that when my old hover function system is running, it works fine
My old system:
#[derive(Debug, Default)]
pub struct PlaceablePlugin;
impl Plugin for PlaceablePlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, ( hover_placeable, touch_placeable, add_events));
}
}
fn hover_placeable(
mut commands: Commands,
q_window: Query<&Window, With<PrimaryWindow>>,
q_camera: Query<(&Camera, &GlobalTransform), With<Camera2d>>,
q_transform_placeable: Query<(Entity, &GlobalTransform), With<PlaceAble>>,
) {
let (camera, camera_transform) = q_camera.single();
let window = q_window.single();
if let Some(world_position) = window
.cursor_position()
.and_then(|cursor| camera.viewport_to_world(camera_transform, cursor))
.map(|ray| ray.origin.truncate())
{
for (entity, placeable_trans) in &q_transform_placeable {
let distance = world_position.distance(placeable_trans.translation().xy());
if distance < 32. {
commands.entity(entity).insert(Hover);
} else {
commands.entity(entity).remove::<Hover>();
}
}
}
}
It's Output:
2024-10-29T06:01:34.002674Z INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Windows 10 Pro", kernel: "19045", cpu: "Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz", core_count: "4", memory: "32.0 GiB" }
2024-10-29T06:01:34.456198Z INFO bevy_render::renderer: AdapterInfo { name: "NVIDIA GeForce RTX 2070 SUPER", vendor: 4318, device: 7812, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "560.94", backend: Vulkan }
2024-10-29T06:01:35.262070Z INFO bevy_winit::system: Creating new window "KautismTD" (Entity { index: 0, generation: 1 })
2024-10-29T06:01:38.278550Z INFO tdrpg::placeable: I've been clicked!
2024-10-29T06:01:38.919977Z INFO tdrpg::placeable: I've been clicked!
2024-10-29T06:01:40.240954Z INFO bevy_window::system: No windows are open, exiting
2024-10-29T06:01:40.249371Z INFO bevy_winit::system: Closing window Entity { index: 0, generation: 1 }
Because I planned to replace the old system with bevy_mod_picking, but it failed.
I remove old system:
- app.add_systems(Update, ( hover_placeable, touch_placeable, add_events));
+ app.add_systems(Update, ( touch_placeable, add_events));
I didn't even know what I did wrong.
OK, I know. This entity do not contains sprite so mod_picking dont know how to click it.
Can i using avian2D as backend? I didn't see any example code for avian 2D, avian.rs seems is avian3d.
@novel hamlet any way to temporarily disable all picking interactions?
If so, I could use Egui's wants_pointer_input to check if bevy-inspector-egui is being used, and disable any picking logic until it is needed again.
Ah, I found InputPluginSettings, looking into whether that's what I need
Yes, that worked. Here's the system I added to fix my issue. I'm sure it can be improved, possibly with a run condition.
// Disable picking when the inspector is active.
fn toggle_picking(
mut ctx: Query<&mut bevy_inspector_egui::bevy_egui::EguiContext>,
mut input: ResMut<bevy_mod_picking::prelude::InputPluginSettings>,
) {
if ctx.single_mut().get_mut().wants_pointer_input() {
input.is_touch_enabled = false;
input.is_mouse_enabled = false;
} else if !input.is_touch_enabled || !input.is_mouse_enabled {
input.is_touch_enabled = true;
input.is_mouse_enabled = true;
}
}
That's basically what the egui backend does
Hmm, looking at that backend now, but it's using it in the other direction, right? E.g. it's using wants_pointer_input to actually register interactions inside egui windows?
I want/do the inverse: disable interactions when over an Egui window (since the interactions don't happen on the inspector window, but happen on the underlying bevy UI nodes).
And for anyone interested, here's how to change the color of the debug text (when using bevy_ui):
fn update_picking_debug_color(mut pointers: Query<&mut Text, With<PointerDebug>>) {
for mut text in &mut pointers {
for section in &mut text.sections {
if section.style.color == Color::WHITE {
section.style.color = Color::BLACK;
}
}
}
}
When I insert hover (a class I created myself), I hope it has an animation, but since this animation is a child element, it seems that a large number of Over Events are triggered every time the animation is played.
Is there any to let the plugin to know which entity do not trigger by child?
Ok, I know, i using worng function to do that. Shouldnt using target_insert, use listener_insert instead.
No, that's what it does. If egui is using the pointer, it registers a hit at a high order, blocking any hits on lower orders.
You can see this working in the example
@novel hamlet I see. So do you have any idea why, when enabling bevy_egui as a feature, it still registers hits for the bevy_ui elements below the egui window?
It means that either the order for egui hits is higher than bevy ui, or the egui plugin isn't running
@novel hamlet I'm having an issue where respawning UI in the Update schedule causes bevy_mod_picking to not run the callback system. I've tested this with a simple UI with a single buttton that gets respawned every frame and verified it will never trigger any callbacks.
This is surprising to me because from reading the code all the bevy_mod_picking systems happen in PreUpdate. Thus, if the user clicks it should only care about what exists at the current point on that frame and the fact that it is despawned later that frame shouldn't matter, right? I'm probably missing something as to why this breaks.
Here's the minimal system that reproduces this (running in Update):
fn render_system(mut commands: Commands, node_query: Query<Entity, With<Ui>>) {
if let Ok(entity) = node_query.get_single() {
commands.entity(entity).despawn_recursive();
}
commands
.spawn(NodeBundle {
// Root node with styles, etc.
})
.insert(Ui)
.with_children(|children| {
children
.spawn(ButtonBundle {
// Button with basic style and background color.
})
.insert(On::<Pointer<Click>>::run(move || warn!("Hello world!")));
});
}
I do see this comment on bevy_picking_egui (https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/backends/bevy_picking_egui/src/lib.rs#L31) which is immediate mode API that seems to be a work around for a similiar issue. But I don't understand why that is needed -- if it runs in PreUpdate why doesn't it just detect hits for the UI spawned on the previous frame? It also isn't a solution for Bevy UI since the backend depends on ViewVisibility which is computed in PostUpdate (i.e. I can't just spawn immediate mode UI in PreUpdate).
Callbacks are executed by bevy_eventlistener
To be frank, I don't really have the wherewhithal to debug issues like this. All effort has gone into upstreaming this plugin to bevy, and switching from eventlisteners to bevy's observers. There have been a number of fixes and improvements made during the upstreaming, the existing plugins will be put on life support.
No expectation to debug! I was just curious if top of mind you understood why it was broken since you wrote the comment for egui.
The event listener set that is executed by bevy_eventlistener is configured to be also run in PreUpdate after all the picking set systems so I don't think that would explain it.
Click and other events rely on the entity being the same. If you are respawning, the entity id will change
e.g. a click is a mouse down and a mouse up on the same entity
I suspect this would work for pointer down events though
Ohhh, snap. That's probably it. I was not remembering Click was down and up. I might just switch to pointer down then. Thank you!
Yep you were spot on. Down does indeed work. Up and Click do not. I wonder why Up doesn't.
I think up is "hovered and down last frame, hovered and up this frame"
Not sure about that though
Gotcha, thanks again!
Either way, most of that stuff has been revamped for the observers version in 0.15
i havent been paying attention, but will i be able to use observers to react to bmp events in that version?
Yep, it's observer-backed
oops, dont mind the drool on the floor. Il clean that up... π§Ή (i hope that doesnt come off as weird π )
hey ! is there a way of having the DragOver event trigger even when the target is the dragged entity ? like dragging the entity on self (i want to know if the dragged entity passed through itself again, so reset a pathing)
thanks !
What do you mean by drag an entity onto itself?
You could check what is under the pointer during drag events maybe?
like the mouse cursor which started the drag event while dragging goes back to the entity that first started being dragged. i dont move it, so its place remain fixed.
thanks for the idea and response ! ill do that with the HitData, but its more cumbersome
Hello, why does my drop event not trigger correctly? It seems random, and I can't even figure out its regular pattern.
it looks like the object you are dragging is also pickable, and is blocking from dropping things underneath
From example:
https://github.com/aevyrie/bevy_mod_picking/blob/7494b9614a50a9c25e77a9bdccdb9c010a506ae9/examples/drag_and_drop.rs#L40
Because of the uncertain order, when I re-insert the pickable object, the event will still be prevented from being generated.
I change this object to:
.insert(Pickable{
should_block_lower: false,
..Default::default()
})
It seems work good but have another issues:
Sometimes it trigger double drop event
I add a checker to prevent this but not work, it only blocks part of events
fn drop(
mut commands: Commands,
event: Listener<Pointer<Drop>>,
bultinassets: Res<BultinAssets>,
) {
info!("Drop");
if event.dropped == event.target {
info!("Skip Drop!");
return;
}
I record another double drop:
OK, Not this
It seems i move insert Pickable::IGNORE prevent this bug.

It's my fault. I use wrong with<> in query.
Hi guys, I've been playing with the example minimal_2d, but seems like it doesn't work.
Is the example outdated?
I tried bring it to main as well, and it still doesn't work
It looks like bevy_mod_picking doesn't have a PR for 0.15. Is this in the works, or should I take it up? I understand a lot of picking has been upstreamed, but many of the backends (including sprite backend) is still missing.
At the very least when 0.15 drops, there should be a migrations strategy, even if it's a hacky mid-way between the upstreamed stuff and the non-upstreamed code.
Ah awesome! Thank you
there is a sprite backend: https://github.com/bevyengine/bevy/blob/main/crates/bevy_sprite/src/picking_backend.rs
Oh maybe this is new? It's not in bevy 0.15.0-rc.3
Or maybe not publicly visible
This should be public in the RC
Can you double check then open an issue?
It might not actually be necessary now that I think about it. If it's always added through the SpritePlugin, that is probably fine
If you are on the latest version, I just realized today there are newer releases of bevy_egui, and picking is behind
It's likely you are just on a more recent version than mod_picking supports
Aha. Should Picking perhaps limit the versions of egui it supports? Or is this all moot now that picking is being upstreamed?
It does limit the version, problem is that there is nothing stopping you from adding multiple versions to your project
If anything I need it to support multiple versions, which I have done in the past. Problem is that there have been breaking changes to egui that mean the code is not cross compatible
@novel hamlet Hi, i woke up to some compiler issues this morning and looks like i got that sorted (had to clear cargo cache and disable cranelift). Since last night i have not changed any of the code, but picking events dont seem to be firing now. Can u give me a checklist list of things to look for? The events are being registered by the app. The Pickable and On<x> components are also there. I have a button that uses picking as well and it seems to be working fine, so its not app wide.
that sounds like a version mismatch to me
cargo tree -i bevy_mod_picking
try with a few related crates to find if you have any duplicate deps
or just cargo tree -d I think, but there might be a lot of noise.
If it works for a button which picking events aren't working?
Over, Out, Down and Up are working. Right now im looking into why DragStart is not working, but the other drags could be broken too for all I know.
The version im getting for the first command: bevy_mod_picking v0.20.1, which is the version id expect to have
Im on bevy 0.14.2
right, but for what kind of entities
the events all use the same resource to fire, so if one works, they all work
I'd be interested to know if any subcrates are duplicated
or egui if you have that
So i ran the other command to get the big tree, bevy_mod_picking v0.20 shows up 20 times in the output
you're looking for the same package with different versions
they're all bevy_mod_picking v0.20.1, so i guess we're good there.
egui is also fine
This might be a complicated answer actually. And im not even sure if im answering ur question...but I made bunch of structs that look like this:
#[derive(Event, Debug)]
pub struct OnButton<E: Debug + Clone + Reflect>(pub ListenerInput<Pointer<E>>);
impl<E: Debug + Clone + Reflect> From<ListenerInput<Pointer<E>>> for OnButton<E> {
fn from(event: ListenerInput<Pointer<E>>) -> Self {
Self(event)
}
}
I forgot why i did this tbh, but i did it early on when i first discovered the crate in order to reduce some boilerplate. I have one for each type of "thing" that needs to be pickable, and its worked fine ever since so i haven't reconsidered this. I register the event like so .add_event::<OnButton<Out>>() and then add On::<Pointer<Out>>::send_event::<OnButton<Out>>() on the button in question. The thing that isnt working is the OnCard one for my cards (its a card game). So really its just the name of the struct thats different, everything else is the same.
I meant "what kind of entities are you picking". It sounds like bevy_ui only?
At this point, all I can think of is a breaking change in mod_picking 0.20.1, if you were on 0.20.0?
But that was released 4 months ago, so I'm not really sure what to make of this other than a local issue. The compiler issues you mention are a bit suspicious.
Ah sorry. Im working with SpriteBundle and MaterialMesh2dBundle
I don't think those have been touched recently
i actually tried 0.20.0 but that didnt change anything
There are still some debugging steps i wanna try later, but thanks for trying π
At this point I would look at the HoverMap to see what entities are being hit tested successfully. The events and listeners you are working with are all derived from that resource, for the most part. Things like drags and clicks are just looking at hits in the hover map, and pointer inputs, to determine when to send events.
Made some progress from looking at the map. I noticed that it wasnt hitting the thing i was expecting, so i put a bunch of Pickable::IGNORE on them. But now im getting no hit data, so its like the cards (MaterialMesh2dBundles) are not even there.
MaterialMesh2dBundle {
mesh: Mesh2dHandle(meshes.add(Rectangle::new(CARD_WIDTH, CARD_HEIGHT))),
material: color_materials.add(Color::NONE),
transform,
..default()
}
the pattern im seeing is that the SpriteBundles work, but not the Mesh2d
I just discovered PickableBundle...
So I tested the Mesh2d from the minimal 2d example and it does not show any hit data in the map
I could just drop Mesh2d all together, i guess, but this aint cool lol
How should I make the tooltip/popup show in full when the cursor is close to the edge? As shown in the screenshot, the rest of the text are truncated/off-screen.
Is it possible to display the Name of the Mesh(PbrBundle) in the tooltip?
commands.spawn((
// vvvvvvvv show this name so that I can identify the meshes easily.
Name::new("Original"),
PbrBundle {
mesh: shape,
material: materials.add(Color::from(GREEN)),
..default()
},
Shape,
));
I am seeing similar. If I clone the repo and run minimal_2d.rs I do not see the entity detection in debugging. Other examples like sprite.rs and event_listener.rs are working for me so it does seem like MaterialMesh2dBundle are an issue
Ty for letting me know. Maybe in 0.15 it will just go away π
I migrated from bevy_mod_picking to bevy_picking, but noticed that the debug UI (the one that follows the mouse) wasn't upstreamed. I find it extremely useful (especially the part that tells me which UI node is the one being pointed at), and plan on porting it over in my own app just so that I can get that feature back.
Before I do so, anyone else already has something similar to share?
If you end up porting this, consider PR'ing it to Bevy as an example please π
Or drop it in the bevy_editor_prototypes repo
Hi I upgraded to 0.15 and I get an error on this:
*on_click = On::<Pointer<Click>>::run(|mut commands: Commands| {
commands.disconnect_client();
});
saying that the closure is not a valid system
I'm not entirely sure what's wrong, any ideas?
oh it hasn't been migrated to 0.15
Is it going to be upgraded or I should use bevy_picking?
Is there a guide to migrate to bevy_picking? the 0.14->0.15 migration docs don't have much
You should try to migrate
@buoyant escarp didn't you write a big guide on the migration? Where did that end up?
yes; i have 90% of the 0.15 upgrade for picking done too, i've just not been able to allocate time to finishing it up
let me find that doc
Actually i figured it out; i like the new observer-based approach
Did you end up migrating this? It'd be super handy
I'm having this issue too. MaterialMesh2dBundle and ColorMesh2dBundle do not work since migrating to 0.20.1 from 0.17.0. Anyone know why? π
This is probably not directly a problem with the picking.
BUT I have a system I want to run in the PreUpdate schedule, after picking has distributed the pointer events. and trying to add it with the line:
// build the plugin
fn build(&self, app: &mut App) {
...
app.add_systems(PreUpdate, PointerTools::update_tools).after(events::pointer_events)
I get this error when trying to compile:
67 | pub struct App {
| -------------- doesn't satisfy `App: SystemSet` or `App: bevy::prelude::IntoSystemSetConfigs`
|
= note: the following trait bounds were not satisfied:
`&mut App: SystemSet`
which is required by `&mut App: bevy::prelude::IntoSystemSetConfigs`
`&&mut App: SystemSet`
which is required by `&&mut App: bevy::prelude::IntoSystemSetConfigs`
`&mut &mut App: SystemSet`
which is required by `&mut &mut App: bevy::prelude::IntoSystemSetConfigs`
`App: SystemSet`
which is required by `App: bevy::prelude::IntoSystemSetConfigs`
`&App: SystemSet`
which is required by `&App: bevy::prelude::IntoSystemSetConfigs`
How should I go about specifying this ?
Thanks !
BTW Happy new Year π
.after should be on the update_tools system
You are calling it on App
Just need to move it inside the )
the ?
there is no update_tools ( string search ) i the bevy source tree.
whet is 'the )'.
?
Thanks π
Hmmm - I tried this and it compiled.
Understaning it though ( brain compiling ... ) π
PointerManager::update_tools.after(bevy::picking::events::pointer_events))
update_tools is a function - do functions have default impl "methods" ? what is it looking for for "after".
Ok - starting to see - an added Trait generic which gets "passed" the type of the "pub fn(some queries)" for a system as the type (implicit) self of has the before, after, etc things that "configure" a "system entry" somewhere adding associated stuff associated with it.
app.add_systems(PreUpdate, PointerTools::update_tools).after(events::pointer_events)
is calling after() on the output of add_systems(), which is App.
However, after() is a method you use to order systems. It is probably more clear when formatted like this:
app
.add_systems(PreUpdate, PointerTools::update_tools)
.after(events::pointer_events)
vs.
app.add_systems(
PreUpdate,
PointerTools::update_tools.after(events::pointer_events)
)
So I see it as ".after(some system)" as a "method" on "update_tools" which is defined in a Trait as a "generic"
pub trait IntoSystemConfigs<Marker>
where
Self: Sized,
{
...
fn after<M>(self, set: impl IntoSystemSet<M>) -> SystemConfigs {
self.into_configs().after(set)
}
...
}
The syntax makes it look like .after(xx) is syntactically an impl "method" on the "system" function update_tools. What it looks like is the "self" in .after then has the type (and address of) of the update_tools (system/function) and registering the type as a system and setting it's config values ( mapped somewhere to the type in into_configs I guess ) .
Since one can't "add an interface/Trait" to a struct in other static typed languages that isn't intuitive to me (yet π )
So the added Trait plus the expansion of the .after generic to resolve to the function to load the config at compile time is a new thing π
Anyway when coded as the below it does the proper thing π
app.add_systems(
PreUpdate,
PointerTools::update_tools.after(events::pointer_events)
)
PK
By the looks of it this crate (or its functions) is getting integrated into bevy. I'm thinking of migrating due to 2dBundles being broken in 0.20.0.
However, I am dependent on the bevy_picking_highlight crate as well. Could I use it separately without bevy_mod_picking, given that I bump dependencies to 0.15.0?
this has already been integrated in the 0.15 release as bevy_picking
it should be possible to port the bevy_picking_highlight crate to the new system (on an infinite timeline i will do it, but i've been busy with other work recently).
the biggest issue with that crate is actually the changes to Handle<T> no longer being a component.
Sweet! I might give it a crack. Thank you
Yeah, I will probably get around to updating all of those, but it is super duper low priority with the upstream available to users.