diff --git a/src/lib.rs b/src/lib.rs index ae59f62ff..ee3a10eea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -373,24 +373,25 @@ impl Plugin for EguiPlugin { world.get_resource_or_insert_with(EguiClipboard::default); world.insert_resource(EguiContext::new()); - let render_app = &mut app.sub_app_mut(RenderApp); - render_app.init_resource::(); - render_app - .init_resource::() - .init_resource::() - .add_system_to_stage( - RenderStage::Extract, - render_systems::extract_egui_render_data, - ) - .add_system_to_stage(RenderStage::Extract, render_systems::extract_egui_textures) - .add_system_to_stage( - RenderStage::Prepare, - render_systems::prepare_egui_transforms, - ) - .add_system_to_stage(RenderStage::Queue, render_systems::queue_bind_groups); - - let mut render_graph = render_app.world.get_resource_mut::().unwrap(); - setup_pipeline(&mut *render_graph, RenderGraphConfig::default()); + if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { + render_app.init_resource::(); + render_app + .init_resource::() + .init_resource::() + .add_system_to_stage( + RenderStage::Extract, + render_systems::extract_egui_render_data, + ) + .add_system_to_stage(RenderStage::Extract, render_systems::extract_egui_textures) + .add_system_to_stage( + RenderStage::Prepare, + render_systems::prepare_egui_transforms, + ) + .add_system_to_stage(RenderStage::Queue, render_systems::queue_bind_groups); + + let mut render_graph = render_app.world.get_resource_mut::().unwrap(); + setup_pipeline(&mut *render_graph, RenderGraphConfig::default()); + } } } @@ -464,8 +465,23 @@ pub fn setup_pipeline( #[cfg(test)] mod tests { + use super::*; + use bevy::{render::options::WgpuOptions, winit::WinitPlugin, DefaultPlugins}; + #[test] fn test_readme_deps() { version_sync::assert_markdown_deps_updated!("README.md"); } + + #[test] + fn headless_mode() { + App::new() + .insert_resource(WgpuOptions { + backends: None, + ..Default::default() + }) + .add_plugins_with(DefaultPlugins, |group| group.disable::()) + .add_plugin(EguiPlugin) + .update(); + } } diff --git a/src/render_systems.rs b/src/render_systems.rs index 879a6264f..02dd554a0 100644 --- a/src/render_systems.rs +++ b/src/render_systems.rs @@ -121,22 +121,23 @@ pub(crate) fn prepare_egui_transforms( egui_transforms .buffer .write_buffer(&render_device, &render_queue); - let buffer = egui_transforms.buffer.uniform_buffer().unwrap(); - - match egui_transforms.bind_group { - Some((id, _)) if buffer.id() == id => {} - _ => { - let transform_bind_group = render_device.create_bind_group(&BindGroupDescriptor { - label: Some("egui transform bind group"), - layout: &egui_pipeline.transform_bind_group_layout, - entries: &[BindGroupEntry { - binding: 0, - resource: egui_transforms.buffer.binding().unwrap(), - }], - }); - egui_transforms.bind_group = Some((buffer.id(), transform_bind_group)); - } - }; + + if let Some(buffer) = egui_transforms.buffer.uniform_buffer() { + match egui_transforms.bind_group { + Some((id, _)) if buffer.id() == id => {} + _ => { + let transform_bind_group = render_device.create_bind_group(&BindGroupDescriptor { + label: Some("egui transform bind group"), + layout: &egui_pipeline.transform_bind_group_layout, + entries: &[BindGroupEntry { + binding: 0, + resource: egui_transforms.buffer.binding().unwrap(), + }], + }); + egui_transforms.bind_group = Some((buffer.id(), transform_bind_group)); + } + }; + } } pub(crate) struct EguiTextureBindGroups { diff --git a/src/systems.rs b/src/systems.rs index 9f834d367..31eca70c1 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -156,34 +156,35 @@ pub fn process_input( } if let Some((x, y)) = egui_context.mouse_position { - let focused_egui_input = input_resources + if let Some(focused_egui_input) = input_resources .egui_input .get_mut(&*window_resources.focused_window) - .unwrap(); - let events = &mut focused_egui_input.raw_input.events; - - let pos = egui::pos2(x, y); - process_mouse_button_event( - events, - pos, - modifiers, - &input_resources.mouse_button_input, - MouseButton::Left, - ); - process_mouse_button_event( - events, - pos, - modifiers, - &input_resources.mouse_button_input, - MouseButton::Right, - ); - process_mouse_button_event( - events, - pos, - modifiers, - &input_resources.mouse_button_input, - MouseButton::Middle, - ); + { + let events = &mut focused_egui_input.raw_input.events; + + let pos = egui::pos2(x, y); + process_mouse_button_event( + events, + pos, + modifiers, + &input_resources.mouse_button_input, + MouseButton::Left, + ); + process_mouse_button_event( + events, + pos, + modifiers, + &input_resources.mouse_button_input, + MouseButton::Right, + ); + process_mouse_button_event( + events, + pos, + modifiers, + &input_resources.mouse_button_input, + MouseButton::Middle, + ); + } } if !ctrl && !win { @@ -200,47 +201,47 @@ pub fn process_input( } } - let focused_input = input_resources + if let Some(focused_input) = input_resources .egui_input .get_mut(&*window_resources.focused_window) - .unwrap(); - - for ev in input_events.ev_keyboard_input.iter() { - if let Some(key) = ev.key_code.and_then(bevy_to_egui_key) { - let egui_event = egui::Event::Key { - key, - pressed: match ev.state { - ElementState::Pressed => true, - ElementState::Released => false, - }, - modifiers, - }; - focused_input.raw_input.events.push(egui_event); - - #[cfg(feature = "manage_clipboard")] - if command { - match key { - egui::Key::C => { - focused_input.raw_input.events.push(egui::Event::Copy); - } - egui::Key::X => { - focused_input.raw_input.events.push(egui::Event::Cut); - } - egui::Key::V => { - if let Some(contents) = input_resources.egui_clipboard.get_contents() { - focused_input - .raw_input - .events - .push(egui::Event::Text(contents)) + { + for ev in input_events.ev_keyboard_input.iter() { + if let Some(key) = ev.key_code.and_then(bevy_to_egui_key) { + let egui_event = egui::Event::Key { + key, + pressed: match ev.state { + ElementState::Pressed => true, + ElementState::Released => false, + }, + modifiers, + }; + focused_input.raw_input.events.push(egui_event); + + #[cfg(feature = "manage_clipboard")] + if command { + match key { + egui::Key::C => { + focused_input.raw_input.events.push(egui::Event::Copy); + } + egui::Key::X => { + focused_input.raw_input.events.push(egui::Event::Cut); } + egui::Key::V => { + if let Some(contents) = input_resources.egui_clipboard.get_contents() { + focused_input + .raw_input + .events + .push(egui::Event::Text(contents)) + } + } + _ => {} } - _ => {} } } } - } - focused_input.raw_input.modifiers = modifiers; + focused_input.raw_input.modifiers = modifiers; + } for egui_input in input_resources.egui_input.values_mut() { egui_input.raw_input.predicted_dt = time.delta_seconds(); @@ -307,7 +308,7 @@ pub fn process_output( mut egui_output: ResMut>, mut egui_shapes: ResMut>, #[cfg(feature = "manage_clipboard")] mut egui_clipboard: ResMut, - winit_windows: Res, + winit_windows: Option>, ) { for id in egui_context.ctx.keys().copied() { let (output, shapes) = egui_context.ctx_for_window(id).end_frame(); @@ -319,11 +320,13 @@ pub fn process_output( egui_clipboard.set_contents(&output.copied_text); } - if let Some(winit_window) = winit_windows.get_window(id) { - winit_window.set_cursor_icon( - egui_to_winit_cursor_icon(output.cursor_icon) - .unwrap_or(winit::window::CursorIcon::Default), - ); + if let Some(ref winit_windows) = winit_windows { + if let Some(winit_window) = winit_windows.get_window(id) { + winit_window.set_cursor_icon( + egui_to_winit_cursor_icon(output.cursor_icon) + .unwrap_or(winit::window::CursorIcon::Default), + ); + } } // TODO: see if we can support `new_tab`.