use std::any::*;
use bevy_ecs::component::ComponentId;
use bevy_ecs::prelude::*;
use bevy_ecs::world::CommandQueue;
use bevy_inspector_egui::egui::{self, Frame};
use bevy_inspector_egui::reflect_inspector::{Context, InspectorUi};
use bevy_inspector_egui::restricted_world_view::RestrictedWorldView;
use bevy_log::warn;
use bevy_reflect::*;
use std::hash::Hash;
pub mod components;
pub mod plugins;
pub mod resources;
pub mod stylesheets;
pub mod systems;
pub mod tables;
pub mod states;
pub enum Display {
Side(Side),
Window,
}
pub enum Side {
Left,
Right,
}
pub use components::*;
pub use plugins::*;
pub use resources::*;
pub use stylesheets::*;
pub use systems::*;
#[derive(Reflect, Clone, PartialEq, Hash, Eq, Debug)]
pub struct TypeIdNameCache {
pub(crate) type_id: TypeId,
pub(crate) name: String,
}
impl TypeIdNameCache {
pub fn type_id(&self) -> TypeId {
self.type_id
}
pub fn name(&self) -> &str {
&self.name
}
pub fn new_typed<T: Reflect>() -> Self {
Self {
type_id: TypeId::of::<T>(),
name: std::any::type_name::<T>().to_owned(),
}
}
}
pub fn component_info_for(
world: &mut RestrictedWorldView<'_>,
component: &TypeIdNameCache,
) -> Option<(String, ComponentId, Option<TypeId>, usize)> {
let component_id = match world.world().components().get_id(component.type_id) {
Some(id) => id,
None => {
warn!("Could not get component id for {:#}", component.name);
return None;
}
};
let info = world.world().components().get_info(component_id)?;
let name = pretty_type_name::pretty_type_name_str(info.name());
return Some((name, component_id, info.type_id(), info.layout().size()));
}
pub fn ui_for_resource(
world: &mut World,
ui: &mut egui::Ui,
id: egui::Id,
type_registry: &TypeRegistry,
resource: &TypeIdNameCache,
) {
let mut queue = CommandQueue::default();
let resource_type_id = resource.type_id();
let id = id.with(resource_type_id);
{
let mut world_view = RestrictedWorldView::new(world);
let (mut resource_view, world_view) = world_view.split_off_resource(resource_type_id);
let mut cx = Context {
world: Some(world_view),
queue: Some(&mut queue),
};
let mut env = InspectorUi::for_bevy(type_registry, &mut cx);
let mut resource =
match resource_view.get_resource_reflect_mut_by_id(resource_type_id, type_registry) {
Ok(resource) => resource,
Err(err) => {
ui.label(format!(
"unable to display: {:#?}, Reason: {:#?}",
resource_type_id, err
));
return;
} };
let changed = env.ui_for_reflect_with_options(
resource.bypass_change_detection().as_partial_reflect_mut(),
ui,
id.with(resource_type_id),
&(),
);
if changed {
resource.set_changed();
}
}
queue.apply(world);
}
pub fn ui_for_components(
world: &mut RestrictedWorldView<'_>,
mut queue: Option<&mut CommandQueue>,
entity: Entity,
ui: &mut egui::Ui,
id: egui::Id,
type_registry: &TypeRegistry,
components: &Vec<&TypeIdNameCache>,
) {
for component in components.iter() {
let Some((name, component_id, component_type_id, size)) =
component_info_for(world, component)
else {
return;
};
let id = id.with(component_id);
let header = egui::CollapsingHeader::new(&name)
.id_salt(id)
.default_open(false);
let Some(component_type_id) = component_type_id else {
return;
};
let (mut component_view, world) = world.split_off_component((entity, component_type_id));
let mut cx = Context {
world: Some(world),
#[allow(clippy::needless_option_as_deref)]
queue: queue.as_deref_mut(),
};
let Ok(mut value) = component_view
.get_entity_component_reflect(entity, component_type_id, type_registry)
.inspect_err(|err| {
let mabye_err = match err {
bevy_inspector_egui::restricted_world_view::Error::NoAccessToResource(_) => {
Some(err)
}
bevy_inspector_egui::restricted_world_view::Error::NoAccessToComponent(_) => {
Some(err)
}
bevy_inspector_egui::restricted_world_view::Error::ResourceDoesNotExist(_) => {
None
}
bevy_inspector_egui::restricted_world_view::Error::ComponentDoesNotExist(_) => {
None
}
bevy_inspector_egui::restricted_world_view::Error::NoComponentId(_) => {
Some(err)
}
bevy_inspector_egui::restricted_world_view::Error::NoTypeRegistration(_) => {
Some(err)
}
bevy_inspector_egui::restricted_world_view::Error::NoTypeData(_, _) => {
Some(err)
}
};
if let Some(msg) = mabye_err {
ui.label(format!("{:#?}", msg));
}
})
else {
continue;
};
if size == 0 {
header.show(ui, |_| {});
continue;
}
header.show(ui, |ui| {
ui.reset_style();
let inspector_changed = InspectorUi::for_bevy(type_registry, &mut cx)
.ui_for_reflect_with_options(
value.bypass_change_detection().as_partial_reflect_mut(),
ui,
id.with(component_id),
&(),
);
if inspector_changed {
value.set_changed();
}
});
ui.reset_style();
}
}