pub struct EguiPlugin {
pub enable_multipass_for_primary_context: bool,
pub ui_render_order: UiRenderOrder,
pub bindless_mode_array_size: Option<NonZero<u32>>,
}Expand description
Adds all Egui resources and render graph nodes.
Fields§
§enable_multipass_for_primary_context: boolEguiPlugin::default instead§About Egui multi-pass mode
From the Egui documentation:
By default, egui usually only does one pass for each rendered frame.
However, egui supports multi-pass immediate mode.
Another pass can be requested with egui::Context::request_discard.
This is used by some widgets to cover up “first-frame jitters”.
For instance, the egui::Grid needs to know the width of all columns before it can properly place the widgets.
But it cannot know the width of widgets to come.
So it stores the max widths of previous frames and uses that.
This means the first time a Grid is shown it will guess the widths of the columns, and will usually guess wrong.
This means the contents of the grid will be wrong for one frame, before settling to the correct places.
Therefore Grid calls egui::Context::request_discard when it is first shown, so the wrong placement is never
visible to the end user.
§Usage
Set this to true to enable an experimental support for the Egui multi-pass mode.
Enabling the multi-pass mode will require your app to use the new EguiPrimaryContextPass schedule:
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(EguiPlugin::default())
.add_systems(Startup, setup_camera_system)
.add_systems(EguiPrimaryContextPass, ui_example_system)
.run();
}
fn setup_camera_system(mut commands: Commands) {
commands.spawn(Camera2d);
}
fn ui_example_system(contexts: EguiContexts) -> Result {
// ...
Ok(())
}If you create multiple contexts (for example, when using multiple windows or rendering to an image), you need to define a custom schedule and assign it to additional contexts manually:
#[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)]
pub struct SecondWindowContextPass;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(EguiPlugin::default())
.add_systems(Startup, setup_system)
.add_systems(EguiPrimaryContextPass, ui_example_system)
.add_systems(SecondWindowContextPass, ui_example_system)
.run();
}
fn setup_system(
mut commands: Commands,
mut egui_global_settings: ResMut<EguiGlobalSettings>,
) {
// Disable the automatic creation of a primary context to set it up manually.
egui_global_settings.auto_create_primary_context = false;
// Spawn a camera for the primary window.
commands.spawn((Camera3d::default(), PrimaryEguiContext));
// Spawn the second window and its camera.
let second_window_id = commands.spawn(Window::default()).id();
commands.spawn((
EguiMultipassSchedule::new(SecondWindowContextPass),
Camera3d::default(),
Camera {
target: RenderTarget::Window(WindowRef::Entity(second_window_id)),
..Default::default()
},
));
}
fn ui_example_system(contexts: EguiContexts) -> Result {
// ...
Ok(())
}In the future, the multi-pass mode will likely phase the single-pass one out.
§Note to developers of public plugins
If your plugin depends on bevy_egui, here are some hints on how to implement the support of both single-pass and multi-pass modes
(with respect to the EguiPlugin::enable_multipass_for_primary_context flag):
- Don’t initialize
EguiPluginfor the user, i.e. DO NOT useadd_plugins(EguiPlugin { ... })in your code, users should be able to opt in or opt out of the multi-pass mode on their own. - If you add UI systems, make sure they go into the
EguiPrimaryContextPassschedule - this will guarantee your plugin supports both the single-pass and multi-pass modes.
Your plugin code might look like this:
pub struct MyPlugin;
impl Plugin for MyPlugin {
fn build(&self, app: &mut App) {
// Don't add the plugin for users, let them chose the default mode themselves
// and just make sure they initialize EguiPlugin before yours.
assert!(app.is_plugin_added::<EguiPlugin>());
app.add_systems(EguiPrimaryContextPass, ui_system);
}
}
fn ui_system(contexts: EguiContexts) -> Result {
// ...
Ok(())
}ui_render_order: UiRenderOrderConfigures whether egui will be rendered above or below bevy_ui_render(Bevy UI) GUIs.
Defaults to UiRenderOrder::EguiAboveBevyUi, on the assumption that games that use both
will typically use Bevy UI for the primary game UI, and egui for debug overlays.
Note: this option take effect only if both bevy_ui and bevy_egui UIs are rendered
to the same camera.
bindless_mode_array_size: Option<NonZero<u32>>Configure if bindless mode for rendering can be used on devices that has support for it.
It is useful in cases where multiple textures are used to render UI and renderer needs to frequently switch between different textures. This avoids the cost of frequently changing bind groups.
Trait Implementations§
Source§impl Default for EguiPlugin
impl Default for EguiPlugin
Source§impl Plugin for EguiPlugin
impl Plugin for EguiPlugin
Source§fn finish(&self, app: &mut App)
fn finish(&self, app: &mut App)
App, once all plugins registered are ready. This can
be useful for plugins that depends on another plugin asynchronous setup, like the renderer.Source§fn ready(&self, _app: &App) -> bool
fn ready(&self, _app: &App) -> bool
finish should be called.Source§fn cleanup(&self, _app: &mut App)
fn cleanup(&self, _app: &mut App)
Auto Trait Implementations§
impl Freeze for EguiPlugin
impl RefUnwindSafe for EguiPlugin
impl Send for EguiPlugin
impl Sync for EguiPlugin
impl Unpin for EguiPlugin
impl UnwindSafe for EguiPlugin
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T ShaderType for self. When used in AsBindGroup
derives, it is safe to assume that all images in self exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more