diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 32c459740..2ce35bbcc 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -30,12 +30,8 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - features: [ - '', - 'manage_clipboard', - 'open_url', - 'manage_clipboard,open_url', - ] + features: + ["", "manage_clipboard", "open_url", "manage_clipboard,open_url"] steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 @@ -68,12 +64,15 @@ jobs: strategy: fail-fast: false matrix: - features: [ - 'immutable_ctx', - 'manage_clipboard', - 'open_url', - 'manage_clipboard,open_url', - ] + features: + [ + "immutable_ctx", + "manage_clipboard", + "open_url", + "manage_clipboard,open_url", + ] + env: + RUSTFLAGS: --cfg=web_sys_unstable_apis steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 diff --git a/Cargo.toml b/Cargo.toml index 8b8f921f6..f21cc50fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,10 @@ default_fonts = ["egui/default_fonts"] serde = ["egui/serde"] [dependencies] -bevy = { version = "0.10", default-features = false, features = ["bevy_render", "bevy_asset"] } +bevy = { version = "0.11", default-features = false, features = [ + "bevy_render", + "bevy_asset", +] } egui = { version = "0.21.0", default-features = false, features = ["bytemuck"] } webbrowser = { version = "0.8.2", optional = true } @@ -33,7 +36,7 @@ thread_local = { version = "1.1.0", optional = true } [dev-dependencies] once_cell = "1.16.0" version-sync = "0.9.4" -bevy = { version = "0.10", default-features = false, features = [ +bevy = { version = "0.11", default-features = false, features = [ "x11", "png", "bevy_pbr", diff --git a/README.md b/README.md index 5a63cf43c..ca4984069 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ fn main() { .add_plugin(EguiPlugin) // Systems that create Egui widgets should be run during the `CoreSet::Update` set, // or after the `EguiSet::BeginFrame` system (which belongs to the `CoreSet::PreUpdate` set). - .add_system(ui_example_system) + .add_systems(Update, ui_example_system) .run(); } diff --git a/examples/render_to_image_widget.rs b/examples/render_to_image_widget.rs index 3c494c07b..289a877eb 100644 --- a/examples/render_to_image_widget.rs +++ b/examples/render_to_image_widget.rs @@ -15,10 +15,10 @@ use egui::Widget; fn main() { App::new() .add_plugins(DefaultPlugins) - .add_plugin(EguiPlugin) - .add_startup_system(setup) - .add_system(rotator_system) - .add_system(render_to_image_example_system) + .add_plugins(EguiPlugin) + .add_systems(Startup, setup) + .add_systems(Update, rotator_system) + .add_systems(Update, render_to_image_example_system) .run(); } diff --git a/examples/side_panel.rs b/examples/side_panel.rs index a0cfc4882..c2b3446bf 100644 --- a/examples/side_panel.rs +++ b/examples/side_panel.rs @@ -17,11 +17,11 @@ struct OriginalCameraTransform(Transform); fn main() { App::new() .add_plugins(DefaultPlugins) - .add_plugin(EguiPlugin) + .add_plugins(EguiPlugin) .init_resource::() - .add_startup_system(setup_system) - .add_system(ui_example_system) - .add_system(update_camera_transform_system) + .add_systems(Startup, setup_system) + .add_systems(Update, ui_example_system) + .add_systems(Update, update_camera_transform_system) .run(); } diff --git a/examples/simple.rs b/examples/simple.rs index 74e031e78..63d592f6e 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -4,10 +4,10 @@ use bevy_egui::{egui, EguiContexts, EguiPlugin}; fn main() { App::new() .add_plugins(DefaultPlugins) - .add_plugin(EguiPlugin) + .add_plugins(EguiPlugin) // Systems that create Egui widgets should be run during the `CoreSet::Update` set, // or after the `EguiSet::BeginFrame` system (which belongs to the `CoreSet::PreUpdate` set). - .add_system(ui_example_system) + .add_systems(Update, ui_example_system) .run(); } diff --git a/examples/two_windows.rs b/examples/two_windows.rs index a2a6fc32d..e5e4c9314 100644 --- a/examples/two_windows.rs +++ b/examples/two_windows.rs @@ -13,12 +13,12 @@ struct Images { fn main() { let mut app = App::new(); app.add_plugins(DefaultPlugins) - .add_plugin(EguiPlugin) + .add_plugins(EguiPlugin) .init_resource::() - .add_startup_system(load_assets_system) - .add_startup_system(create_new_window_system) - .add_system(ui_first_window_system) - .add_system(ui_second_window_system); + .add_systems(Startup, load_assets_system) + .add_systems(Startup, create_new_window_system) + .add_systems(Update, ui_first_window_system) + .add_systems(Update, ui_second_window_system); app.run(); } @@ -69,7 +69,9 @@ fn ui_first_window_system( mut egui_ctx: Query<&mut EguiContext, With>, ) { let bevy_texture_id = egui_user_textures.add_image(images.bevy_icon.clone_weak()); - let Ok(mut ctx) = egui_ctx.get_single_mut() else { return; }; + let Ok(mut ctx) = egui_ctx.get_single_mut() else { + return; + }; egui::Window::new("First Window") .vscroll(true) .show(ctx.get_mut(), |ui| { @@ -94,7 +96,9 @@ fn ui_second_window_system( mut egui_ctx: Query<&mut EguiContext, Without>, ) { let bevy_texture_id = egui_user_textures.add_image(images.bevy_icon.clone_weak()); - let Ok(mut ctx) = egui_ctx.get_single_mut() else { return; }; + let Ok(mut ctx) = egui_ctx.get_single_mut() else { + return; + }; egui::Window::new("Second Window") .vscroll(true) .show(ctx.get_mut(), |ui| { diff --git a/examples/ui.rs b/examples/ui.rs index b06a843fc..62da28fd2 100644 --- a/examples/ui.rs +++ b/examples/ui.rs @@ -26,11 +26,11 @@ fn main() { .insert_resource(Msaa::Sample4) .init_resource::() .add_plugins(DefaultPlugins) - .add_plugin(EguiPlugin) - .add_startup_system(configure_visuals_system) - .add_startup_system(configure_ui_state_system) - .add_system(update_ui_scale_factor_system) - .add_system(ui_example_system) + .add_plugins(EguiPlugin) + .add_systems(Startup, configure_visuals_system) + .add_systems(Startup, configure_ui_state_system) + .add_systems(Update, update_ui_scale_factor_system) + .add_systems(Update, ui_example_system) .run(); } #[derive(Default, Resource)] diff --git a/src/egui_node.rs b/src/egui_node.rs index f530baafe..a713797e0 100644 --- a/src/egui_node.rs +++ b/src/egui_node.rs @@ -193,7 +193,8 @@ impl Node for EguiNode { fn update(&mut self, world: &mut World) { let mut window_sizes = world.query::<(&WindowSize, &mut EguiRenderOutput)>(); - let Ok((window_size, mut render_output)) = window_sizes.get_mut(world, self.window_entity) else { + let Ok((window_size, mut render_output)) = window_sizes.get_mut(world, self.window_entity) + else { return; }; let window_size = *window_size; @@ -316,12 +317,13 @@ impl Node for EguiNode { return Ok(()); // No window }; - let swap_chain_texture = - if let Some(swap_chain_texture) = extracted_window.swap_chain_texture.as_ref() { - swap_chain_texture - } else { - return Ok(()); // No swapchain texture - }; + let swap_chain_texture_view = if let Some(swap_chain_texture_view) = + extracted_window.swap_chain_texture_view.as_ref() + { + swap_chain_texture_view + } else { + return Ok(()); // No swapchain texture + }; let render_queue = world.get_resource::().unwrap(); @@ -343,7 +345,7 @@ impl Node for EguiNode { .begin_render_pass(&RenderPassDescriptor { label: Some("egui render pass"), color_attachments: &[Some(RenderPassColorAttachment { - view: swap_chain_texture, + view: swap_chain_texture_view, resolve_target: None, ops: Operations { load: LoadOp::Load, @@ -353,8 +355,12 @@ impl Node for EguiNode { depth_stencil_attachment: None, }); - let Some(pipeline_id) = egui_pipelines.get(&extracted_window.entity) else { return Ok(()) }; - let Some(pipeline) = pipeline_cache.get_render_pipeline(*pipeline_id) else { return Ok(()) }; + let Some(pipeline_id) = egui_pipelines.get(&extracted_window.entity) else { + return Ok(()); + }; + let Some(pipeline) = pipeline_cache.get_render_pipeline(*pipeline_id) else { + return Ok(()); + }; render_pass.set_pipeline(pipeline); render_pass.set_vertex_buffer(0, *self.vertex_buffer.as_ref().unwrap().slice(..)); diff --git a/src/lib.rs b/src/lib.rs index b18889474..fb873b9ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,24 +69,23 @@ use crate::{ #[cfg(all(feature = "manage_clipboard", not(target_arch = "wasm32")))] use arboard::Clipboard; use bevy::{ - app::{App, Plugin}, - asset::{AssetEvent, Assets, Handle}, + app::{App, Last, Plugin, PostUpdate, PreStartup, PreUpdate}, + asset::{load_internal_asset, AssetEvent, Assets, Handle}, ecs::{ event::EventReader, query::{QueryEntityError, WorldQuery}, - schedule::apply_system_buffers, + schedule::apply_deferred, system::{ResMut, SystemParam}, }, input::InputSystem, log, prelude::{ - Added, Commands, Component, CoreSet, Deref, DerefMut, Entity, IntoSystemAppConfigs, - IntoSystemConfig, IntoSystemConfigs, Query, Resource, Shader, StartupSet, SystemSet, With, - Without, + Added, Commands, Component, Deref, DerefMut, Entity, IntoSystemConfigs, Query, Resource, + Shader, SystemSet, With, Without, }, render::{ - render_resource::SpecializedRenderPipelines, texture::Image, ExtractSchedule, RenderApp, - RenderSet, + render_resource::SpecializedRenderPipelines, texture::Image, ExtractSchedule, Render, + RenderApp, RenderSet, }, utils::HashMap, window::{PrimaryWindow, Window}, @@ -216,7 +215,7 @@ impl EguiClipboard { pub struct EguiRenderOutput { /// Pairs of rectangles and paint commands. /// - /// The field gets populated during the [`EguiSet::ProcessOutput`] system (belonging to [`CoreSet::PostUpdate`]) and reset during `EguiNode::update`. + /// The field gets populated during the [`EguiSet::ProcessOutput`] system (belonging to bevy's [`PostUpdate`]) and reset during `EguiNode::update`. pub paint_jobs: Vec, /// The change in egui textures since last frame. @@ -226,7 +225,7 @@ pub struct EguiRenderOutput { /// Is used for storing Egui output. #[derive(Component, Clone, Default)] pub struct EguiOutput { - /// The field gets updated during the [`EguiSet::ProcessOutput`] system (belonging to [`CoreSet::PostUpdate`]). + /// The field gets updated during the [`EguiSet::ProcessOutput`] system (belonging to [`PostUpdate`]). pub platform_output: egui::PlatformOutput, } @@ -534,76 +533,91 @@ impl Plugin for EguiPlugin { world.init_resource::(); world.init_resource::(); - app.add_startup_systems( + app.add_systems( + PreStartup, ( setup_new_windows_system, - apply_system_buffers, + apply_deferred, update_window_contexts_system, ) .chain() - .in_set(EguiStartupSet::InitContexts) - .in_base_set(StartupSet::PreStartup), + .in_set(EguiStartupSet::InitContexts), ); app.add_systems( + PreUpdate, ( setup_new_windows_system, - apply_system_buffers, + apply_deferred, update_window_contexts_system, ) .chain() - .in_set(EguiSet::InitContexts) - .in_base_set(CoreSet::PreUpdate), + .in_set(EguiSet::InitContexts), ); - app.add_system( + app.add_systems( + PreUpdate, process_input_system .in_set(EguiSet::ProcessInput) .after(InputSystem) - .after(EguiSet::InitContexts) - .in_base_set(CoreSet::PreUpdate), + .after(EguiSet::InitContexts), ); - app.add_system( + app.add_systems( + PreUpdate, begin_frame_system .in_set(EguiSet::BeginFrame) - .after(EguiSet::ProcessInput) - .in_base_set(CoreSet::PreUpdate), + .after(EguiSet::ProcessInput), ); - app.add_system( - process_output_system - .in_set(EguiSet::ProcessOutput) - .in_base_set(CoreSet::PostUpdate), + app.add_systems( + PostUpdate, + process_output_system.in_set(EguiSet::ProcessOutput), ); - app.add_system( - update_egui_textures_system - .after(EguiSet::ProcessOutput) - .in_base_set(CoreSet::PostUpdate), + app.add_systems( + PostUpdate, + update_egui_textures_system.after(EguiSet::ProcessOutput), ); - app.add_system(free_egui_textures_system.in_base_set(CoreSet::Last)); + app.add_systems(Last, free_egui_textures_system) + .add_systems( + Render, + render_systems::prepare_egui_transforms_system.in_set(RenderSet::Prepare), + ) + .add_systems( + Render, + render_systems::queue_bind_groups_system.in_set(RenderSet::Queue), + ) + .add_systems( + Render, + render_systems::queue_pipelines_system.in_set(RenderSet::Queue), + ); - let mut shaders = app.world.resource_mut::>(); - shaders.set_untracked( - EGUI_SHADER_HANDLE, - Shader::from_wgsl(include_str!("egui.wgsl")), - ); + load_internal_asset!(app, EGUI_SHADER_HANDLE, "egui.wgsl", Shader::from_wgsl); + } + fn finish(&self, app: &mut App) { if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { render_app .init_resource::() .init_resource::>() .init_resource::() .add_systems( + ExtractSchedule, ( render_systems::extract_egui_render_data_system, render_systems::extract_egui_textures_system, render_systems::setup_new_windows_render_system, ) - .into_configs() - .in_schedule(ExtractSchedule), + .into_configs(), ) - .add_system( + .add_systems( + Render, render_systems::prepare_egui_transforms_system.in_set(RenderSet::Prepare), ) - .add_system(render_systems::queue_bind_groups_system.in_set(RenderSet::Queue)) - .add_system(render_systems::queue_pipelines_system.in_set(RenderSet::Queue)); + .add_systems( + Render, + render_systems::queue_bind_groups_system.in_set(RenderSet::Queue), + ) + .add_systems( + Render, + render_systems::queue_pipelines_system.in_set(RenderSet::Queue), + ); } } } @@ -773,7 +787,7 @@ mod tests { .build() .disable::(), ) - .add_plugin(EguiPlugin) + .add_plugins(EguiPlugin) .update(); } } diff --git a/src/systems.rs b/src/systems.rs index 767f6cce0..18de70491 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -92,14 +92,16 @@ pub fn process_input_system( }; } - let shift = input_resources.keyboard_input.pressed(KeyCode::LShift) - || input_resources.keyboard_input.pressed(KeyCode::RShift); - let ctrl = input_resources.keyboard_input.pressed(KeyCode::LControl) - || input_resources.keyboard_input.pressed(KeyCode::RControl); - let alt = input_resources.keyboard_input.pressed(KeyCode::LAlt) - || input_resources.keyboard_input.pressed(KeyCode::RAlt); - let win = input_resources.keyboard_input.pressed(KeyCode::LWin) - || input_resources.keyboard_input.pressed(KeyCode::RWin); + let shift = input_resources.keyboard_input.pressed(KeyCode::ShiftLeft) + || input_resources.keyboard_input.pressed(KeyCode::ShiftRight); + let ctrl = input_resources.keyboard_input.pressed(KeyCode::ControlLeft) + || input_resources + .keyboard_input + .pressed(KeyCode::ControlRight); + let alt = input_resources.keyboard_input.pressed(KeyCode::AltLeft) + || input_resources.keyboard_input.pressed(KeyCode::AltRight); + let win = input_resources.keyboard_input.pressed(KeyCode::SuperLeft) + || input_resources.keyboard_input.pressed(KeyCode::SuperRight); let mac_cmd = if cfg!(target_os = "macos") { win @@ -143,12 +145,11 @@ pub fn process_input_system( // that has been left. if cursor_left_window != Some(cursor_moved.window) { let scale_factor = egui_settings.scale_factor as f32; - let mut mouse_position: (f32, f32) = (cursor_moved.position / scale_factor).into(); + let mouse_position: (f32, f32) = (cursor_moved.position / scale_factor).into(); let mut context = context_params .contexts .get_mut(cursor_moved.window) .unwrap(); - mouse_position.1 = context.window_size.height() / scale_factor - mouse_position.1; egui_mouse_position.0 = Some((cursor_moved.window, mouse_position.into())); context .egui_input