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
#![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>) { /* */ } //! ``` //! #[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: &'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, 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: &'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: &'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. 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; /// Required setup for the bevy application, e.g. registering Resources. #[allow(unused_variables)] fn setup(app: &mut AppBuilder) {} }