-
-
Notifications
You must be signed in to change notification settings - Fork 175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Picking doesnt work on adjacent 2d meshes (backend_raycast
)
#341
Comments
backend_raycast
)
backend_raycast
)backend_raycast
)
I can reproduce it with your example. If I had to guess, it's some kind of floating-point math error, but when logging the cursor position and x/y, I get whole numbers, so I'm not entirely sure. When the stars align, the ray cast appears like it's failing to resolve anything on some of the squares (note "some" as it only happens to the right-hand side of the board for me, so maybe as x increases, the margin of error increases?). Still, if you move everything by 1, it no longer has an issue AFAICT. Alternatively, if you set your camera translation to Vertical adjacencies don't seem to be an issue, or maybe you need a larger grid to see them. Modified Example with input mapped to moving the camera and boardsuse std::fmt::Debug;
use bevy::{
prelude::*,
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
window::WindowResolution,
};
use bevy::color::palettes::css::{BEIGE, DARK_GREEN};
use bevy::window::PrimaryWindow;
use bevy_mod_picking::prelude::*;
#[derive(Component, Debug)]
struct MainCamera;
#[derive(Component, Debug)]
struct Board;
#[derive(Component)]
struct Moveable;
fn is_key_pressed_factory(key_code: KeyCode) -> impl Fn(Res<ButtonInput<KeyCode>>) -> bool {
move |input: Res<ButtonInput<KeyCode>>| -> bool { input.just_pressed(key_code) }
}
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: WindowResolution::new(800., 400.).with_scale_factor_override(1.0),
// resizable: false,
..default()
}),
..default()
}))
.add_plugins(DefaultPickingPlugins)
.add_systems(Startup, setup)
.add_systems(
Update,
move_left::<Board>.run_if(is_key_pressed_factory(KeyCode::KeyA)),
)
.add_systems(
Update,
move_right::<Board>.run_if(is_key_pressed_factory(KeyCode::KeyD)),
)
.add_systems(
Update,
move_left::<MainCamera>.run_if(is_key_pressed_factory(KeyCode::KeyQ)),
)
.add_systems(
Update,
move_right::<MainCamera>.run_if(is_key_pressed_factory(KeyCode::KeyE)),
)
.add_systems(Update, log_click)
.run();
}
fn move_right<T: Component + Debug>(mut q: Query<(&T, &mut Transform), With<Moveable>>) {
for (comp, mut transform) in q.iter_mut() {
println!("moving {comp:?} right");
transform.translation.x += 1.0;
}
}
fn move_left<T: Component + Debug>(mut q: Query<(&T, &mut Transform), With<Moveable>>) {
for (comp, mut transform) in q.iter_mut() {
println!("moving {comp:?} left");
transform.translation.x -= 1.0;
}
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let camera_entity = commands
.spawn((
Camera2dBundle {
transform: Transform::from_xyz(200.0, 200.0, 0.0),
..default()
},
MainCamera,
Moveable,
))
.id();
let square_size = 50.0;
let width = 8usize;
let height = 8usize;
let mesh = Mesh2dHandle(meshes.add(Rectangle::new(square_size, square_size)));
let dark_mat = materials.add(Color::from(BEIGE));
let light_mat = materials.add(Color::from(DARK_GREEN));
fn is_dark_square(x: usize, y: usize) -> bool {
x % 2 == 0 && y % 2 == 0 || x % 2 != 0 && y % 2 != 0
}
let mut render_board = |offset: Vec2, movable: bool| {
let mut entity = commands.spawn((Board, SpatialBundle::default()));
entity.with_children(|parent| {
for x in 0..width {
for y in 0..height {
let material = if is_dark_square(x, y) {
dark_mat.clone()
} else {
light_mat.clone()
};
parent.spawn((
PickableBundle::default(),
On::<Pointer<Click>>::run(move || {
info!("({x}, {y})");
}),
MaterialMesh2dBundle {
mesh: mesh.clone(),
transform: Transform::from_translation(Vec3 {
x: x as f32 * square_size + offset.x,
y: y as f32 * square_size + offset.y,
z: 1.0,
}),
material,
..default()
},
));
}
}
});
if movable {
entity.insert(Moveable);
}
};
render_board(Vec2::new(0.0, 0.0), true);
// render_board(Vec2::new(-square_size * width as f32, 0.0), false);
// render_board(Vec2::new(square_size * width as f32 / 2.0, 0.0), true);
let mut ui = commands.spawn((
TargetCamera(camera_entity),
NodeBundle {
style: Style {
width: Val::Percent(100.0),
flex_direction: FlexDirection::Row,
..default()
},
..default()
},
));
ui.with_children(|parent| {
parent.spawn(TextBundle {
text: Text::from_section(
"KeyMap: A/D = board, Q/E = camera",
TextStyle {
font_size: 20.0,
color: Color::WHITE,
..default()
},
),
..default()
});
});
}
fn log_click(input: Res<ButtonInput<MouseButton>>, q_windows: Query<&Window, With<PrimaryWindow>>) {
if input.just_pressed(MouseButton::Left) {
if let Some(position) = q_windows.single().cursor_position() {
println!("Cursor is inside the primary window, at {:?}", position);
} else {
println!("Cursor is not in the game window.");
}
}
} |
I believe I have found the potential root cause and opened aevyrie/bevy_mod_raycast#118 |
In 2d, when I have 2 Meshes that are exactly adjacent to each other, I can position the mouse right on the edge between them, and the click won't be captured. Is this how it is supposed to work? User error?
For example, creating a chessboard like this (every square is exactly
50
wide, and50
away from each other, you can put the mouse right between the squares and the click won't be recognized.The text was updated successfully, but these errors were encountered: