Code Monkey home page Code Monkey logo

bevy_panorbit_camera's Introduction

Crates.io docs.rs Bevy tracking

Bevy Pan/Orbit Camera

A screen recording showing camera movement

Summary

Bevy Pan/Orbit Camera provides orbit camera controls for Bevy Engine, designed with simplicity and flexibility in mind. Use it to quickly prototype, experiment, for model viewers, and more!

Features:

  • Smoothed orbiting, panning, and zooming
  • Works with orthographic camera projection in addition to perspective
  • Customisable controls, sensitivity, and more
  • Touch support
  • Works with multiple viewports and/or windows
  • Easy to control manually, e.g. for keyboard control or animation
  • Can control cameras that render to a texture

Controls

Default mouse controls:

  • Left Mouse - Orbit
  • Right Mouse - Pan
  • Scroll Wheel - Zoom

Default touch controls:

  • One finger - Orbit
  • Two fingers - Pan
  • Pinch - Zoom

Quick Start

Add the plugin:

.add_plugins(PanOrbitCameraPlugin)

Add PanOrbitCamera to a camera:

commands.spawn((
    Camera3dBundle {
        transform: Transform::from_translation(Vec3::new(0.0, 1.5, 5.0)),
        ..default()
    },
    PanOrbitCamera::default(),
));

This will set up a camera with good defaults.

Check out the advanced example to see all the possible configuration options.

Cargo Features

  • bevy_egui (optional): Makes PanOrbitCamera ignore any input that egui uses, thus preventing moving the camera when interacting with egui windows

Version Compatibility

bevy bevy_panorbit_camera
0.14 0.19
0.13 0.14-0.18
0.12 0.9-0.13
0.11 0.6-0.8
0.10 0.1-0.5

Credits

License

All code in this repository is dual-licensed under either:

at your option. This means you can select the license you prefer! This dual-licensing approach is the de-facto standard in the Rust ecosystem and there are very good reasons to include both.

bevy_panorbit_camera's People

Contributors

kristoff3r avatar plonq avatar sk83rjosh avatar striezel avatar thmxv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

bevy_panorbit_camera's Issues

Allow overriding `ActiveCameraData`

Hey! Fantastic library. I love the ease of setup, and it works great by default in most environments.

The one thing I'd like to request is that you allow some way to override ActiveCameraData on a specific camera, to change the circumstances under which a given camera receives input. I have a setup where I have a main 3d camera that renders to a texture, and then a 2d camera downscales that and sends it to the main window's render texture. As is, I can't get the library to move the main camera, and I also can't overwrite the ActiveCameraData resource, because it gets rewritten when input is detected.

If I could set something like CameraDataOverride as a struct on my 3d camera to tell the library that it uses the main window, with such and such window dimensions, and this is the size of the viewport, that would be awesome.

Again, great library. I use it for 3 other projects as-is with no issues. Also, optionally, if you give some direction as to how this should be implemented, I can submit a PR.

Jitter with orthographic camera

