I'm trying to create a system which will allow me to zoom in an out on a orthographic camera (taken from the orthographic bevy example). However, the following query produces 0 results: mut query: Query<(&mut Transform, &mut OrthographicProjection)>. What's the proper way to query for this camera so that I can update the projection scale and camera position? Thanks!
#Zoom orthographic 3d camera
1 messages · Page 1 of 1 (latest)
fn modify_camera(mut query: Query<(&mut Transform, &mut OrthographicProjection)>) {
let Some(camera) = query.iter_mut().next() else { return };
dbg!(camera);
}
I tried this and it works for me, I'm just using the default Camera2dBundle as well, here's the output:
It seems like this is the problem. When I switch to Camera2dBundle, the query starts returning results, but then the 3d orthographic rendering breaks.
So something seems to be broken with this query when using Camera3dBundle but not with Camera2dBundle
camera3dbundle uses perspective projection by default
fn setup_camera(mut commands: Commands) {
commands.spawn(Camera3dBundle {
projection: Projection::Orthographic(OrthographicProjection::default()),
..default()
});
}
fn modify_camera(mut query: Query<(&mut Transform, &mut Projection)>) {
let Some(camera) = query.iter_mut().next() else { return };
dbg!(camera);
}
doing this worked for me, since Projection is the component on Camera3dBundle which wraps OrthoGraphicProjection (or PerspectiveProjection, if you're using that)
in vscode, with the bundle you can use go to definition (ctrl+left click) which shows that the bundle has a Projection component
Ah, I'll try using Projection in the query! Just waiting for the build now... been getting these spurious errors where LINK.EXE complains about "unresolved external symbol"s and cargo clean has been the only thing to resolve it when it occurs every now and then
hm, how do you access the ortographicprojection scale when you have the Projection enum:
Perspective(PerspectiveProjection),
Orthographic(OrthographicProjection),
}```
?
i also just ran across https://github.com/bevyengine/bevy/pull/2662/files
a stalled diff adding zooming to the orthographic example 🙂
the pull is also trying to use OrthographicProjection. not sure if the Projection enum is meant to be used in a query...
fn setup_camera(mut commands: Commands) {
commands.spawn(Camera3dBundle {
projection: Projection::Orthographic(OrthographicProjection::default()),
..default()
});
}
fn modify_camera(mut query: Query<(&mut Transform, &mut Projection)>) {
let Some(mut camera) = query.iter_mut().next() else { return };
camera.0.scale.x += 0.1;
dbg!(camera.0.scale.x);
}
the enum has two values, each value is a 1-element tuple, so you access the projection like this
I think 1 element tuple is the right way to describe it technically, it's when you have a type that's SomeType(ExistingType)
projection.0 doesn't seem to work in this context. im such a noob with rust, but at least i can see that the scale is in there:
[src\main.rs:37] projection = Mut(
Orthographic(
OrthographicProjection {
left: -0.8888889,
right: 0.8888889,
bottom: -0.5,
top: 0.5,
near: 0.0,
far: 1000.0,
window_origin: Center,
scaling_mode: FixedVertical(
1.0,
),
scale: 4.0,
},
),
)
oh wait my code is accessing the transform, not the projection, I'm not any better with rust either
yeah you forgot it's a tuple but i got what you were going for
fn modify_camera(mut query: Query<&Projection>) {
let Some(camera) = query.iter_mut().next() else { return };
let Projection::Orthographic(orthographic) = camera else { return };
dbg!(orthographic);
}
I can access the orthographic projection like this, but if I change it to &mut Projection I get an error that I don't know what to do with
You need to dereference camera since bevy is giving you a Mut<Projection>
Try = *camera
This is often known in Rust as a “newtype”
Yeah, I think I understand what you mean, but given a Projection, I've only been able to replace the whole thing, rather than just changing the scale, like so:
*projection = Projection::Orthographic(OrthographicProjection {
scale: 14.0,
scaling_mode: ScalingMode::FixedVertical(1.0),
..default()
});
But it'd be much better to be able to just change the scale, though I can't figure out how to drill down into that Mut<Projection>
reading about newtype
Ok this also works
match *projection {
Projection::Orthographic(ref mut ortho) => {
ortho.scale += dist;
},
_ => (),
}
This also works. Don't know if it can be made any cleaner still
if let Projection::Orthographic(ref mut ortho) = *projection {
ortho.scale += dist;
}
So this does what I was hoping for:
fn player_camera_control(
kb: Res<Input<KeyCode>>,
time: Res<Time>,
mut cameras: Query<(&mut Transform, &mut Projection)>,
) {
if let Some((mut transform, mut projection)) = cameras.iter_mut().next() {
if let Projection::Orthographic(ref mut ortho) = *projection {
let dist = 1. * time.delta().as_secs_f32();
let mut log_scale = ortho.scale.ln();
if kb.pressed(KeyCode::PageUp) {
log_scale += dist;
}
if kb.pressed(KeyCode::PageDown) {
log_scale -= dist;
}
ortho.scale = log_scale.exp();
}
}
}
I mean I think you can do = &mut *projection which is a little cleaner imo
Also, another thing to keep in mind is that mutable dereferencing like this triggers change detection (which should be fine here since you’re always mutating). So just be mindful of that if you rely on change detection for that component anywhere
The ref mut? I see. Well, ideally this would query for the OrtographicProjection directly, but that query didn't produce any results.