1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
#![warn(missing_docs)] #![allow( clippy::unit_arg, clippy::needless_doctest_main, clippy::too_many_arguments, clippy::collapsible_if )] //! This crate provides the ability to annotate structs with a `#[derive(Inspectable)]`, //! which opens a debug interface using [egui](https://github.com/emilk/egui) where you can visually edit the values of your struct live. //! //! Your struct will then be available to you as a bevy resource. //! //! ## Example //! ```rust //! use bevy_inspector_egui::Inspectable; //! //! #[derive(Inspectable, Default)] //! struct Data { //! should_render: bool, //! text: String, //! #[inspectable(min = 42.0, max = 100.0)] //! size: f32, //! } //! ``` //! Add the [`InspectorPlugin`] to your App. //! ```rust,no_run //! use bevy_inspector_egui::InspectorPlugin; //! # use bevy::prelude::*; //! //! # #[derive(bevy_inspector_egui::Inspectable, Default)] struct Data {} //! fn main() { //! App::build() //! .add_plugins(DefaultPlugins) //! .add_plugin(InspectorPlugin::<Data>::new()) //! .add_system(your_system.system()) //! .run(); //! } //! //! # fn your_system() {} //! // fn your_system(data: Res<Data>) { /* */ } //! ``` //! //! The list of built-in attributes is documented [here](trait.Inspectable.html#default-attributes). //! //! ## World Inspector //! //! If you want to display all world entities you can add the [`WorldInspectorPlugin`]: //! ```rust,no_run //! use bevy::prelude::*; //! use bevy_inspector_egui::WorldInspectorPlugin; //! //! fn main() { //! App::build() //! .add_plugins(DefaultPlugins) //! .add_plugin(WorldInspectorPlugin::new()) //! .add_startup_system(setup.system()) //! .run(); //! } //! # fn setup() {} //! ``` //! You can configure it by inserting the [`WorldInspectorParams`] resource. #[macro_use] mod utils; /// Utitly types implementing [`Inspectable`](crate::Inspectable) pub mod widgets; #[allow(missing_docs)] mod impls; mod plugin; /// configuration for the [`WorldInspectorPlugin`](crate::world_inspector::WorldInspectorPlugin) mod world_inspector; use std::hash::Hasher; use bevy::prelude::{AppBuilder, World}; use egui::CtxRef; pub use world_inspector::{InspectableRegistry, WorldInspectorParams, WorldInspectorPlugin}; /// [`Inspectable`] implementation for foreign types implementing [`Reflect`](bevy::reflect::Reflect) pub mod reflect; pub use bevy_egui; pub use bevy_egui::egui; /// Derives the [`Inspectable`](Inspectable) trait. pub use bevy_inspector_egui_derive::Inspectable; pub use plugin::InspectorPlugin; /// Attributes for the built-in [`Inspectable`](Inspectable) implementations pub mod options { pub use crate::impls::*; pub use crate::widgets::button::ButtonAttributes; pub use crate::widgets::new_window::WindowAttributes; pub use crate::world_inspector::impls::EntityAttributes; } /// The context passed to [`Inspectable::ui`]. pub struct Context<'a> { /// egui ui context pub ui_ctx: Option<&'a CtxRef>, /// The world is only available when not using `InspectablePlugin::shared()` world: Option<*mut World>, /// Something to distinguish between siblings. pub id: Option<u64>, } impl<'a> Context<'a> { /// Gives mutable access to the [bevy::ecs::world::World] /// # Safety /// The pointer provided in `Context::new_raw` must give unique access. pub unsafe fn world(&'a self) -> Option<&'a mut World> { self.world.map(|ptr| &mut *ptr) } } impl<'a> Context<'a> { /// Create new context with exclusive access to the `World` pub fn new(ui_ctx: &'a CtxRef, world: &'a mut World) -> Self { Context { ui_ctx: Some(ui_ctx), world: Some(world as *mut _), id: None, } } /// Create a new context with access to the world /// # Safety /// The `world` pointer must come from a mutable reference to a world and no /// other threads must be writing to it. pub unsafe fn new_ptr(ui_ctx: Option<&'a CtxRef>, world: *mut World) -> Self { Context { ui_ctx, world: Some(world), id: None, } } /// Creates a context without access to `World` pub fn new_shared(ui_ctx: Option<&'a CtxRef>) -> Self { Context { ui_ctx, world: None, id: None, } } /// Same context but with a specified `id` pub fn with_id(&self, id: u64) -> Self { let mut hasher = std::collections::hash_map::DefaultHasher::default(); if let Some(id) = self.id { hasher.write_u64(id); } hasher.write_u64(id); let id = hasher.finish(); Context { id: Some(id), ..*self } } /// Returns the [id](struct.Context.html#structfield.id) if present, otherwise a dummy id. pub fn id(&self) -> egui::Id { let dummy_id = egui::Id::new(42); match self.id { Some(id) => egui::Id::new(id), None => dummy_id, } } } /// This trait describes how a struct should be displayed. /// It can be derived for structs and enums, see the [crate-level docs](index.html) for how to do that. /// /// ## Default attributes /// - **ignore**: hides the field in the inspector /// - **label**: provides a label instead of using the field name /// - **read_only**: disables the UI /// - **collapse**: wraps the ui in an [`egui::CollapsingHeader`]. /// - **default**: only for enums, specifies the default value when selecting a new variant /// - **wrapper**: wrap field UI in a custom function. Demo in the [rust_types example](https://github.com/jakobhellermann/bevy-inspector-egui/blob/main/examples/rust_types.rs#L20). pub trait Inspectable { /// The `Attributes` associated type specifies what attributes can be passed to a field. /// See the following snippet for an example: /// ```rust,no_run /// # use bevy_inspector_egui::{egui, Inspectable, Context}; /// struct MyCustomType; /// # #[derive(Clone, Default)] /// struct MyWidgetAttributes { a: f32, b: Option<String> } /// /// impl Inspectable for MyCustomType { /// type Attributes = MyWidgetAttributes; /// /// fn ui(&mut self, _: &mut egui::Ui, options: MyWidgetAttributes, context: &Context) -> bool { /// println!("a = {}, b = {:?}", options.a, options.b); /// false /// } /// } /// /// // ... /// /// #[derive(Inspectable)] /// struct InspectorData { /// #[inspectable(a = 10.0, b = None)] /// value: MyCustomType, /// } /// ``` type Attributes: Default + Clone; /// This methods is responsible for building the egui ui. /// Returns whether any data was modified. fn ui(&mut self, ui: &mut egui::Ui, options: Self::Attributes, context: &Context) -> bool; /// Displays the value without any context. Useful for usage outside of the plugins, where /// there is no access to the world or [`EguiContext`](bevy_egui::EguiContext). fn ui_raw(&mut self, ui: &mut egui::Ui, options: Self::Attributes) { let empty_context = Context::new_shared(None); self.ui(ui, options, &empty_context); } /// Required setup for the bevy application, e.g. registering events. Note that this method will run for every instance of a type. #[allow(unused_variables)] fn setup(app: &mut AppBuilder) {} }