diff --git a/Cargo.toml b/Cargo.toml index 37cf5e54..c0d40147 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ name = "render_egui_to_texture" required-features = ["render"] [dependencies] -bevy = { version = "0.15.0-dev", default-features = false, features = [ +bevy = { version = "0.15.0-rc.2", default-features = false, features = [ "bevy_asset", "bevy_winit", ] } @@ -66,13 +66,14 @@ thread_local = { version = "1.1.0", optional = true } [dev-dependencies] version-sync = "0.9.4" -bevy = { version = "0.15.0-dev", default-features = false, features = [ +bevy = { version = "0.15.0-rc.2", default-features = false, features = [ "x11", "png", "bevy_pbr", "bevy_core_pipeline", "tonemapping_luts", "webgl2", + "custom_cursor", ] } egui = { version = "0.29", default-features = false, features = ["bytemuck"] } @@ -102,4 +103,19 @@ crossbeam-channel = "0.5.8" members = ["run-wasm"] [patch.crates-io] -bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "9386bd0114c44c9f00a2e9c41db1225aaa78d15" } +# doesnt work: +# bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "a2b53d46e73b98f7f5d074ed2bb8ddfedfcc5d4d" } +# doesnt work: +#bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "cab00766d99c2bf0519464a60e8a91e05c83d0fd" } +# doesnt work: +# bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "1df8238e8d8fe968d682468301ad4140c95b7604" } +# doesnt work, breakage appears here! +# bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "56f8e526dde49b4e4ad62efb7ad27bfe0bd6f617" } +# works: +# bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "01dce4742f77a572a1ef21ce8f64ce3b6d2328a8" } +# works: +# bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "7ee5143d45f9246f9cffc52e916ae12d85a71779" } +# works: +# bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "3139b03e7400313d947dc912e12d7c2d98207653" } +# works: +#bevy = { git = "https://github.com/bevyengine/bevy.git", rev = "9386bd0114c44c9f00a2e9c41db1225aaa78d15" } diff --git a/examples/paint_callback.rs b/examples/paint_callback.rs index 8bb2b217..a0c57c67 100644 --- a/examples/paint_callback.rs +++ b/examples/paint_callback.rs @@ -8,6 +8,7 @@ use bevy::{ MultisampleState, PipelineCache, PolygonMode, PrimitiveState, RenderPipelineDescriptor, SpecializedRenderPipeline, SpecializedRenderPipelines, }, + sync_world::RenderEntity, RenderApp, }, }; @@ -52,7 +53,7 @@ impl EguiBevyPaintCallbackImpl for CustomPaintCallback { fn update( &self, _info: egui::PaintCallbackInfo, - window_entity: Entity, + window_entity: RenderEntity, key: EguiPipelineKey, world: &mut World, ) { @@ -72,7 +73,7 @@ impl EguiBevyPaintCallbackImpl for CustomPaintCallback { ); world - .entity_mut(window_entity) + .entity_mut(window_entity.id()) .insert(CustomPaintPipelineIdComp { pipeline_id }); pipeline_id }, @@ -86,12 +87,13 @@ impl EguiBevyPaintCallbackImpl for CustomPaintCallback { &self, _info: egui::PaintCallbackInfo, render_pass: &mut bevy::render::render_phase::TrackedRenderPass<'pass>, - window_entity: Entity, + window_entity: RenderEntity, _key: EguiPipelineKey, world: &'pass World, ) { let Some(pipeline) = world - .get_entity(window_entity) + .get_entity(window_entity.id()) + .ok() .and_then(|entity| entity.get::()) .and_then(|comp| { world @@ -99,6 +101,7 @@ impl EguiBevyPaintCallbackImpl for CustomPaintCallback { .and_then(|cache| cache.get_render_pipeline(comp.pipeline_id)) }) else { + warn!("Could not find pipeline."); return; }; @@ -202,23 +205,22 @@ fn setup_worldspace( output_texture }); - commands.spawn(PbrBundle { - mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0).mesh()), - material: materials.add(StandardMaterial { + commands.spawn(( + Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0).mesh())), + MeshMaterial3d(materials.add(StandardMaterial { base_color: Color::WHITE, base_color_texture: Some(Handle::clone(&output_texture)), alpha_mode: AlphaMode::Blend, // Remove this if you want it to use the world's lighting. unlit: true, ..default() - }), - ..default() - }); + })), + )); commands.spawn(EguiRenderToTextureHandle(output_texture)); - commands.spawn(Camera3dBundle { - transform: Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::new(0., 0., 0.), Vec3::Y), - ..default() - }); + commands.spawn(( + Camera3d::default(), + Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::new(0., 0., 0.), Vec3::Y), + )); } fn ui_render_to_texture_example_system( diff --git a/examples/render_egui_to_texture.rs b/examples/render_egui_to_texture.rs index 953ee584..dfde0f50 100644 --- a/examples/render_egui_to_texture.rs +++ b/examples/render_egui_to_texture.rs @@ -49,21 +49,20 @@ fn setup_worldspace( output_texture }); - commands.spawn(PbrBundle { - mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0).mesh()), - material: materials.add(StandardMaterial { + commands.spawn(( + Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0).mesh())), + MeshMaterial3d(materials.add(StandardMaterial { base_color: Color::WHITE, base_color_texture: Some(Handle::clone(&output_texture)), alpha_mode: AlphaMode::Blend, // Remove this if you want it to use the world's lighting. unlit: true, ..default() - }), - ..default() - }); + })), + )); commands.spawn(EguiRenderToTextureHandle(output_texture)); - commands.spawn(Camera3dBundle { - transform: Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::new(0., 0., 0.), Vec3::Y), - ..default() - }); + commands.spawn(( + Camera3d::default(), + Transform::from_xyz(1.5, 1.5, 1.5).looking_at(Vec3::new(0., 0., 0.), Vec3::Y), + )); } diff --git a/examples/render_to_image_widget.rs b/examples/render_to_image_widget.rs index c782b689..39a52c23 100644 --- a/examples/render_to_image_widget.rs +++ b/examples/render_to_image_widget.rs @@ -82,37 +82,36 @@ fn setup( // The cube that will be rendered to the texture. commands - .spawn(PbrBundle { - mesh: cube_handle, - material: preview_material_handle, - transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)), - ..default() - }) + .spawn(( + Mesh3d(cube_handle), + MeshMaterial3d(preview_material_handle), + Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)), + )) .insert(PreviewPassCube) .insert(preview_pass_layer.clone()); // The same light is reused for both passes, // you can specify different lights for preview and main pass by setting appropriate RenderLayers. commands - .spawn(PointLightBundle { - transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)), - ..default() - }) + .spawn(( + PointLight::default(), + Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)), + )) .insert(RenderLayers::default().with(1)); commands - .spawn(Camera3dBundle { - camera: Camera { + .spawn(( + Camera3d::default(), + Camera { // render before the "main pass" camera order: -1, target: RenderTarget::Image(image_handle), clear_color: ClearColorConfig::Custom(Color::srgba(1.0, 1.0, 1.0, 0.0)), ..default() }, - transform: Transform::from_translation(Vec3::new(0.0, 0.0, 15.0)) + Transform::from_translation(Vec3::new(0.0, 0.0, 15.0)) .looking_at(Vec3::default(), Vec3::Y), - ..default() - }) + )) .insert(preview_pass_layer); let cube_size = 4.0; @@ -122,30 +121,28 @@ fn setup( // Main pass cube. commands - .spawn(PbrBundle { - mesh: cube_handle, - material: main_material_handle, - transform: Transform { + .spawn(( + Mesh3d(cube_handle), + MeshMaterial3d(main_material_handle), + Transform { translation: Vec3::new(0.0, 0.0, 1.5), rotation: Quat::from_rotation_x(-std::f32::consts::PI / 5.0), ..default() }, - ..default() - }) + )) .insert(MainPassCube); // The main pass camera. - commands.spawn(Camera3dBundle { - transform: Transform::from_translation(Vec3::new(0.0, 0.0, 15.0)) - .looking_at(Vec3::default(), Vec3::Y), - ..default() - }); + commands.spawn(( + Camera3d::default(), + Transform::from_translation(Vec3::new(0.0, 0.0, 15.0)).looking_at(Vec3::default(), Vec3::Y), + )); } fn render_to_image_example_system( cube_preview_image: Res, - preview_cube_query: Query<&Handle, With>, - main_cube_query: Query<&Handle, With>, + preview_cube_query: Query<&MeshMaterial3d, With>, + main_cube_query: Query<&MeshMaterial3d, With>, mut materials: ResMut>, mut contexts: EguiContexts, ) { @@ -225,7 +222,7 @@ fn rotator_system( mut query: Query<&mut Transform, Or<(With, With)>>, ) { for mut transform in &mut query { - transform.rotate_x(1.5 * time.delta_seconds()); - transform.rotate_z(1.3 * time.delta_seconds()); + transform.rotate_x(1.5 * time.delta_secs()); + transform.rotate_z(1.3 * time.delta_secs()); } } diff --git a/examples/side_panel.rs b/examples/side_panel.rs index 14e9c56e..4980bee2 100644 --- a/examples/side_panel.rs +++ b/examples/side_panel.rs @@ -88,36 +88,30 @@ fn setup_system( mut meshes: ResMut>, mut materials: ResMut>, ) { - commands.spawn(PbrBundle { - mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)), - material: materials.add(Color::srgb(0.3, 0.5, 0.3)), - ..Default::default() - }); - commands.spawn(PbrBundle { - mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)), - material: materials.add(Color::srgb(0.8, 0.7, 0.6)), - transform: Transform::from_xyz(0.0, 0.5, 0.0), - ..Default::default() - }); - commands.spawn(PointLightBundle { - point_light: PointLight { + commands.spawn(( + Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))), + MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))), + )); + commands.spawn(( + Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))), + MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))), + Transform::from_xyz(0.0, 0.5, 0.0), + )); + commands.spawn(( + PointLight { intensity: 1500.0, shadows_enabled: true, ..Default::default() }, - transform: Transform::from_xyz(4.0, 8.0, 4.0), - ..Default::default() - }); + Transform::from_xyz(4.0, 8.0, 4.0), + )); let camera_pos = Vec3::new(-2.0, 2.5, 5.0); let camera_transform = Transform::from_translation(camera_pos).looking_at(CAMERA_TARGET, Vec3::Y); commands.insert_resource(OriginalCameraTransform(camera_transform)); - commands.spawn(Camera3dBundle { - transform: camera_transform, - ..Default::default() - }); + commands.spawn((Camera3d::default(), camera_transform)); } fn update_camera_transform_system( diff --git a/examples/two_windows.rs b/examples/two_windows.rs index b072950f..6bd22110 100644 --- a/examples/two_windows.rs +++ b/examples/two_windows.rs @@ -35,14 +35,14 @@ fn create_new_window_system(mut commands: Commands) { .id(); // second window camera - commands.spawn(Camera3dBundle { - camera: Camera { + commands.spawn(( + Camera3d::default(), + Camera { target: RenderTarget::Window(WindowRef::Entity(second_window_id)), ..Default::default() }, - transform: Transform::from_xyz(6.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y), - ..Default::default() - }); + Transform::from_xyz(6.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y), + )); } fn load_assets_system(mut commands: Commands, assets: Res) { @@ -70,6 +70,7 @@ fn ui_first_window_system( ) { let bevy_texture_id = egui_user_textures.add_image(images.bevy_icon.clone_weak()); let Ok(mut ctx) = egui_ctx.get_single_mut() else { + warn!("Could not find ctx."); return; }; egui::Window::new("First Window") @@ -100,6 +101,7 @@ fn ui_second_window_system( ) { let bevy_texture_id = egui_user_textures.add_image(images.bevy_icon.clone_weak()); let Ok(mut ctx) = egui_ctx.get_single_mut() else { + warn!("Could not find ctx(2)."); return; }; egui::Window::new("Second Window") diff --git a/examples/ui.rs b/examples/ui.rs index e3b05fed..a9164fd2 100644 --- a/examples/ui.rs +++ b/examples/ui.rs @@ -1,7 +1,8 @@ use bevy::{ + log::{Level, LogPlugin}, prelude::*, - render::view::cursor::CursorIcon, window::{PrimaryWindow, SystemCursorIcon}, + winit::cursor::CursorIcon, }; use bevy_egui::{EguiContexts, EguiPlugin, EguiSettings}; @@ -28,20 +29,31 @@ fn main() { App::new() .insert_resource(ClearColor(Color::BLACK)) .init_resource::() - .add_plugins(DefaultPlugins.set(WindowPlugin { - primary_window: Some(Window { - // You may want this set to `true` if you need virtual keyboard work in mobile browsers. - prevent_default_event_handling: false, - ..default() - }), - ..default() - })) + .add_plugins( + DefaultPlugins + .set(LogPlugin { + filter: "warn,ui=info".to_string(), + level: Level::INFO, + ..Default::default() + }) + .set(WindowPlugin { + primary_window: Some(Window { + // You may want this set to `true` if you need virtual keyboard work in mobile browsers. + prevent_default_event_handling: false, + ..default() + }), + ..default() + }), + ) .add_plugins(EguiPlugin) .add_systems(Startup, configure_cursor) .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) + .add_systems(PreUpdate, || { + info!("new frame:"); + }) .run(); } #[derive(Default, Resource)] diff --git a/src/egui_node.rs b/src/egui_node.rs index d08d9894..92b0e099 100644 --- a/src/egui_node.rs +++ b/src/egui_node.rs @@ -6,7 +6,8 @@ use crate::{ }; use bevy::{ ecs::world::{FromWorld, World}, - prelude::{Entity, Handle, Resource}, + log::{info, warn}, + prelude::{Handle, Resource}, render::{ render_asset::RenderAssetUsages, render_graph::{Node, NodeRunError, RenderGraphContext}, @@ -22,6 +23,7 @@ use bevy::{ VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, }, renderer::{RenderContext, RenderDevice, RenderQueue}, + sync_world::{MainEntity, RenderEntity}, texture::{ GpuImage, Image, ImageAddressMode, ImageFilterMode, ImageSampler, ImageSamplerDescriptor, @@ -192,7 +194,8 @@ pub(crate) struct EguiDraw { /// Egui render node. pub struct EguiNode { - window_entity: Entity, + window_entity_main: MainEntity, + window_entity_render: RenderEntity, vertex_data: Vec, vertex_buffer_capacity: usize, vertex_buffer: Option, @@ -206,9 +209,10 @@ pub struct EguiNode { impl EguiNode { /// Constructs Egui render node. - pub fn new(window_entity: Entity) -> Self { + pub fn new(window_entity_main: MainEntity, window_entity_render: RenderEntity) -> Self { EguiNode { - window_entity, + window_entity_main, + window_entity_render, draw_commands: Vec::new(), vertex_data: Vec::new(), vertex_buffer_capacity: 0, @@ -224,11 +228,13 @@ impl EguiNode { impl Node for EguiNode { fn update(&mut self, world: &mut World) { + info!("drawing"); let Some(key) = world .get_resource::() - .and_then(|windows| windows.windows.get(&self.window_entity)) + .and_then(|windows| windows.windows.get(&self.window_entity_main.id())) .and_then(EguiPipelineKey::from_extracted_window) else { + warn!("Could not make EguiPipelineKey."); return; }; @@ -236,8 +242,9 @@ impl Node for EguiNode { world.query::<(&EguiSettings, &RenderTargetSize, &mut EguiRenderOutput)>(); let Ok((egui_settings, window_size, mut render_output)) = - render_target_query.get_mut(world, self.window_entity) + render_target_query.get_mut(world, self.window_entity_render.id()) else { + warn!("Could not find settings."); return; }; let window_size = *window_size; @@ -245,6 +252,8 @@ impl Node for EguiNode { self.pixels_per_point = window_size.scale_factor * egui_settings.scale_factor; if window_size.physical_width == 0.0 || window_size.physical_height == 0.0 { + warn!("small window"); + return; } @@ -282,6 +291,7 @@ impl Node for EguiNode { )) .is_empty() { + warn!("empty clip"); continue; } @@ -324,7 +334,7 @@ impl Node for EguiNode { index_offset += mesh.vertices.len() as u32; let texture_handle = match mesh.texture_id { - egui::TextureId::Managed(id) => EguiTextureId::Managed(self.window_entity, id), + egui::TextureId::Managed(id) => EguiTextureId::Managed(self.window_entity_main, id), egui::TextureId::User(id) => EguiTextureId::User(id), }; @@ -377,7 +387,7 @@ impl Node for EguiNode { command .callback .cb() - .update(info, self.window_entity, key, world); + .update(info, self.window_entity_render, key, world); } } @@ -391,10 +401,14 @@ impl Node for EguiNode { let pipeline_cache = world.get_resource::().unwrap(); let extracted_windows = &world.get_resource::().unwrap().windows; - let extracted_window = extracted_windows.get(&self.window_entity); + let extracted_window = extracted_windows.get(&self.window_entity_main.id()); let swap_chain_texture_view = match extracted_window.and_then(|v| v.swap_chain_texture_view.as_ref()) { - None => return Ok(()), + None => { + warn!("no extracted_window for eguinode"); + + return Ok(()); + } Some(window) => window, }; @@ -402,7 +416,10 @@ impl Node for EguiNode { let (vertex_buffer, index_buffer) = match (&self.vertex_buffer, &self.index_buffer) { (Some(vertex), Some(index)) => (vertex, index), - _ => return Ok(()), + _ => { + warn!("no vertex or index buffer for eguinode"); + return Ok(()); + } }; render_queue.write_buffer(vertex_buffer, 0, &self.vertex_data); @@ -417,6 +434,8 @@ impl Node for EguiNode { None => unreachable!(), }; let Some(key) = pipeline_key else { + warn!("no pipeline KEY for eguinode"); + return Ok(()); }; @@ -434,7 +453,7 @@ impl Node for EguiNode { command.callback.cb().prepare_render( info, render_context, - self.window_entity, + self.window_entity_render, key, world, ); @@ -467,12 +486,13 @@ impl Node for EguiNode { }); let mut render_pass = TrackedRenderPass::new(device, render_pass); - let pipeline_id = egui_pipelines.get(&self.window_entity).unwrap(); + let pipeline_id = egui_pipelines.get(&self.window_entity_main).unwrap(); let Some(pipeline) = pipeline_cache.get_render_pipeline(*pipeline_id) else { + warn!("no pipeline for eguinode"); return Ok(()); }; - let transform_buffer_offset = egui_transforms.offsets[&self.window_entity]; + let transform_buffer_offset = egui_transforms.offsets[&self.window_entity_main]; let transform_buffer_bind_group = &egui_transforms.bind_group.as_ref().unwrap().1; let mut requires_reset = true; @@ -516,6 +536,7 @@ impl Node for EguiNode { physical_height, )); if scrissor_rect.is_empty() { + warn!("too small scissor"); continue; } @@ -577,7 +598,7 @@ impl Node for EguiNode { command.callback.cb().render( info, &mut render_pass, - self.window_entity, + self.window_entity_render, key, world, ); @@ -687,7 +708,7 @@ pub trait EguiBevyPaintCallbackImpl: Send + Sync { fn update( &self, info: egui::PaintCallbackInfo, - window_entity: Entity, + window_entity: RenderEntity, pipeline_key: EguiPipelineKey, world: &mut World, ); @@ -701,7 +722,7 @@ pub trait EguiBevyPaintCallbackImpl: Send + Sync { &self, info: egui::PaintCallbackInfo, render_context: &mut RenderContext<'w>, - window_entity: Entity, + window_entity: RenderEntity, pipeline_key: EguiPipelineKey, world: &'w World, ) { @@ -717,7 +738,7 @@ pub trait EguiBevyPaintCallbackImpl: Send + Sync { &self, info: egui::PaintCallbackInfo, render_pass: &mut TrackedRenderPass<'pass>, - window_entity: Entity, + window_entity: RenderEntity, pipeline_key: EguiPipelineKey, world: &'pass World, ); diff --git a/src/egui_render_to_texture_node.rs b/src/egui_render_to_texture_node.rs index 47883d5f..b83fb8d0 100644 --- a/src/egui_render_to_texture_node.rs +++ b/src/egui_render_to_texture_node.rs @@ -8,7 +8,6 @@ use crate::{ }; use bevy::{ ecs::world::World, - prelude::Entity, render::{ render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext, RenderLabel}, @@ -18,6 +17,7 @@ use bevy::{ PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, StoreOp, }, renderer::{RenderContext, RenderDevice, RenderQueue}, + sync_world::{MainEntity, RenderEntity}, texture::GpuImage, }, }; @@ -34,7 +34,8 @@ pub struct EguiRenderToTexturePass { /// Egui render to texture node. pub struct EguiRenderToTextureNode { - render_to_texture_target: Entity, + render_to_texture_target_render: RenderEntity, + render_to_texture_target_main: MainEntity, vertex_data: Vec, vertex_buffer_capacity: usize, vertex_buffer: Option, @@ -47,9 +48,13 @@ pub struct EguiRenderToTextureNode { } impl EguiRenderToTextureNode { /// Constructs Egui render node. - pub fn new(render_to_texture_target: Entity) -> Self { + pub fn new( + render_to_texture_target_render: RenderEntity, + render_to_texture_target_main: MainEntity, + ) -> Self { EguiRenderToTextureNode { - render_to_texture_target, + render_to_texture_target_render, + render_to_texture_target_main, draw_commands: Vec::new(), vertex_data: Vec::new(), vertex_buffer_capacity: 0, @@ -66,7 +71,7 @@ impl Node for EguiRenderToTextureNode { fn update(&mut self, world: &mut World) { let Ok(image_handle) = world .query::<&EguiRenderToTextureHandle>() - .get(world, self.render_to_texture_target) + .get(world, self.render_to_texture_target_render.id()) .map(|handle| handle.0.clone_weak()) else { return; @@ -82,7 +87,7 @@ impl Node for EguiRenderToTextureNode { let mut render_target_query = world.query::<(&EguiSettings, &RenderTargetSize, &mut EguiRenderOutput)>(); let Ok((egui_settings, render_target_size, mut render_output)) = - render_target_query.get_mut(world, self.render_to_texture_target) + render_target_query.get_mut(world, self.render_to_texture_target_render.id()) else { return; }; @@ -171,7 +176,7 @@ impl Node for EguiRenderToTextureNode { let texture_handle = match mesh.texture_id { egui::TextureId::Managed(id) => { - EguiTextureId::Managed(self.render_to_texture_target, id) + EguiTextureId::Managed(self.render_to_texture_target_main, id) } egui::TextureId::User(id) => EguiTextureId::User(id), }; @@ -225,7 +230,7 @@ impl Node for EguiRenderToTextureNode { command .callback .cb() - .update(info, self.render_to_texture_target, key, world); + .update(info, self.render_to_texture_target_render, key, world); } } @@ -239,7 +244,7 @@ impl Node for EguiRenderToTextureNode { let pipeline_cache = world.get_resource::().unwrap(); let extracted_render_to_texture: Option<&EguiRenderToTextureHandle> = - world.get(self.render_to_texture_target); + world.get(self.render_to_texture_target_render.id()); let Some(render_to_texture_gpu_image) = extracted_render_to_texture else { return Ok(()); }; @@ -272,7 +277,7 @@ impl Node for EguiRenderToTextureNode { command.callback.cb().prepare_render( info, render_context, - self.render_to_texture_target, + self.render_to_texture_target_render, key, world, ); @@ -306,7 +311,7 @@ impl Node for EguiRenderToTextureNode { let mut render_pass = TrackedRenderPass::new(device, render_pass); - let Some(pipeline_id) = egui_pipelines.get(&self.render_to_texture_target) else { + let Some(pipeline_id) = egui_pipelines.get(&self.render_to_texture_target_main) else { bevy::log::error!("no egui_pipeline"); return Ok(()); }; @@ -314,7 +319,7 @@ impl Node for EguiRenderToTextureNode { return Ok(()); }; - let transform_buffer_offset = egui_transforms.offsets[&self.render_to_texture_target]; + let transform_buffer_offset = egui_transforms.offsets[&self.render_to_texture_target_main]; let transform_buffer_bind_group = &egui_transforms.bind_group.as_ref().unwrap().1; let mut requires_reset = true; @@ -417,7 +422,7 @@ impl Node for EguiRenderToTextureNode { command.callback.cb().render( info, &mut render_pass, - self.render_to_texture_target, + self.render_to_texture_target_render, key, world, ); diff --git a/src/lib.rs b/src/lib.rs index b674c3a2..f073de8f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -124,8 +124,8 @@ use bevy::{ With, Without, }, reflect::Reflect, - render::view::cursor::CursorIcon, window::{PrimaryWindow, Window}, + winit::cursor::CursorIcon, }; #[cfg(all( feature = "manage_clipboard", diff --git a/src/render_systems.rs b/src/render_systems.rs index cf9d6a99..10fe58ab 100644 --- a/src/render_systems.rs +++ b/src/render_systems.rs @@ -16,6 +16,7 @@ use bevy::{ DynamicUniformBuffer, PipelineCache, ShaderType, SpecializedRenderPipelines, }, renderer::{RenderDevice, RenderQueue}, + sync_world::{MainEntity, RenderEntity}, texture::GpuImage, view::ExtractedWindows, Extract, @@ -42,7 +43,7 @@ impl ExtractResource for ExtractedEguiManagedTextures { #[derive(Debug, PartialEq, Eq, Hash)] pub enum EguiTextureId { /// Textures allocated via Egui. - Managed(Entity, u64), + Managed(MainEntity, u64), /// Textures allocated via Bevy. User(u64), } @@ -72,7 +73,10 @@ impl ExtractedEguiTextures<'_> { .0 .iter() .map(|(&(window, texture_id), managed_tex)| { - (EguiTextureId::Managed(window, texture_id), managed_tex.id()) + ( + EguiTextureId::Managed(MainEntity::from(window), texture_id), + managed_tex.id(), + ) }) .chain( self.user_textures @@ -85,16 +89,16 @@ impl ExtractedEguiTextures<'_> { /// Sets up the pipeline for newly created windows. pub fn setup_new_windows_render_system( - windows: Extract>>, + windows: Extract>>, mut render_graph: ResMut, ) { - for window in windows.iter() { + for (window, render_window) in windows.iter() { let egui_pass = EguiPass { - entity_index: window.index(), - entity_generation: window.generation(), + entity_index: render_window.index(), + entity_generation: render_window.generation(), }; - - let new_node = EguiNode::new(window); + dbg!("setup_new_windows_render_system"); + let new_node = EguiNode::new(MainEntity::from(window), *render_window); render_graph.add_node(egui_pass.clone(), new_node); @@ -103,16 +107,21 @@ pub fn setup_new_windows_render_system( } /// Sets up the pipeline for newly created Render to texture entities. pub fn setup_new_rtt_render_system( - render_to_texture_targets: Extract>>, + render_to_texture_targets: Extract< + Query<(Entity, &RenderEntity), Added>, + >, mut render_graph: ResMut, ) { - for render_to_texture_target in render_to_texture_targets.iter() { + for (render_to_texture_target, render_entity) in render_to_texture_targets.iter() { let egui_rtt_pass = EguiRenderToTexturePass { entity_index: render_to_texture_target.index(), entity_generation: render_to_texture_target.generation(), }; - let new_node = EguiRenderToTextureNode::new(render_to_texture_target); + let new_node = EguiRenderToTextureNode::new( + *render_entity, + MainEntity::from(render_to_texture_target), + ); render_graph.add_node(egui_rtt_pass.clone(), new_node); @@ -125,8 +134,8 @@ pub fn setup_new_rtt_render_system( pub struct EguiTransforms { /// Uniform buffer. pub buffer: DynamicUniformBuffer, - /// Offsets for each window. - pub offsets: HashMap, + /// The Entity is from the main world. + pub offsets: HashMap, /// Bind group. pub bind_group: Option<(BufferId, BindGroup)>, } @@ -160,22 +169,26 @@ impl EguiTransform { /// Prepares Egui transforms. pub fn prepare_egui_transforms_system( mut egui_transforms: ResMut, - render_targets: Query<(Entity, &EguiSettings, &RenderTargetSize)>, + render_targets: Query<(Option<&MainEntity>, &EguiSettings, &RenderTargetSize)>, render_device: Res, render_queue: Res, egui_pipeline: Res, ) { + info!("prepare_egui_transforms_system"); egui_transforms.buffer.clear(); egui_transforms.offsets.clear(); - for (render_target, egui_settings, size) in render_targets.iter() { + for (window_main, egui_settings, size) in render_targets.iter() { let offset = egui_transforms .buffer .push(&EguiTransform::from_render_target_size( *size, egui_settings.scale_factor, )); - egui_transforms.offsets.insert(render_target, offset); + info!(offset); + if let Some(window_main) = window_main { + egui_transforms.offsets.insert(*window_main, offset); + } } egui_transforms @@ -186,6 +199,7 @@ pub fn prepare_egui_transforms_system( match egui_transforms.bind_group { Some((id, _)) if buffer.id() == id => {} _ => { + info!("{:?}", buffer.id()); let transform_bind_group = render_device.create_bind_group( Some("egui transform bind group"), &egui_pipeline.transform_bind_group_layout, @@ -239,7 +253,7 @@ pub fn queue_bind_groups_system( /// Cached Pipeline IDs for the specialized instances of `EguiPipeline`. #[derive(Resource)] -pub struct EguiPipelines(pub HashMap); +pub struct EguiPipelines(pub HashMap); /// Queue [`EguiPipeline`] instances specialized on each window's swap chain texture format. pub fn queue_pipelines_system( @@ -248,26 +262,34 @@ pub fn queue_pipelines_system( mut specialized_pipelines: ResMut>, egui_pipeline: Res, windows: Res, - render_to_texture: Query<(Entity, &EguiRenderToTextureHandle)>, + render_to_texture: Query<(&MainEntity, &EguiRenderToTextureHandle)>, images: Res>, ) { - let mut pipelines: HashMap = windows + dbg!("queue_pipelines_system"); + let mut pipelines: HashMap = windows .iter() .filter_map(|(window_id, window)| { + dbg!("pipeline contd"); let key = EguiPipelineKey::from_extracted_window(window)?; let pipeline_id = specialized_pipelines.specialize(&pipeline_cache, &egui_pipeline, key); - Some((*window_id, pipeline_id)) + Some((dbg!(MainEntity::from(*window_id)), pipeline_id)) }) .collect(); - pipelines.extend(render_to_texture.iter().filter_map(|(entity_id, handle)| { - let img = images.get(&handle.0)?; - let key = EguiPipelineKey::from_gpu_image(img); - let pipeline_id = specialized_pipelines.specialize(&pipeline_cache, &egui_pipeline, key); + pipelines.extend( + render_to_texture + .iter() + .filter_map(|(main_entity, handle)| { + dbg!("pipeline rtt"); + let img = images.get(&handle.0)?; + let key = EguiPipelineKey::from_gpu_image(img); + let pipeline_id = + specialized_pipelines.specialize(&pipeline_cache, &egui_pipeline, key); - Some((entity_id, pipeline_id)) - })); + Some((dbg!(*main_entity), pipeline_id)) + }), + ); commands.insert_resource(EguiPipelines(pipelines)); } diff --git a/src/systems.rs b/src/systems.rs index f4c8ff62..e3beac04 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -96,7 +96,7 @@ impl ContextSystemParams<'_, '_> { } Err( err @ QueryEntityError::NoSuchEntity(_) - | err @ QueryEntityError::QueryDoesNotMatch(_), + | err @ QueryEntityError::QueryDoesNotMatch(_, _), ) => { log::error!("Failed to get an Egui context for a window ({window:?}): {err:?}",); None @@ -501,7 +501,7 @@ pub fn process_input_system( for mut context in context_params.contexts.iter_mut() { context.egui_input.modifiers = modifiers; - context.egui_input.time = Some(time.elapsed_seconds_f64()); + context.egui_input.time = Some(time.elapsed_secs_f64()); } // In some cases, we may skip certain events. For example, we ignore `ReceivedCharacter` events @@ -624,7 +624,7 @@ pub fn process_output_system( if let Some(mut cursor) = context.cursor { let mut set_icon = || { - *cursor = bevy::render::view::cursor::CursorIcon::System( + *cursor = bevy::winit::cursor::CursorIcon::System( egui_to_winit_cursor_icon(platform_output.cursor_icon) .unwrap_or(bevy::window::SystemCursorIcon::Default), );