bevy-inspector-egui v0.15.0-pre.0
Announcement and Migration Guide
I just released the next version 0.15.0-pre.0
of bevy-inspector-egui
and would like to gather some feedback before the actual release.
If you just want a stable release for bevy 0.9
, feel free to continue using bevy-inspector-egui
0.14
.
If you miss any features from the previous release, or have suggestions for features or API design, please open an issue at bevy-inspector-egui/issues or ping me on the bevy discord (in #project-collaboration
@dubi steinkek#2182
).
You can check out the 0.15.0
docs on docs.rs
: https://docs.rs/bevy-inspector-egui/0.15.0-pre
What’s new in the update?
This release features the removal of the Inspectable
trait in favor of reusing the existing Reflect
trait. This leads to less derive boilerplate and more reusability, paving the way for non-egui Inspector implementations (in the general sense, could also be autocomplete in a console) and usage outside of bevy.
New APIs
The release is a rewrite from scratch so here’s the new layout of the crate. For more detail, you can browse the crate docs.
The main modules are:
egui_reflect_inspector
- General-purpose machinery for displaying Reflect types using egui
bevy_inspector
- Methods for displaying bevy resources, assets and entities
inspector_options
- Way of associating options to fields using InspectorOptions
quick
- Easy plugins for showing UI panels.
egui_reflect_inspector
This module has no knowledge of bevy and provides general purpose methods for displaying arbitrary &mut dyn Reflect
or &dyn Reflect
(that’s right, we support readonly UI now).
Most of the time however you can just use either the
quick
module for an simple WorldInspectorPlugin
/ResourceInspectorPlugin
/StateInspectorPlugin
plugins, or the
bevy_inspector
module for functions like ui_for_resource
, ui_for_entity
, etc.
use bevy_reflect::{Reflect, TypeRegistry};
use bevy_inspector_egui::egui_reflect_inspector::{InspectorUi, Context};
#[derive(Reflect)]
struct Data {
value: f32,
}
fn ui(data: &mut Data, ui: &mut egui::Ui, type_registry: &TypeRegistry) -> bool {
let mut cx = Context::default();
let mut env = InspectorUi::new_no_short_circuit(type_registry, &mut cx);
env.ui_for_reflect(data, ui)
}
This is the minimum needed to display a value: the value, the Ui
and the type registry. This is enough for basic usage, but consider a struct like this
pub struct StandardMaterial {
base_color: Color
base_color_texture: Option<Handle<Image>>
..
}
base_color
can be reflected and displayed, but what about the Handle<Image>
? To really display its value, you would need to access the Assets<Image>
resource and look the handle up.
This is what the Context
struct and the short_circuit
ing is about.
You can put a &mut World
into the Context and InspectorUi::new(type_registry, cx, short_circuit, short_circuit_readonly)
accepts to short circuiting methods, which will be asked at every step in the recursive reflect walking if you know a better way to display the struct.
We provide short circuiting methods capable of displaying Handle
s which look something like this:
fn short_circuit_handle(..) {
if value is Handle<?> {
let assets = context.world.resource::Assets<?asset_type>();
let value = assets.get_mut(handle);
return ui_for_reflect(value, ..);
}
return None;
}
As a user, you don’t have to worry about this, if you just use the InspectorUi::for_bevy
constructor:
let world: &mut World = ..;
let standard_material: Handle<StandardMaterial> = ..;
let mut cx = Context {
world: Some(world.into()),
};
let mut env = InspectorUi::for_bevy(type_registry, &mut cx);
env.ui_for_reflect(value, ui)
This will just work and display the value of the StandardMaterial
.
Side node about change detection
If you have a Mut
value and directly write env.ui_for_reflect(&mut *value, ui)
you will always trigger change detection.
The proper way to write this is
let changed = env.ui_for_reflect(value.bypass_change_detection(), ui);
if changed {
value.set_changed();
}
bevy_inspector
This module contains functions for quickly building UI for bevy apps.
The following example speaks for itself, for more info just look at the module docs.
use bevy_inspector_egui::bevy_inspector;
#[derive(Debug, Clone, Eq, PartialEq, Hash, Reflect)]
enum AppState { A, B, C }
fn show_ui(world: &mut World, ui: &mut egui::Ui) {
ui.heading("Msaa resource");
bevy_inspector::ui_for_resource::<Msaa>(world, ui);
ui.heading("App State");
bevy_inspector::ui_for_state::<AppState>(world, ui);
egui::CollapsingHeader::new("Entities")
.default_open(true)
.show(ui, |ui| {
bevy_inspector::ui_for_world_entities(world, ui);
});
egui::CollapsingHeader::new("Resources").show(ui, |ui| {
bevy_inspector::ui_for_resources(world, ui);
});
egui::CollapsingHeader::new("Assets").show(ui, |ui| {
bevy_inspector::ui_for_all_assets(world, ui);
});
}
quick
Plugins you can easily add to your app.
Pro: less typing
Con: less flexibility
#[derive(Reflect, Resource, Default, InspectorOptions)]
#[reflect(Resource, InspectorOptions)]
struct Configuration {
#[inspector(min = 0.0)]
value: f32,
}
#[derive(Reflect, Debug, Clone, Eq, PartialEq, Hash)]
enum AppState { A, B, C }
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(WorldInspectorPlugin)
.add_plugin(ResourceInspectorPlugin::<Configuration>::default())
.add_plugin(StateInspectorPlugin::<AppState>::default())
.add_state(AppState::A)
.init_resource::<Configuration>()
.register_type::<Configuration>()
.register_type::<AppState>()
.add_startup_system(setup)
.run();
}
If you want more control over the presentation (egui window vs side panel vs egui_dock
), or over the content, you can just add an exclusive system like this:
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(DefaultInspectorConfigPlugin)
.add_plugin(EguiPlugin)
.add_system(ui)
.run();
}
fn ui(world: &mut World) {
let egui_context = world
.resource_mut::<bevy_egui::EguiContext>()
.ctx_mut()
.clone();
egui::Window::new("UI").show(&egui_context, |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
bevy_inspector_egui::bevy_inspector::ui_for_world(world, ui);
ui.allocate_space(ui.available_size());
});
});
}
Migration Guide
WorldInspectorPlugin
Before
use bevy_inspector_egui::WorldInspectorPlugin;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(WorldInspectorPlugin)
.run();
}
After
use bevy_inspector_egui::quick::WorldInspectorPlugin;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(WorldInspectorPlugin)
.run();
}
Basic usage of the world inspector doesn’t actually change. The only difference is that registration works differently now and WorldInspectorParams
is gone. If you want to have more customization, copy the implementation, it’s ~10 lines.
InspectorPlugin
To display a single resource, the InspectorPlugin
has been replaced with the ResourceInspectorPlugin
:
Before
#[derive(Resource, Inspectable, Default)]
struct Data {
the: f32,
values: String,
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(InspectorPlugin::<Data>::new())
.run();
}
After
#[derive(Reflect, Resource, Default)]
#[reflect(Resource)]
struct Data {
the: f32,
values: String,
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugin(ResourceInspectorPlugin::<Data>::new())
.init_type::<Default>()
.register_type::<Data>()
.run();
}
#[inspectable]
Attributes
Before
The Reflect
trait is not capable of reading and storing arbitrary attributes. Instead, you can add the InspectorOptions
derive which will parse and typecheck the attributes, and insert a type-erased options struct into the type registry.
#[derive(Resource, Inspectable)]
struct Data {
#[inspectable(min = 10.0, max = 70.0)]
font_size: f32,
}
After
#[derive(Reflect, Resource, InspectorOptions)]
#[reflect(Resource, InspectorOptions)]
struct Data {
#[inspector(min = 10.0, max = 70.0)]
font_size: f32,
}
...
app.register_type::<Data>()
As I said in the beginning, if you have any feedback please open an issue or ping me on discord :)
bevy-inspector-egui
v0.15.0-pre.0
Announcement and Migration GuideI just released the next version
0.15.0-pre.0
ofbevy-inspector-egui
and would like to gather some feedback before the actual release.If you just want a stable release for bevy
0.9
, feel free to continue usingbevy-inspector-egui
0.14
.If you miss any features from the previous release, or have suggestions for features or API design, please open an issue at bevy-inspector-egui/issues or ping me on the bevy discord (in
#project-collaboration
@dubi steinkek#2182
).You can check out the
0.15.0
docs ondocs.rs
: https://docs.rs/bevy-inspector-egui/0.15.0-preWhat’s new in the update?
This release features the removal of the
Inspectable
trait in favor of reusing the existingReflect
trait. This leads to less derive boilerplate and more reusability, paving the way for non-egui Inspector implementations (in the general sense, could also be autocomplete in a console) and usage outside of bevy.New APIs
The release is a rewrite from scratch so here’s the new layout of the crate. For more detail, you can browse the crate docs.
The main modules are:
egui_reflect_inspector
- General-purpose machinery for displaying Reflect types using eguibevy_inspector
- Methods for displaying bevy resources, assets and entitiesinspector_options
- Way of associating options to fields using InspectorOptionsquick
- Easy plugins for showing UI panels.egui_reflect_inspector
This module has no knowledge of bevy and provides general purpose methods for displaying arbitrary
&mut dyn Reflect
or&dyn Reflect
(that’s right, we support readonly UI now).Most of the time however you can just use either the
quick
module for an simpleWorldInspectorPlugin
/ResourceInspectorPlugin
/StateInspectorPlugin
plugins, or thebevy_inspector
module for functions likeui_for_resource
,ui_for_entity
, etc.This is the minimum needed to display a value: the value, the
Ui
and the type registry. This is enough for basic usage, but consider a struct like thisbase_color
can be reflected and displayed, but what about theHandle<Image>
? To really display its value, you would need to access theAssets<Image>
resource and look the handle up.This is what the
Context
struct and theshort_circuit
ing is about.You can put a
&mut World
into the Context andInspectorUi::new(type_registry, cx, short_circuit, short_circuit_readonly)
accepts to short circuiting methods, which will be asked at every step in the recursive reflect walking if you know a better way to display the struct.We provide short circuiting methods capable of displaying
Handle
s which look something like this:As a user, you don’t have to worry about this, if you just use the
InspectorUi::for_bevy
constructor:This will just work and display the value of the
StandardMaterial
.Side node about change detection
If you have a
Mut
value and directly writeenv.ui_for_reflect(&mut *value, ui)
you will always trigger change detection.The proper way to write this is
bevy_inspector
This module contains functions for quickly building UI for bevy apps.
The following example speaks for itself, for more info just look at the module docs.
quick
Plugins you can easily add to your app.
Pro: less typing
Con: less flexibility
If you want more control over the presentation (egui window vs side panel vs
egui_dock
), or over the content, you can just add an exclusive system like this:Migration Guide
WorldInspectorPlugin
Before
After
Basic usage of the world inspector doesn’t actually change. The only difference is that registration works differently now and
WorldInspectorParams
is gone. If you want to have more customization, copy the implementation, it’s ~10 lines.InspectorPlugin
To display a single resource, the
InspectorPlugin
has been replaced with theResourceInspectorPlugin
:Before
After
#[inspectable]
AttributesBefore
The
Reflect
trait is not capable of reading and storing arbitrary attributes. Instead, you can add theInspectorOptions
derive which will parse and typecheck the attributes, and insert a type-erased options struct into the type registry.After
As I said in the beginning, if you have any feedback please open an issue or ping me on discord :)