Since commit 11b0348 (pull request #76) there are jitters when in orthographic camera.

To fix this, the system set does not only need to be before TransformSystem::TransformPropagate but also before CameraUpdateSystem (I think).

Export EguiWantsFocus resource

The check for GUI focus is super useful, and I need to do the same for other game input, so I ended up copy-pasting it into my input handling plugin. It would be great if the crate could pub it instead, so that I don't have to have two copies of the system and the resource on every frame.

Thanks for the great crate! Not only it works well, but oddly, it uses almost the exact same controls I had in my previous (Godot) prototype. Great minds I guess.

Framerate independence for rolling

Make rolling framerate independent. Since it is applied per system tick and doesn't use mouse motion, it's not framerate independent by default.

cannot freely rotate around in vertical direction

I'm using this crate for molecule visualization in my project and I find it very helpful. Thank you for creating it!

I've encountered an issue that's titled. When I rotate in horizontal direction, it seems to be okay. I'm not sure if it's a feature or a bug.

This can be reproduced in example basic:

cargo run --example basic

Panning in XZ, but not Y direction

Is it possible to use this plugin to have the camera pan in the X and Y (edit: Z) direction only but not the Z (edit: Y)? This is to make the equivalent of what google earth does where clicking and dragging only moves you horizontally but keeps your altitude the same.

Thanks!

Edit: I meant the XZ (horizontal) plane

egui feature will not work if default plugin sets exit_condition

Thank you for your great work and continuous improvement! I find bevy_egui to be a great feature that I really needed. However, I noticed that it doesn’t work as expected when I set the exit_condition in DefaultPlugins.

Relevant code snippets:

let default_plugin = DefaultPlugins.set(WindowPlugin {
    // FIXME: it will work if comment below line
    exit_condition: bevy::window::ExitCondition::OnPrimaryClosed,
    ..default()
});

App::new()
    .add_plugins(default_plugin)
    .add_plugin(PanOrbitCameraPlugin)
    .add_plugin(WorldInspectorPlugin::default())
    .add_startup_system(setup)
    .run();`

To reproduce this bug

  1. Changes I made in my fork:
    master...ybyygu:bevy_panorbit_camera-egui-bug:master
  2. run

    cargo run --example egui --features bevy_egui

mouse_delta in pan_orbit_camera fn yields unexpected values and movements

Context (Environment)

I am running the multiple_viewports.rs example in dev mode. I am interacting with the GUI through Windows Remote Desktop Connection. A println!("mouse delta: {}", mouse_delta); was added on line 420 in lib.rs.

Behavior

I am presuming the mouse delta shouldn't spike to the tens of thousands. With these current delta readings, the camera orbits and pans in sharp and unexpected directions and intensities.

Possible Fix

This is most likely a problem with bevy_input as opposed to bevy_panorbit_camera. I haven't taken a deep looked into bevy_input to source the problem. Never posted an issue before, lmk if there's a better place to post this issue.

Log

Compiling bevy_panorbit_camera v0.7.0 
(D:\rust\bevy_panorbit_camera)
    Finished dev [unoptimized + debuginfo] target(s) in 11.00s
     Running `target\debug\examples\multiple_viewports.exe`
2023-08-17T17:03:43.722274Z  INFO bevy_winit::system: Creating new window "App" (0v0)
2023-08-17T17:03:44.608741Z  INFO bevy_render::renderer: AdapterInfo { name: "NVIDIA GeForce GTX 1650", vendor: 4318, device: 8066, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "531.61", backend: Vulkan }
2023-08-17T17:03:45.439330Z  INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Windows 10 Pro", kernel: "19045", cpu: "Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz", core_count: "8", memory: "15.8 GiB" }
// Note: Program Running
mouse delta: [27699, 28732]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [0, 0]
mouse delta: [27733, 29036]
mouse delta: [0, 0]
mouse delta: [27733, 28975]
mouse delta: [27733, 28914]
mouse delta: [0, 0]
mouse delta: [55466, 57343]
mouse delta: [27733, 28489]
// Note: Program Stopped

Egui Context panics

I get this error after upgrading to bevy 0.14

`EguiContexts::ctx_for_window_mut` was called for an uninitialized context (window Entity { index: 92, generation: 5 }), make sure your system is run after [`EguiSet::InitContexts`] (or [`EguiStartupSet::InitContexts`] for startup systems)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_panorbit_camera::egui::check_egui_wants_focus`!

I don't have any clue why it doesn't work now but it worked before the upgrade and I haven't changed anything else.
I dynamically create a new window and now, bevy_panorbit_camera just intervenes and crashes because of a missing egui context.

bevy_egui feature does not work correctly with bevy_egui 0.24.0

It seems the focus handling does not work correctly anymore together with bevy_egui 0.24.0 (tested with bevy_panorbit_camera = { version = "0.9.2", features = ["bevy_egui"] })

Inputs on top of egui windows still cause the camera to move/rotate/zoom. With bevy_egui 0.23.0 drag and rotate events at least were not passing through. Mouse scroll events on Windows were kind of broken with 0.23.0 already: When scrolling on top of the menu the scroll events where buffered and applied (as zoom) when the mouse left the menu.

Scroll inputs going to wrong window in some cases

If multiple windows are open, and you scroll (zoom) the unfocused window, you can no longer zoom the focused window until you either pan or orbit on it.

Screen.Recording.2023-06-12.at.5.10.53.pm.mov

`Resource requested by bevy_panorbit_camera::egui::check_egui_wants_focus does not exist: bevy_egui::EguiUserTextures`

Hello,

Thank you for your awesome crate. It is a huge help to the bevy beginners. I'm fairly new to the bevy scene.
I ran into this error and some errors regarding Context (which I couldn't reproduce) on my machine.
I am not sure if this is me having a corrupt and very old installation of an OS or this is due to some bug in the program or bevy.

Error

Initially, I was working on my own project and ran into this error:
Resource requested by bevy_panorbit_camera::egui::check_egui_wants_focus does not exist: bevy_egui::EguiUserTextures
As it is an egui error, it happens when bevy_egui is featured.

What I did

After some tinkering with values and plugins, I suspected the versions. I used bevy_egui crate in 0.25 and 0.26 with and without feature render also checked bevy with its own render feature. Nothing worked on my project when having full dependencies as the following:

bevy-inspector-egui = "0.23.4"
bevy_utils = "0.13.2"
bevy_window = "0.13.2"

Assuming I am the main criminal here for skipping through the documentations and notes, I used your own examples. Both with a [workspace] empty config and without one on a fresh config (not that it matters just thought I mention). Again, I went forward and edited flags on your own Cargo.toml (the render thing). Also tried to bump to version 0.26.

The demo advanced ALWAYS crashed. 100% of the times. egui worked when the version was 0.25 without any other dependency in my own project.

Searching in the internet, I didn't find anything mostly because I am still not efficient in googling bevy related stuff. This caught my eye and I tried to contact the author of the issue as well so I just link it here for future reference.

I also have this issue and if I just let bevy_editor_pls insert the EguiPlugin it never inserts the bevy_egui::EguiUserTextures Resource and sometimes segfaults the program

Originally posted by @lambdadeltakay in mvlabat/bevy_egui#252 (comment)

All in all, I thought I report this for the sake of being documented. I have no idea how can I contribute to fix the issue as I am still learning bevy. But if I can make a blind guess, it guess the problem lies within this package. Please let me know if I can help in any capacity.

I am using a recent update of Arch (altho old in installation and pretty much it has its own set of problems) and I attached a full trace down below.

RUST_BACKTRACE=full cargo run --features="bevy_egui" --example advanced
Finished dev [unoptimized + debuginfo] target(s) in 0.09s
 Running `target/debug/examples/advanced`

2024-04-13T10:01:46.934734Z WARN log: error setting XSETTINGS; Xft options won't reload automatically
2024-04-13T10:01:46.945243Z INFO bevy_winit::system: Creating new window "App" (0v1)
2024-04-13T10:01:46.945400Z INFO log: Guessed window scale factor: 1
2024-04-13T10:01:46.991157Z INFO bevy_render::renderer: AdapterInfo { name: "NVIDIA GeForce RTX 3070 Ti", vendor: 4318, device: 9346, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "550.67", backend: Vulkan }
2024-04-13T10:01:47.282967Z INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Linux rolling Arch Linux", kernel: "6.8.2-arch1-1", cpu: "11th Gen Intel(R) Core(TM) i7-11700K @ 3.60GHz", core_count: "8", memory: "15.5 GiB" }
thread 'Compute Task Pool (7)' panicked at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/system/system_param.rs:570:17:
Resource requested by bevy_panorbit_camera::egui::check_egui_wants_focus does not exist: bevy_egui::EguiUserTextures
stack backtrace:
0: 0x56b093bfa616 - std::backtrace_rs::backtrace::libunwind::trace::hd6ffdc229294c06f
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/../../backtrace/src/backtrace/libunwind.rs:104:5
1: 0x56b093bfa616 - std::backtrace_rs::backtrace::trace_unsynchronized::h991f79b6e9960513
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x56b093bfa616 - std::sys_common::backtrace::_print_fmt::hf4ebe716f7ccda10
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/sys_common/backtrace.rs:68:5
3: 0x56b093bfa616 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h410d4c66be4e37f9
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/sys_common/backtrace.rs:44:22
4: 0x56b093c26070 - core::fmt::rt::Argument::fmt::he0ff0e0e188c0db5
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/fmt/rt.rs:142:9
5: 0x56b093c26070 - core::fmt::write::he40921d4802ce2ac
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/fmt/mod.rs:1120:17
6: 0x56b093bf6f5f - std::io::Write::write_fmt::h5de5a4e7037c9b20
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/io/mod.rs:1846:15
7: 0x56b093bfa3f4 - std::sys_common::backtrace::print::hd8e2e3f655086663
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/sys_common/backtrace.rs:47:5
8: 0x56b093bfa3f4 - std::sys_common::backtrace::print::h11c067a88e3bdb22
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/sys_common/backtrace.rs:34:9
9: 0x56b093bfbc77 - std::panicking::default_hook::{{closure}}::h8c832ecb03fde8ea
10: 0x56b093bfb9d9 - std::panicking::default_hook::h1633e272b4150cf3
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:292:9
11: 0x56b093bfc178 - std::panicking::rust_panic_with_hook::hb164d19c0c1e71d4
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:781:13
12: 0x56b093bfc052 - std::panicking::begin_panic_handler::{{closure}}::h0369088c533c20e9
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:659:13
13: 0x56b093bfab16 - std::sys_common::backtrace::__rust_end_short_backtrace::hc11d910daf35ac2e
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/sys_common/backtrace.rs:171:18
14: 0x56b093bfbda4 - rust_begin_unwind
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:647:5
15: 0x56b093c23465 - core::panicking::panic_fmt::ha6effc2775a0749c
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/panicking.rs:72:14
16: 0x56b08ffd3368 - <bevy_ecs::change_detection::ResMut as bevy_ecs::system::system_param::SystemParam>::get_param::{{closure}}::h2e930ec5dc85514d
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/system/system_param.rs:570:17
17: 0x56b08ffd78ff - core::option::Option::unwrap_or_else::h9ccaa69006e28daa
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/option.rs:976:21
18: 0x56b08ffdb0a3 - <bevy_ecs::change_detection::ResMut as bevy_ecs::system::system_param::SystemParam>::get_param::h1cd923751882e7c0
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/system/system_param.rs:567:21
19: 0x56b08ffd74ab - <(P0,P1) as bevy_ecs::system::system_param::SystemParam>::get_param::h1171ed556ed8a62f
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/system/system_param.rs:1363:20
20: 0x56b08ffd5e7c - bevy_egui::
::::get_param::h88cb0c59dc3d6247
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_egui-0.25.0/src/lib.rs:347:10
21: 0x56b08ffc6652 - <(P0,P1,P2) as bevy_ecs::system::system_param::SystemParam>::get_param::h6a544d3385754ea2
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/system/system_param.rs:1363:20
22: 0x56b08ffcc085 - <bevy_ecs::system::function_system::FunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run_unsafe::hb68e7465b8c35f46
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/system/function_system.rs:493:22
23: 0x56b093969fd9 - bevy_ecs::schedule::executor::multi_threaded::MultiThreadedExecutor::spawn_system_task::{{closure}}::{{closure}}::h4819dd6baa2b42d4
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/schedule/executor/multi_threaded.rs:534:26
24: 0x56b0939aa7b9 - core::ops::function::FnOnce::call_once::h52d56c755ecc1146
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/ops/function.rs:250:5
25: 0x56b093929539 - <core::panic::unwind_safe::AssertUnwindSafe as core::ops::function::FnOnce<()>>::call_once::hac576f44f4a8f4b7
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/panic/unwind_safe.rs:272:9
26: 0x56b093976bbd - std::panicking::try::do_call::h7658211b416e8e5a
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:554:40
27: 0x56b09397df1b - __rust_try
28: 0x56b09397667e - std::panicking::try::he3106bc3f39d09ea
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:518:19
29: 0x56b0939cff2a - std::panic::catch_unwind::h1bd227ad3f936291
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panic.rs:142:14
30: 0x56b0939698ca - bevy_ecs::schedule::executor::multi_threaded::MultiThreadedExecutor::spawn_system_task::{{closure}}::h9597e5cfa7c785cb
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.13.2/src/schedule/executor/multi_threaded.rs:529:23
31: 0x56b093927d87 - <core::panic::unwind_safe::AssertUnwindSafe as core::future::future::Future>::poll::h1825a220bd537531
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/panic/unwind_safe.rs:297:9
32: 0x56b09395487e - <futures_lite::future::CatchUnwind as core::future::future::Future>::poll::{{closure}}::hd491861c7b3d3a00
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.3.0/src/future.rs:588:42
33: 0x56b093929474 - <core::panic::unwind_safe::AssertUnwindSafe as core::ops::function::FnOnce<()>>::call_once::h645c7a0b9691250a
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/panic/unwind_safe.rs:272:9
34: 0x56b093976da6 - std::panicking::try::do_call::hb2990bd85ad64e37
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:554:40
35: 0x56b09397df1b - __rust_try
36: 0x56b093976718 - std::panicking::try::hebb93ec4f1aaad9e
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:518:19
37: 0x56b0939cff7b - std::panic::catch_unwind::h46594b9492343a45
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panic.rs:142:14
38: 0x56b0939545b0 - <futures_lite::future::CatchUnwind as core::future::future::Future>::poll::hbe8fd1935f644d9f
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.3.0/src/future.rs:588:9
39: 0x56b093970f39 - async_executor::Executor::spawn_inner::{{closure}}::ha791aa456099a3f4
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.10.0/src/lib.rs:237:20
40: 0x56b093909c07 - async_task::raw::RawTask<F,T,S,M>::run::{{closure}}::h32788f23108fe0aa
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/async-task-4.7.0/src/raw.rs:550:21
41: 0x56b0939aa284 - core::ops::function::FnOnce::call_once::h2e3c4522e9abef1e
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/ops/function.rs:250:5
42: 0x56b09392939c - <core::panic::unwind_safe::AssertUnwindSafe as core::ops::function::FnOnce<()>>::call_once::h15ea68178764cabc
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/panic/unwind_safe.rs:272:9
43: 0x56b093976a08 - std::panicking::try::do_call::h3e7c2bba5c70cd9d
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:554:40
44: 0x56b09397df1b - __rust_try
45: 0x56b093975efa - std::panicking::try::ha12b978c1c4eff62
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:518:19
46: 0x56b0939d01fb - std::panic::catch_unwind::hf285d9518ccfff2f
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panic.rs:142:14
47: 0x56b093903c54 - async_task::raw::RawTask<F,T,S,M>::run::h69301f18717db755
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/async-task-4.7.0/src/raw.rs:549:23
48: 0x56b093a0e51f - async_task::runnable::Runnable::run::h4cd6a868d3d76438
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/async-task-4.7.0/src/runnable.rs:781:18
49: 0x56b0939eeff2 - async_executor::Executor::run::{{closure}}::{{closure}}::hb9369966ddf25561
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.10.0/src/lib.rs:352:21
50: 0x56b0939e8495 - <futures_lite::future::Or<F1,F2> as core::future::future::Future>::poll::h3cae43337f80d69c
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.3.0/src/future.rs:449:33
51: 0x56b0939eeba1 - async_executor::Executor::run::{{closure}}::h0ac20053eadaf831
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/async-executor-1.10.0/src/lib.rs:359:32
52: 0x56b0939e3666 - futures_lite::future::block_on::{{closure}}::h2d65b073b7eac8ae
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.3.0/src/future.rs:99:19
53: 0x56b0939e5671 - std::thread::local::LocalKey::try_with::h4479394c6d398926
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/thread/local.rs:286:16
54: 0x56b0939e50b4 - std::thread::local::LocalKey::with::h1c45df7b950fcecd
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/thread/local.rs:262:9
55: 0x56b0939e343d - futures_lite::future::block_on::h2f5056a4514e9b9c
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-lite-2.3.0/src/future.rs:78:5
56: 0x56b0939faf82 - bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}::{{closure}}::{{closure}}::h36cacc40e82fc1ae
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.13.2/src/task_pool.rs:180:37
57: 0x56b0939f6521 - std::panicking::try::do_call::h28d42a01fec84196
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:554:40
58: 0x56b0939fb93b - __rust_try
59: 0x56b0939f6358 - std::panicking::try::h9ada44ff19d7fb13
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:518:19
60: 0x56b0939f233e - std::panic::catch_unwind::hdc1b4dbfe21a8674
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panic.rs:142:14
61: 0x56b0939fac8c - bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}::{{closure}}::h9d6f3d8d62567020
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.13.2/src/task_pool.rs:174:43
62: 0x56b0939e57c1 - std::thread::local::LocalKey::try_with::h6c816048fc66774f
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/thread/local.rs:286:16
63: 0x56b0939e512b - std::thread::local::LocalKey::with::h96b61245cff574b1
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/thread/local.rs:262:9
64: 0x56b0939faa95 - bevy_tasks::task_pool::TaskPool::new_internal::{{closure}}::{{closure}}::he809386342cb1058
at /home/yas/.local/share/cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.13.2/src/task_pool.rs:167:25
65: 0x56b0939e8c86 - std::sys_common::backtrace::_rust_begin_short_backtrace::ha014311ad1a9592a
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/sys_common/backtrace.rs:155:18
66: 0x56b0939ea5cd - std::thread::Builder::spawn_unchecked
::{{closure}}::{{closure}}::hde7246d4a9e5e886
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/thread/mod.rs:529:17
67: 0x56b0939ec881 - <core::panic::unwind_safe::AssertUnwindSafe as core::ops::function::FnOnce<()>>::call_once::he5f82f7d19faf347
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/panic/unwind_safe.rs:272:9
68: 0x56b0939f65b5 - std::panicking::try::do_call::h6b7e52662797902a
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:554:40
69: 0x56b0939fb93b - _rust_try
70: 0x56b0939f6482 - std::panicking::try::hdbc58e0535411d34
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panicking.rs:518:19
71: 0x56b0939ea3ed - std::panic::catch_unwind::hd4492b24aae18d36
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/panic.rs:142:14
72: 0x56b0939ea3ed - std::thread::Builder::spawn_unchecked
::{{closure}}::h14e791413a5d6eda
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/thread/mod.rs:528:30
73: 0x56b0939f238f - core::ops::function::FnOnce::call_once{{vtable.shim}}::h9e69d4f788419c6d
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/core/src/ops/function.rs:250:5
74: 0x56b093bff915 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce>::call_once::h6b630278c760b971
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/alloc/src/boxed.rs:2015:9
75: 0x56b093bff915 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce>::call_once::h70462b441b6c0e1f
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/alloc/src/boxed.rs:2015:9
76: 0x56b093bff915 - std::sys::pal::unix::thread::Thread::new::thread_start::h3631815ad38387d6
at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library/std/src/sys/pal/unix/thread.rs:108:17
77: 0x7e35ef21f55a -
78: 0x7e35ef29ca3c -
79: 0x0 -
Encountered a panic in system bevy_panorbit_camera::egui::check_egui_wants_focus!
Encountered a panic in system bevy_app::main_schedule::Main::run_main!

