diff --git a/Cargo.toml b/Cargo.toml index fb26439d..18cfdd00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,8 +39,11 @@ name = "ui" required-features = ["render"] [dependencies] -bevy = { version = "0.13", default-features = false, features = ["bevy_asset"] } +bevy = { version = "0.14.0", default-features = false, features = [ + "bevy_asset", +] } egui = { version = "0.28", default-features = false, features = ["bytemuck"] } +bytemuck = "1" webbrowser = { version = "0.8.2", optional = true } [target.'cfg(not(any(target_arch = "wasm32", target_os = "android")))'.dependencies] @@ -49,7 +52,7 @@ thread_local = { version = "1.1.0", optional = true } [dev-dependencies] version-sync = "0.9.4" -bevy = { version = "0.13", default-features = false, features = [ +bevy = { version = "0.14.0", default-features = false, features = [ "x11", "png", "bevy_pbr", @@ -59,7 +62,7 @@ bevy = { version = "0.13", default-features = false, features = [ ] } [target.'cfg(target_arch = "wasm32")'.dependencies] -winit = "0.29" +winit = "0.30" web-sys = { version = "0.3.63", features = [ "Clipboard", "ClipboardEvent", diff --git a/build.rs b/build.rs new file mode 100644 index 00000000..5e6da5fb --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo::rustc-check-cfg=cfg(web_sys_unstable_apis)"); +} diff --git a/examples/render_to_image_widget.rs b/examples/render_to_image_widget.rs index 9f4e782a..c782b689 100644 --- a/examples/render_to_image_widget.rs +++ b/examples/render_to_image_widget.rs @@ -70,7 +70,7 @@ fn setup( let cube_handle = meshes.add(Cuboid::new(4.0, 4.0, 4.0)); let default_material = StandardMaterial { - base_color: Color::rgb(0.8, 0.7, 0.6), + base_color: Color::srgb(0.8, 0.7, 0.6), reflectance: 0.02, unlit: false, ..default() @@ -89,7 +89,7 @@ fn setup( ..default() }) .insert(PreviewPassCube) - .insert(preview_pass_layer); + .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. @@ -98,7 +98,7 @@ fn setup( transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)), ..default() }) - .insert(RenderLayers::all()); + .insert(RenderLayers::default().with(1)); commands .spawn(Camera3dBundle { @@ -106,7 +106,7 @@ fn setup( // render before the "main pass" camera order: -1, target: RenderTarget::Image(image_handle), - clear_color: ClearColorConfig::Custom(Color::rgba(1.0, 1.0, 1.0, 0.0)), + 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)) @@ -166,7 +166,9 @@ fn render_to_image_example_system( ui.end_row(); ui.label("Emissive:"); - color_picker_widget(ui, &mut preview_material.emissive); + let mut emissive_color = Color::from(preview_material.emissive); + color_picker_widget(ui, &mut emissive_color); + preview_material.emissive = emissive_color.into(); ui.end_row(); ui.label("Perceptual roughness:"); @@ -194,7 +196,7 @@ fn render_to_image_example_system( } fn color_picker_widget(ui: &mut egui::Ui, color: &mut Color) -> egui::Response { - let [r, g, b, a] = color.as_rgba_f32(); + let [r, g, b, a] = Srgba::from(*color).to_f32_array(); let mut egui_color: egui::Rgba = egui::Rgba::from_srgba_unmultiplied( (r * 255.0) as u8, (g * 255.0) as u8, @@ -207,7 +209,7 @@ fn color_picker_widget(ui: &mut egui::Ui, color: &mut Color) -> egui::Response { egui::color_picker::Alpha::Opaque, ); let [r, g, b, a] = egui_color.to_srgba_unmultiplied(); - *color = Color::rgba( + *color = Color::srgba( r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0, diff --git a/examples/side_panel.rs b/examples/side_panel.rs index 5536bbe6..5989f27f 100644 --- a/examples/side_panel.rs +++ b/examples/side_panel.rs @@ -76,12 +76,12 @@ fn setup_system( ) { commands.spawn(PbrBundle { mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)), - material: materials.add(Color::rgb(0.3, 0.5, 0.3)), + 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::rgb(0.8, 0.7, 0.6)), + material: materials.add(Color::srgb(0.8, 0.7, 0.6)), transform: Transform::from_xyz(0.0, 0.5, 0.0), ..Default::default() }); diff --git a/examples/ui.rs b/examples/ui.rs index d8c76c5d..b7622a0f 100644 --- a/examples/ui.rs +++ b/examples/ui.rs @@ -22,7 +22,7 @@ impl FromWorld for Images { /// - configuring egui contexts during the startup. fn main() { App::new() - .insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0))) + .insert_resource(ClearColor(Color::BLACK)) .insert_resource(Msaa::Sample4) .init_resource::() .add_plugins(DefaultPlugins.set(WindowPlugin { diff --git a/src/egui_node.rs b/src/egui_node.rs index 2943f1f9..399ee851 100644 --- a/src/egui_node.rs +++ b/src/egui_node.rs @@ -5,7 +5,6 @@ use crate::{ EguiRenderOutput, EguiSettings, WindowSize, }; use bevy::{ - core::cast_slice, ecs::world::{FromWorld, World}, prelude::{Entity, Handle, Resource}, render::{ @@ -26,6 +25,7 @@ use bevy::{ view::ExtractedWindows, }, }; +use bytemuck::cast_slice; use egui::{TextureFilter, TextureOptions}; /// Egui shader. diff --git a/src/lib.rs b/src/lib.rs index 51687a97..65cd1048 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -634,7 +634,7 @@ impl Plugin for EguiPlugin { fn build(&self, app: &mut App) { app.register_type::(); - let world = &mut app.world; + let world = app.world_mut(); world.init_resource::(); #[cfg(feature = "render")] world.init_resource::(); @@ -730,7 +730,7 @@ impl Plugin for EguiPlugin { #[cfg(feature = "render")] fn finish(&self, app: &mut App) { - if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { + if let Some(render_app) = app.get_sub_app_mut(RenderApp) { render_app .init_resource::() .init_resource::>() @@ -877,7 +877,7 @@ fn free_egui_textures_system( if let egui::TextureId::Managed(texture_id) = texture_id { let managed_texture = egui_managed_textures.remove(&(window_id, texture_id)); if let Some(managed_texture) = managed_texture { - image_assets.remove(managed_texture.handle); + image_assets.remove(&managed_texture.handle); } } } diff --git a/src/render_systems.rs b/src/render_systems.rs index c04357f1..84ef7a2c 100644 --- a/src/render_systems.rs +++ b/src/render_systems.rs @@ -14,6 +14,7 @@ use bevy::{ DynamicUniformBuffer, PipelineCache, ShaderType, SpecializedRenderPipelines, }, renderer::{RenderDevice, RenderQueue}, + texture::GpuImage, view::ExtractedWindows, Extract, }, @@ -188,7 +189,7 @@ pub fn queue_bind_groups_system( mut commands: Commands, egui_textures: ExtractedEguiTextures, render_device: Res, - gpu_images: Res>, + gpu_images: Res>, egui_pipeline: Res, ) { let bind_groups = egui_textures diff --git a/src/systems.rs b/src/systems.rs index 5ca12623..8f0827d6 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -16,7 +16,7 @@ use bevy::{ log, prelude::{Entity, EventReader, Query, Resource, Time}, time::Real, - window::{CursorMoved, ReceivedCharacter, RequestRedraw}, + window::{CursorMoved, RequestRedraw}, }; use std::marker::PhantomData; @@ -27,7 +27,6 @@ pub struct InputEvents<'w, 's> { pub ev_cursor: EventReader<'w, 's, CursorMoved>, pub ev_mouse_button_input: EventReader<'w, 's, MouseButtonInput>, pub ev_mouse_wheel: EventReader<'w, 's, MouseWheel>, - pub ev_received_character: EventReader<'w, 's, ReceivedCharacter>, pub ev_keyboard_input: EventReader<'w, 's, KeyboardInput>, pub ev_touch: EventReader<'w, 's, TouchInput>, } @@ -38,7 +37,6 @@ impl<'w, 's> InputEvents<'w, 's> { self.ev_cursor.read().last(); self.ev_mouse_button_input.read().last(); self.ev_mouse_wheel.read().last(); - self.ev_received_character.read().last(); self.ev_keyboard_input.read().last(); self.ev_touch.read().last(); } @@ -228,26 +226,24 @@ pub fn process_input_system( }); } - if !command && !win || !*context_params.is_macos && ctrl && alt { - for event in input_events.ev_received_character.read() { - let Some(mut window_context) = context_params.window_context(event.window) else { - continue; - }; - - if event.char.matches(char::is_control).count() == 0 { - window_context - .egui_input - .events - .push(egui::Event::Text(event.char.to_string())); - } - } - } - for event in keyboard_input_events { + let text_event_allowed = !command && !win || !*context_params.is_macos && ctrl && alt; let Some(mut window_context) = context_params.window_context(event.window) else { continue; }; + if text_event_allowed && event.state.is_pressed() { + match &event.logical_key { + Key::Character(char) if char.matches(char::is_control).count() == 0 => { + (window_context.egui_input.events).push(egui::Event::Text(char.to_string())); + } + Key::Space => { + (window_context.egui_input.events).push(egui::Event::Text(" ".into())); + } + _ => (), + } + } + let (Some(key), physical_key) = ( bevy_to_egui_key(&event.logical_key), bevy_to_egui_physical_key(&event.key_code),