From 011a4c201d918f4586e6c20de8a37bd042a417f4 Mon Sep 17 00:00:00 2001 From: Aevyrie Date: Sat, 16 Apr 2022 01:44:48 -0700 Subject: [PATCH] Update to Bevy 0.7 (#79) * Upgrade to bevy main * Add mailbox vsync * Use Bevy 0.7 * Cleanup * Add missing desktop app settings * Fix cargo toml errors * Clean up the examples Co-authored-by: Forb.Jok Co-authored-by: mvlabat --- Cargo.toml | 12 ++++--- examples/side_panel.rs | 8 ++++- examples/simple.rs | 2 ++ examples/two_windows.rs | 69 +++++++---------------------------------- examples/ui.rs | 8 ++++- src/lib.rs | 4 +-- src/systems.rs | 20 ++++++++---- 7 files changed, 52 insertions(+), 71 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2b76873e8..5a72ff48c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,13 +19,13 @@ multi_threaded = ["egui/multi_threaded"] open_url = ["webbrowser"] [dependencies] -bevy = { version = "0.6", default-features = false, features = [ +bevy = { version = "0.7", default-features = false, features = [ "bevy_render", "bevy_winit", - "bevy_core_pipeline" + "bevy_core_pipeline", ] } egui = { version = "0.17", features = ["convert_bytemuck"] } -webbrowser = { version = "0.5.5", optional = true } +webbrowser = { version = "0.6.0", optional = true } winit = { version = "0.26.0", features = ["x11"], default-features = false } bytemuck = { version = "1.7.0", features = ["derive"] } wgpu = "0.12.0" @@ -35,6 +35,10 @@ arboard = { version = "2.0.1", optional = true } thread_local = { version = "1.1.0", optional = true } [dev-dependencies] -bevy = "0.6" once_cell = "1.9.0" version-sync = "0.9.2" +bevy = { version = "0.7", default-features = false, features = [ + "x11", + "png", + "bevy_pbr", +] } diff --git a/examples/side_panel.rs b/examples/side_panel.rs index b3f0da46d..fc463b30d 100644 --- a/examples/side_panel.rs +++ b/examples/side_panel.rs @@ -1,4 +1,4 @@ -use bevy::prelude::*; +use bevy::{prelude::*, window::PresentMode, winit::WinitSettings}; use bevy_egui::{egui, EguiContext, EguiPlugin}; #[derive(Default)] @@ -17,6 +17,12 @@ fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugin(EguiPlugin) + // Optimal power saving and present mode settings for desktop apps. + .insert_resource(WinitSettings::desktop_app()) + .insert_resource(WindowDescriptor { + present_mode: PresentMode::Mailbox, + ..Default::default() + }) .init_resource::() .add_startup_system(setup_system) .add_system(ui_example_system) diff --git a/examples/simple.rs b/examples/simple.rs index 725b7a6d6..1924744cc 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -5,6 +5,8 @@ fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugin(EguiPlugin) + // Systems that create Egui widgets should be run during the `CoreStage::Update` stage, + // or after the `EguiSystem::BeginFrame` system (which belongs to the `CoreStage::PreUpdate` stage). .add_system(ui_example) .run(); } diff --git a/examples/two_windows.rs b/examples/two_windows.rs index de9d81102..d72aa5ffd 100644 --- a/examples/two_windows.rs +++ b/examples/two_windows.rs @@ -1,14 +1,8 @@ use bevy::{ - core_pipeline::{draw_3d_graph, node, AlphaMask3d, Opaque3d, Transparent3d}, prelude::*, - render::{ - camera::{ActiveCameras, ExtractedCameraNames}, - render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext, SlotValue}, - render_phase::RenderPhase, - renderer::RenderContext, - RenderApp, RenderStage, - }, - window::{CreateWindow, WindowId}, + render::{camera::RenderTarget, render_graph::RenderGraph, RenderApp}, + window::{CreateWindow, PresentMode, WindowId}, + winit::WinitSettings, }; use bevy_egui::{EguiContext, EguiPlugin}; use once_cell::sync::Lazy; @@ -22,6 +16,12 @@ struct Images { fn main() { let mut app = App::new(); app.add_plugins(DefaultPlugins) + // Optimal power saving and present mode settings for desktop apps. + .insert_resource(WinitSettings::desktop_app()) + .insert_resource(WindowDescriptor { + present_mode: PresentMode::Mailbox, + ..Default::default() + }) .add_plugin(EguiPlugin) .init_resource::() .add_startup_system(load_assets) @@ -30,12 +30,7 @@ fn main() { .add_system(ui_second_window); let render_app = app.sub_app_mut(RenderApp); - render_app.add_system_to_stage(RenderStage::Extract, extract_secondary_camera_phases); let mut graph = render_app.world.get_resource_mut::().unwrap(); - graph.add_node(SECONDARY_PASS_DRIVER, SecondaryCameraDriver); - graph - .add_node_edge(node::MAIN_PASS_DEPENDENCIES, SECONDARY_PASS_DRIVER) - .unwrap(); bevy_egui::setup_pipeline( &mut graph, @@ -48,34 +43,16 @@ fn main() { app.run(); } -fn extract_secondary_camera_phases(mut commands: Commands, active_cameras: Res) { - if let Some(secondary) = active_cameras.get(SECONDARY_CAMERA_NAME) { - if let Some(entity) = secondary.entity { - commands.get_or_spawn(entity).insert_bundle(( - RenderPhase::::default(), - RenderPhase::::default(), - RenderPhase::::default(), - )); - } - } -} - -const SECONDARY_CAMERA_NAME: &str = "Secondary"; -const SECONDARY_PASS_DRIVER: &str = "secondary_pass_driver"; const SECONDARY_EGUI_PASS: &str = "secondary_egui_pass"; -fn create_new_window( - mut create_window_events: EventWriter, - mut commands: Commands, - mut active_cameras: ResMut, -) { +fn create_new_window(mut create_window_events: EventWriter, mut commands: Commands) { // sends out a "CreateWindow" event, which will be received by the windowing backend create_window_events.send(CreateWindow { id: *SECOND_WINDOW_ID, descriptor: WindowDescriptor { width: 800., height: 600., - vsync: false, + present_mode: PresentMode::Mailbox, title: "Second window".to_string(), ..Default::default() }, @@ -83,15 +60,12 @@ fn create_new_window( // second window camera commands.spawn_bundle(PerspectiveCameraBundle { camera: Camera { - window: *SECOND_WINDOW_ID, - name: Some(SECONDARY_CAMERA_NAME.into()), + target: RenderTarget::Window(*SECOND_WINDOW_ID), ..Default::default() }, transform: Transform::from_xyz(6.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y), ..Default::default() }); - - active_cameras.add(SECONDARY_CAMERA_NAME); } fn load_assets(mut commands: Commands, assets: Res) { @@ -100,25 +74,6 @@ fn load_assets(mut commands: Commands, assets: Res) { }); } -struct SecondaryCameraDriver; -impl Node for SecondaryCameraDriver { - fn run( - &self, - graph: &mut RenderGraphContext, - _render_context: &mut RenderContext, - world: &World, - ) -> Result<(), NodeRunError> { - let extracted_cameras = world.get_resource::().unwrap(); - if let Some(camera_3d) = extracted_cameras.entities.get(SECONDARY_CAMERA_NAME) { - graph.run_sub_graph( - crate::draw_3d_graph::NAME, - vec![SlotValue::Entity(*camera_3d)], - )?; - } - Ok(()) - } -} - #[derive(Default)] struct UiState { input: String, diff --git a/examples/ui.rs b/examples/ui.rs index 22f3fb3b7..4d320523e 100644 --- a/examples/ui.rs +++ b/examples/ui.rs @@ -1,4 +1,4 @@ -use bevy::prelude::*; +use bevy::{prelude::*, window::PresentMode, winit::WinitSettings}; use bevy_egui::{egui, EguiContext, EguiPlugin, EguiSettings}; struct Images { @@ -24,6 +24,12 @@ fn main() { App::new() .insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0))) .insert_resource(Msaa { samples: 4 }) + // Optimal power saving and present mode settings for desktop apps. + .insert_resource(WinitSettings::desktop_app()) + .insert_resource(WindowDescriptor { + present_mode: PresentMode::Mailbox, + ..Default::default() + }) .init_resource::() .add_plugins(DefaultPlugins) .add_plugin(EguiPlugin) diff --git a/src/lib.rs b/src/lib.rs index 659043bf7..f87efb47c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -598,7 +598,7 @@ pub fn setup_pipeline(render_graph: &mut RenderGraph, config: RenderGraphConfig) #[cfg(test)] mod tests { use super::*; - use bevy::{render::options::WgpuOptions, winit::WinitPlugin, DefaultPlugins}; + use bevy::{render::settings::WgpuSettings, winit::WinitPlugin, DefaultPlugins}; #[test] fn test_readme_deps() { @@ -608,7 +608,7 @@ mod tests { #[test] fn test_headless_mode() { App::new() - .insert_resource(WgpuOptions { + .insert_resource(WgpuSettings { backends: None, ..Default::default() }) diff --git a/src/systems.rs b/src/systems.rs index ba2f323f8..25b8c3025 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -4,18 +4,21 @@ use crate::{EguiContext, EguiInput, EguiOutput, EguiRenderOutput, EguiSettings, #[cfg(feature = "open_url")] use bevy::log; use bevy::{ - app::EventReader, core::Time, - ecs::system::{Local, Res, ResMut, SystemParam}, + ecs::{ + event::EventWriter, + system::{Local, Res, ResMut, SystemParam}, + }, input::{ keyboard::{KeyCode, KeyboardInput}, mouse::{MouseButton, MouseButtonInput, MouseScrollUnit, MouseWheel}, ElementState, Input, }, + prelude::{EventReader, NonSend}, utils::HashMap, window::{ - CursorEntered, CursorLeft, CursorMoved, ReceivedCharacter, WindowCreated, WindowFocused, - WindowId, Windows, + CursorEntered, CursorLeft, CursorMoved, ReceivedCharacter, RequestRedraw, WindowCreated, + WindowFocused, WindowId, Windows, }, winit::WinitWindows, }; @@ -341,7 +344,8 @@ pub fn process_output( mut egui_output: ResMut>, mut egui_render_output: ResMut>, #[cfg(feature = "manage_clipboard")] mut egui_clipboard: ResMut, - winit_windows: Option>, + winit_windows: Option>, + mut event: EventWriter, ) { let window_ids: Vec<_> = egui_context.ctx.keys().copied().collect(); for window_id in window_ids { @@ -350,7 +354,7 @@ pub fn process_output( platform_output, shapes, textures_delta, - needs_repaint: _, // TODO: only repaint if needed + needs_repaint, } = full_output; let egui_render_output = egui_render_output.entry(window_id).or_default(); @@ -373,6 +377,10 @@ pub fn process_output( } } + if needs_repaint { + event.send(RequestRedraw) + } + // TODO: see if we can support `new_tab`. #[cfg(feature = "open_url")] if let Some(egui::output::OpenUrl {