Smooth focus movement

Similar to target_alpha and target_beta it would be good to have a field to use for updating the position of focus after initialization. This would allow smooth camera movement with the focus point that moves.

Equivalent of Blender "auto depth"

This would require the use of ray casting. But allow much more instinctive navigation in the scene.

The idea is to cast a ray into the scene from the camera position into the direction of the mouse pointer. If there is a hit, use the location of the hit:

  • As the rotation center while rotating
  • As the "target" while zooming or panning (affecting the radius)

With this enabled, the geometry under the cursor is always the same after the zoom/rotation/pan as it was before.

Mouse Inputs Passthrough from `egui` to `bevy_panorbit_camera`

When not directly scrolling / dragging / clicking egui ui elements, all inputs get passed through to bevy_panorbit_camera when using the following code to add ui systems:

add_systems(Update, (draw_title_bar, draw_file_tree).chain())

As demonstrated here:

bevy_panorbit_camera_repo_ZH28m2hvHm.mp4

This appears to be a scheduling issue, and doing the following somewhat resolves the issue and blocks scroll events, but not mouse drag events:

add_systems(PreUpdate, (draw_title_bar, draw_file_tree).chain().after(EguiSet::BeginFrame))

As demonstrated here:

bevy_panorbit_camera_repo_0tAfLcCWZ4.mp4

