Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ open_url = ["webbrowser"]
default_fonts = ["egui/default_fonts"]

[dependencies]
bevy = { version = "0.9.0", default-features = false, features = ["bevy_render", "bevy_core_pipeline", "bevy_asset"] }
bevy = { version = "0.10", default-features = false, features = ["bevy_render", "bevy_core_pipeline", "bevy_asset"] }
egui = { version = "0.20.0", default-features = false, features = ["bytemuck"] }
webbrowser = { version = "0.8.2", optional = true }

Expand All @@ -32,7 +32,7 @@ thread_local = { version = "1.1.0", optional = true }
[dev-dependencies]
once_cell = "1.16.0"
version-sync = "0.9.4"
bevy = { version = "0.9.0", default-features = false, features = [
bevy = { version = "0.10", default-features = false, features = [
"x11",
"png",
"bevy_pbr",
Expand Down
6 changes: 4 additions & 2 deletions examples/render_to_image_widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ fn setup(
usage: TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
},
..default()
};
Expand Down Expand Up @@ -107,7 +108,7 @@ fn setup(
},
camera: Camera {
// render before the "main pass" camera
priority: -1,
order: -1,
target: RenderTarget::Image(image_handle),
..default()
},
Expand Down Expand Up @@ -150,12 +151,13 @@ fn render_to_image_example_system(
preview_cube_query: Query<&Handle<StandardMaterial>, With<PreviewPassCube>>,
main_cube_query: Query<&Handle<StandardMaterial>, With<MainPassCube>>,
mut materials: ResMut<Assets<StandardMaterial>>,
windows: Query<Entity, With<Window>>,
) {
let cube_preview_texture_id = egui_ctx.image_id(&cube_preview_image).unwrap();
let preview_material_handle = preview_cube_query.single();
let preview_material = materials.get_mut(preview_material_handle).unwrap();

let ctx = egui_ctx.ctx_mut();
let ctx = egui_ctx.ctx_for_window_mut(windows.iter().next().unwrap());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a loss of ergonomics indeed, I look forward to what can be done component-wise :) ; egui_context stored in a component attached to a window is my first not-much-informed thought

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now this looks like:

egui_ctx: Query<&EguiContext, With<Window>>,
[...]
let ctx = egui_ctx.iter().next().unwrap();

Thoughts?
The With<Window> isn't really needed, but maybe clarifies things. idk if it makes sense or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With<PrimaryWindow> might convey a better intention, that way you can use egui_ctx.single() ?

let mut apply = false;
egui::Window::new("Cube material preview").show(ctx, |ui| {
ui.image(cube_preview_texture_id, [300.0, 300.0]);
Expand Down
20 changes: 13 additions & 7 deletions examples/side_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,37 @@ fn main() {
fn ui_example_system(
mut egui_context: ResMut<EguiContext>,
mut occupied_screen_space: ResMut<OccupiedScreenSpace>,
windows: Query<Entity, With<Window>>,
) {
let ctx = egui_context.ctx_for_window_mut(windows.iter().next().unwrap());

occupied_screen_space.left = egui::SidePanel::left("left_panel")
.resizable(true)
.show(egui_context.ctx_mut(), |ui| {
.show(ctx, |ui| {
ui.allocate_rect(ui.available_rect_before_wrap(), egui::Sense::hover());
})
.response
.rect
.width();
occupied_screen_space.right = egui::SidePanel::right("right_panel")
.resizable(true)
.show(egui_context.ctx_mut(), |ui| {
.show(ctx, |ui| {
ui.allocate_rect(ui.available_rect_before_wrap(), egui::Sense::hover());
})
.response
.rect
.width();
occupied_screen_space.top = egui::TopBottomPanel::top("top_panel")
.resizable(true)
.show(egui_context.ctx_mut(), |ui| {
.show(ctx, |ui| {
ui.allocate_rect(ui.available_rect_before_wrap(), egui::Sense::hover());
})
.response
.rect
.height();
occupied_screen_space.bottom = egui::TopBottomPanel::bottom("bottom_panel")
.resizable(true)
.show(egui_context.ctx_mut(), |ui| {
.show(ctx, |ui| {
ui.allocate_rect(ui.available_rect_before_wrap(), egui::Sense::hover());
})
.response
Expand All @@ -69,7 +72,10 @@ fn setup_system(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
mesh: meshes.add(Mesh::from(shape::Plane {
size: 5.0,
subdivisions: 0,
})),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..Default::default()
});
Expand Down Expand Up @@ -103,7 +109,7 @@ fn setup_system(
fn update_camera_transform_system(
occupied_screen_space: Res<OccupiedScreenSpace>,
original_camera_transform: Res<OriginalCameraTransform>,
windows: Res<Windows>,
windows: Query<&Window>,
mut camera_query: Query<(&Projection, &mut Transform)>,
) {
let (camera_projection, mut transform) = match camera_query.get_single_mut() {
Expand All @@ -115,7 +121,7 @@ fn update_camera_transform_system(
let frustum_height = 2.0 * distance_to_target * (camera_projection.fov * 0.5).tan();
let frustum_width = frustum_height * camera_projection.aspect_ratio;

let window = windows.get_primary().unwrap();
let window = windows.iter().next().unwrap();

let left_taken = occupied_screen_space.left / window.width();
let right_taken = occupied_screen_space.right / window.width();
Expand Down
11 changes: 7 additions & 4 deletions examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ fn main() {
.run();
}

fn ui_example_system(mut egui_context: ResMut<EguiContext>) {
egui::Window::new("Hello").show(egui_context.ctx_mut(), |ui| {
ui.label("world");
});
fn ui_example_system(mut egui_context: ResMut<EguiContext>, windows: Query<Entity, With<Window>>) {
egui::Window::new("Hello").show(
egui_context.ctx_for_window_mut(windows.iter().next().unwrap()),
|ui| {
ui.label("world");
},
);
}
76 changes: 45 additions & 31 deletions examples/two_windows.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use bevy::{
prelude::*,
render::{camera::RenderTarget, render_graph::RenderGraph, RenderApp},
window::{CreateWindow, PresentMode, WindowId},
render::{camera::RenderTarget, render_graph::RenderGraph, Extract, RenderApp},
window::{PresentMode, PrimaryWindow, WindowRef, WindowResolution},
};
use bevy_egui::{EguiContext, EguiPlugin};
use once_cell::sync::Lazy;

static SECOND_WINDOW_ID: Lazy<WindowId> = Lazy::new(WindowId::new);
//TODO WindowId::new
//static SECOND_WINDOW_ID: Lazy<WindowId> = Lazy::new(WindowId::new);

#[derive(Resource)]
struct Images {
Expand All @@ -24,40 +24,49 @@ fn main() {
.add_system(ui_second_window_system);

let render_app = app.sub_app_mut(RenderApp);
let mut graph = render_app.world.get_resource_mut::<RenderGraph>().unwrap();

bevy_egui::setup_pipeline(
&mut graph,
bevy_egui::RenderGraphConfig {
window_id: *SECOND_WINDOW_ID,
egui_pass: SECONDARY_EGUI_PASS,
},
);
render_app.add_system_to_schedule(ExtractSchedule, init_second_window);

app.run();
}

fn init_second_window(
query: Extract<Query<(Entity, &Window), Without<PrimaryWindow>>>,
mut render_graph: ResMut<RenderGraph>,
mut is_setup: Local<bool>,
) {
if *is_setup {
return;
}
if let Some((entity, _window)) = query.iter().next() {
bevy_egui::setup_pipeline(
&mut render_graph,
bevy_egui::RenderGraphConfig {
window: entity,
egui_pass: SECONDARY_EGUI_PASS,
},
);
*is_setup = true;
}
}

const SECONDARY_EGUI_PASS: &str = "secondary_egui_pass";

fn create_new_window_system(
mut create_window_events: EventWriter<CreateWindow>,
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.,
fn create_new_window_system(mut commands: Commands) {
// Spawn a second window
let second_window_id = commands
.spawn(Window {
title: "Second window".to_owned(),
resolution: WindowResolution::new(800., 600.),
present_mode: PresentMode::AutoVsync,
title: "Second window".to_string(),
..Default::default()
},
});
})
.id();

// second window camera
commands.spawn(Camera3dBundle {
camera: Camera {
target: RenderTarget::Window(*SECOND_WINDOW_ID),
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),
Expand Down Expand Up @@ -86,11 +95,13 @@ fn ui_first_window_system(
mut ui_state: Local<UiState>,
mut shared_ui_state: ResMut<SharedUiState>,
images: Res<Images>,
windows: Query<Entity, With<Window>>,
) {
let first_window = windows.iter().nth(0).unwrap();
let bevy_texture_id = egui_context.add_image(images.bevy_icon.clone_weak());
egui::Window::new("First Window")
.vscroll(true)
.show(egui_context.ctx_mut(), |ui| {
egui::Window::new("First Window").vscroll(true).show(
egui_context.ctx_for_window_mut(first_window),
|ui| {
ui.horizontal(|ui| {
ui.label("Write something: ");
ui.text_edit_singleline(&mut ui_state.input);
Expand All @@ -101,17 +112,20 @@ fn ui_first_window_system(
});

ui.add(egui::widgets::Image::new(bevy_texture_id, [256.0, 256.0]));
});
},
);
}

fn ui_second_window_system(
mut egui_context: ResMut<EguiContext>,
mut ui_state: Local<UiState>,
mut shared_ui_state: ResMut<SharedUiState>,
images: Res<Images>,
windows: Query<Entity, With<Window>>,
) {
let second_window = windows.iter().nth(1).unwrap();
let bevy_texture_id = egui_context.add_image(images.bevy_icon.clone_weak());
let ctx = match egui_context.try_ctx_for_window_mut(*SECOND_WINDOW_ID) {
let ctx = match egui_context.try_ctx_for_window_mut(second_window) {
Some(ctx) => ctx,
None => return,
};
Expand Down
36 changes: 23 additions & 13 deletions examples/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl FromWorld for Images {
fn main() {
App::new()
.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0)))
.insert_resource(Msaa { samples: 4 })
.insert_resource(Msaa::Sample4)
.init_resource::<UiState>()
.add_plugins(DefaultPlugins)
.add_plugin(EguiPlugin)
Expand All @@ -43,11 +43,16 @@ struct UiState {
is_window_open: bool,
}

fn configure_visuals_system(mut egui_ctx: ResMut<EguiContext>) {
egui_ctx.ctx_mut().set_visuals(egui::Visuals {
window_rounding: 0.0.into(),
..Default::default()
});
fn configure_visuals_system(
mut egui_ctx: ResMut<EguiContext>,
windows: Query<Entity, With<Window>>,
) {
egui_ctx
.ctx_for_window_mut(windows.iter().next().unwrap())
.set_visuals(egui::Visuals {
window_rounding: 0.0.into(),
..Default::default()
});
}

fn configure_ui_state_system(mut ui_state: ResMut<UiState>) {
Expand All @@ -58,12 +63,12 @@ fn update_ui_scale_factor_system(
keyboard_input: Res<Input<KeyCode>>,
mut toggle_scale_factor: Local<Option<bool>>,
mut egui_settings: ResMut<EguiSettings>,
windows: Res<Windows>,
windows: Query<&Window>,
) {
if keyboard_input.just_pressed(KeyCode::Slash) || toggle_scale_factor.is_none() {
*toggle_scale_factor = Some(!toggle_scale_factor.unwrap_or(true));

if let Some(window) = windows.get_primary() {
if let Some(window) = windows.iter().next() {
let scale_factor = if toggle_scale_factor.unwrap() {
1.0
} else {
Expand All @@ -85,11 +90,14 @@ fn ui_example_system(
// If you need to access the ids from multiple systems, you can also initialize the `Images`
// resource while building the app and use `Res<Images>` instead.
images: Local<Images>,
windows: Query<Entity, With<Window>>,
) {
let primary_window = windows.iter().next().unwrap();
let ctx = egui_ctx.ctx_for_window_mut(primary_window);
let egui_texture_handle = ui_state
.egui_texture_handle
.get_or_insert_with(|| {
egui_ctx.ctx_mut().load_texture(
ctx.load_texture(
"example-image",
egui::ColorImage::example(),
Default::default(),
Expand All @@ -106,9 +114,11 @@ fn ui_example_system(
*rendered_texture_id = egui_ctx.add_image(images.bevy_icon.clone_weak());
}

let ctx = egui_ctx.ctx_for_window_mut(primary_window);

egui::SidePanel::left("side_panel")
.default_width(200.0)
.show(egui_ctx.ctx_mut(), |ui| {
.show(ctx, |ui| {
ui.heading("Side Panel");

ui.horizontal(|ui| {
Expand Down Expand Up @@ -149,7 +159,7 @@ fn ui_example_system(
});
});

egui::TopBottomPanel::top("top_panel").show(egui_ctx.ctx_mut(), |ui| {
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
// The top panel is often a good place for a menu bar:
egui::menu::bar(ui, |ui| {
egui::menu::menu_button(ui, "File", |ui| {
Expand All @@ -160,7 +170,7 @@ fn ui_example_system(
});
});

egui::CentralPanel::default().show(egui_ctx.ctx_mut(), |ui| {
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("Egui Template");
ui.hyperlink("https://github.com/emilk/egui_template");
ui.add(egui::github_link_file_line!(
Expand All @@ -185,7 +195,7 @@ fn ui_example_system(
egui::Window::new("Window")
.vscroll(true)
.open(&mut ui_state.is_window_open)
.show(egui_ctx.ctx_mut(), |ui| {
.show(ctx, |ui| {
ui.label("Windows can be moved by dragging them.");
ui.label("They are automatically sized based on contents.");
ui.label("You can turn on resizing and scrolling if you like.");
Expand Down
Loading