Using the solution mentioned in #39 yields no further improvements.

Here is the code used for both of the above:
repro.zip

Remove `scale` field?

Can we remove the scale field and instead bind the orthographic camera's scale to radius, as shown in the code below? This would make it easier to switch between perspective and orthographic cameras. If there are no issues, I will submit a PR.

pub fn update_orbit_transform(
    alpha: f32,
    beta: f32,
    mut radius: f32,
    focus: Vec3,
    transform: &mut Transform,
    projection: &mut Projection,
    basis: &Transform,
) {
    let mut new_transform = *basis;
    if let Projection::Orthographic(ref mut p) = *projection {
        p.scale = radius;
        // (near + far) / 2.0 ensures that objects near `focus` are not clipped
        radius = (p.near + p.far) / 2.0;
    }
    new_transform.rotation *= Quat::from_rotation_y(alpha) * Quat::from_rotation_x(-beta);
    new_transform.translation += focus + new_transform.rotation * Vec3::new(0.0, 0.0, radius);
    *transform = new_transform;
}

Feature request: changing the UP vector of the camera

It would be cool if I could change the camera's UP vector, for instance by holding ALT and using the scroll wheel, or whatever input scheme would be considered good.

That way I could not only yaw and pitch, but also roll (I am slowly getting a sore neck from trying to find a nice shot in my pet project 😇)

grafik

Zoom in the direction of the mouse position

It would be nice to allow zooming in the mouse position and thus not changing what is under the mouse while zooming and having a much more instinctive navigation in the scene.

Can only roll when mouse inside viewport

The plugin supports multiple viewports/windows, which means it needs to keep track of which one (and thus which PanOrbitCamera component) should be processing input events. This is called the 'active' camera. This works great when the input is from the mouse or touch, because those are always tied to a specific viewport/window (whichever one is under the cursor / being touched).

However, #45 just added 'roll' controls with keyboard only, which lands us in an awkward situation. When the user presses a roll key, which PanOrbitCamera should process the events? Because key presses alone aren't tied to any particular window/viewport, there's no way to know which camera the user intends to control. Given how this plugin is set up, the result is that rolling controls whichever camera is under the cursor, and if the camera is outside the window entirely it does nothing.

This isn't 100% solveable, but one possibility that should cover most cases is that when there's only a single instance of PanOrbitCamera then treat that as a special case and make it process all events regardless of whether it's the 'active' cam. Since I strongly suspect the vast majority of the time this plugin is used to control a single camera, this should fix the problem for most people.

One other possibility is to make the 'roll' controls use the mouse. I need to test this, but I think it might feel weird? Or maybe even removing the controls for roll and make that up to the user to do manually, since I think rolling is likely not a common use case anyway.

Please add support for RenderTarget::Image()

I draw my app GUI with bevy_ui, when I set the camera target of a Camera3dBundle to RenderTarget::Image(some_handle), and I spawn an ImageBundle (bevy_ui bundle) as a image texture to "capture" this Camera3dBundle with PanOrbitCamera , but the mouse events (mousewheel, mouse click) doesn't work for me. The only way right now to change the Transform of a Camera3dBundle is to Query Transform of this Camera3dBundle and set the translation of this bundle on my own. So is there a way to use PanOrbitCamera when the Camera3dBundle's render target is set to RenderTarget::Image (I know that RenderTarget::Window can work)?

Here's some of my code:

...some code...
let image_handle = generate_render_target_image(&mut images, 1000, 1000);

commands.spawn((
    Camera3dBundle {
        camera: Camera {
            order: camera_order_1,
            ..default()
        },
      camera_3d: Camera3d {
          clear_color: ClearColorConfig::None,
          ..default()
      },
      ..default()
  },
  render_layer_1,
));

// Spawn a ImageBundle to "capture" Camera3dBundle.
commands
.spawn((
    NodeBundle {
        style: Style {
            size: Size::new(Val::Px(1600.), Val::Px(1000.)),
            ..default()
        },
        background_color: BackgroundColor(Color::AZURE),
        ..default()
    },
    render_layer_1,
))
.with_children(|parent| {
    parent.spawn((
        ImageBundle {
            style: Style {
                size: Size::all(Val::Percent(80.)),
                ..default()
            },
            image: UiImage::new(image_handle.clone()),
            ..default()
        },
        render_layer_2,
    ));
});

commands.spawn((
    MaterialMeshBundle {
        mesh: meshes.add(mesh.clone()),
        material: materials.add(Color::GREEN.into()),
        ..default()
    },
    render_layer_2,
));

commands.spawn((
    Camera3dBundle {
        camera: Camera {
            order: camera_order_2,
            target: RenderTarget::Image(image_handle),
            ..default()
        },
        camera_3d: Camera3d {
            clear_color: ClearColorConfig::Custom(Color::BLACK),
            ..default()
        },
        ..default()
    },
    UiCameraConfig { show_ui: false },
    render_layer_2,
    PanOrbitCamera {
        zoom_sensitivity: 0.5,
        reversed_zoom: false,
        ..default()
    },
));
...

pub fn generate_render_target_image(
    images: &mut ResMut<Assets<Image>>,
    width: u32,
    height: u32,
) -> Handle<Image> {
    let render_target_size = Extent3d {
        width,
        height,
        ..default()
    };

    // This is the texture that will be rendered to.
    let mut render_target_image = Image {
        texture_descriptor: TextureDescriptor {
            label: None,
            size: render_target_size,
            dimension: TextureDimension::D2,
            format: TextureFormat::Bgra8UnormSrgb,
            mip_level_count: 1,
            sample_count: 1,
            usage: TextureUsages::TEXTURE_BINDING
                | TextureUsages::COPY_DST
                | TextureUsages::RENDER_ATTACHMENT,
            view_formats: &[],
        },
        ..default()
    };

    // fill image.data with zeroes
    render_target_image.resize(render_target_size);

    images.add(render_target_image)
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.