Getting rid of most of unsafe stuff
This commit is contained in:
parent
20f37715e4
commit
e464c49592
|
@ -2,37 +2,24 @@ use std::{alloc::Layout, cell::Cell, num::NonZeroU32};
|
|||
|
||||
use bevy::{
|
||||
core::Name,
|
||||
ecs::world::DeferredWorld,
|
||||
ecs::system::SystemParam,
|
||||
gltf::GltfExtras,
|
||||
log::{info, warn},
|
||||
prelude::{HierarchyQueryExt, Parent, QueryState, With, World},
|
||||
prelude::{HierarchyQueryExt, Parent, Query, With},
|
||||
reflect::ReflectDeserialize,
|
||||
scene::{InstanceId, SceneInstance},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
pub(crate) struct BadWorldAccess {
|
||||
world: *mut World,
|
||||
names: QueryState<(bevy::ecs::entity::Entity, &'static Name), With<GltfExtras>>,
|
||||
hierarchy: QueryState<&'static Parent, ()>,
|
||||
scene_instances: QueryState<&'static SceneInstance, ()>,
|
||||
}
|
||||
|
||||
impl BadWorldAccess {
|
||||
pub unsafe fn new(world: &mut World) -> Self {
|
||||
BadWorldAccess {
|
||||
world,
|
||||
// We have to check that we focus on a node, not a mesh with the same name.
|
||||
// Currently, the only possible way of checking this is with `GltfExtras`, so selected entities must at least have one component.
|
||||
names: world.query_filtered::<(bevy::ecs::entity::Entity, &Name), With<GltfExtras>>(),
|
||||
hierarchy: world.query::<&Parent>(),
|
||||
scene_instances: world.query::<&SceneInstance>(),
|
||||
}
|
||||
}
|
||||
#[derive(SystemParam)]
|
||||
pub(crate) struct BadWorldAccess<'w, 's> {
|
||||
pub(crate) names: Query<'w, 's, (bevy::ecs::entity::Entity, &'static Name), With<GltfExtras>>,
|
||||
pub(crate) hierarchy: Query<'w, 's, &'static Parent, ()>,
|
||||
pub(crate) scene_instances: Query<'w, 's, &'static SceneInstance, ()>,
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub(crate) static BAD_WORLD_ACCESS: Cell<Option<BadWorldAccess>> = Cell::new(None);
|
||||
pub(crate) static BAD_WORLD_ACCESS: Cell<Option<BadWorldAccess<'static, 'static>>> = Cell::new(None);
|
||||
pub(crate) static INSTANCE_ID: Cell<Option<InstanceId>> = Cell::new(None);
|
||||
}
|
||||
|
||||
|
@ -70,25 +57,20 @@ impl<'de> Deserialize<'de> for Entity {
|
|||
let entity = if let Some(name) = entity_data.name {
|
||||
info!("Found name {name}");
|
||||
let BadWorldAccess {
|
||||
world,
|
||||
mut names,
|
||||
mut hierarchy,
|
||||
mut scene_instances,
|
||||
names,
|
||||
hierarchy,
|
||||
scene_instances,
|
||||
} = BAD_WORLD_ACCESS.take().expect("No bad world access :c");
|
||||
let instance = INSTANCE_ID.get().expect("No instance id set :c");
|
||||
|
||||
let mut target = None;
|
||||
let w = unsafe { &*world.cast_const() };
|
||||
'search: for (e, n) in names.iter(w) {
|
||||
'search: for (e, n) in names.iter() {
|
||||
if !name.eq(n.as_str()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut dw = DeferredWorld::from(unsafe { &mut *world });
|
||||
let hierarchy = dw.query(&mut hierarchy);
|
||||
|
||||
for parent in hierarchy.iter_ancestors(e) {
|
||||
let Ok(id) = scene_instances.get(w, parent) else {
|
||||
let Ok(id) = scene_instances.get(parent) else {
|
||||
continue;
|
||||
};
|
||||
if instance.eq(id) {
|
||||
|
@ -99,7 +81,6 @@ impl<'de> Deserialize<'de> for Entity {
|
|||
}
|
||||
|
||||
BAD_WORLD_ACCESS.set(Some(BadWorldAccess {
|
||||
world,
|
||||
names,
|
||||
hierarchy,
|
||||
scene_instances,
|
||||
|
|
|
@ -6,12 +6,13 @@ use bevy::{
|
|||
entity::Entity,
|
||||
query::{Added, Without},
|
||||
reflect::{AppTypeRegistry, ReflectComponent},
|
||||
world::{DeferredWorld, World},
|
||||
system::{SystemParam, SystemState},
|
||||
world::World,
|
||||
},
|
||||
gltf::{GltfExtras, GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras},
|
||||
hierarchy::Parent,
|
||||
log::{debug, warn},
|
||||
prelude::HierarchyQueryExt,
|
||||
prelude::{HierarchyQueryExt, Local, Query, Res},
|
||||
reflect::{Reflect, TypeRegistration},
|
||||
scene::SceneInstance,
|
||||
utils::HashMap,
|
||||
|
@ -61,18 +62,56 @@ fn find_entity_components(
|
|||
(target_entity, reflect_components)
|
||||
}
|
||||
|
||||
#[derive(SystemParam)]
|
||||
#[doc(hidden)]
|
||||
pub struct ExtrasComponentQueries<'w, 's> {
|
||||
extras: Query<
|
||||
'w,
|
||||
's,
|
||||
(Entity, Option<&'static Name>, &'static GltfExtras),
|
||||
(Added<GltfExtras>, Without<GltfProcessed>),
|
||||
>,
|
||||
scene_extras: Query<
|
||||
'w,
|
||||
's,
|
||||
(Entity, Option<&'static Name>, &'static GltfSceneExtras),
|
||||
(Added<GltfSceneExtras>, Without<GltfProcessed>),
|
||||
>,
|
||||
mesh_extras: Query<
|
||||
'w,
|
||||
's,
|
||||
(Entity, Option<&'static Name>, &'static GltfMeshExtras),
|
||||
(Added<GltfMeshExtras>, Without<GltfProcessed>),
|
||||
>,
|
||||
material_extras: Query<
|
||||
'w,
|
||||
's,
|
||||
(Entity, Option<&'static Name>, &'static GltfMaterialExtras),
|
||||
(Added<GltfMaterialExtras>, Without<GltfProcessed>),
|
||||
>,
|
||||
// Hierarchy and Scene instances are both here and in BadWorldAccess, but they don't clash because read-only.
|
||||
bad_world_access: BadWorldAccess<'w, 's>,
|
||||
hierarchy: Query<'w, 's, &'static Parent>,
|
||||
scene_instances: Query<'w, 's, &'static SceneInstance>,
|
||||
type_registry: Res<'w, AppTypeRegistry>,
|
||||
}
|
||||
|
||||
/// main function: injects components into each entity in gltf files that have `gltf_extras`, using reflection
|
||||
pub fn add_components_from_gltf_extras(world: &mut World) {
|
||||
let mut extras = world.query_filtered::<(Entity, Option<&Name>, &GltfExtras), (Added<GltfExtras>, Without<GltfProcessed>)>();
|
||||
let mut scene_extras = world.query_filtered::<(Entity, Option<&Name>, &GltfSceneExtras), (Added<GltfSceneExtras>, Without<GltfProcessed>)>();
|
||||
let mut mesh_extras = world.query_filtered::<(Entity, Option<&Name>, &GltfMeshExtras), (Added<GltfMeshExtras>, Without<GltfProcessed>)>();
|
||||
let mut material_extras = world.query_filtered::<(Entity, Option<&Name>, &GltfMaterialExtras), (Added<GltfMaterialExtras>, Without<GltfProcessed>)>();
|
||||
|
||||
let mut scene_instances = world.query::<&SceneInstance>();
|
||||
|
||||
let mut hierarchy_state = world.query::<&Parent>();
|
||||
let mut __unsafe_dw = DeferredWorld::from(unsafe { &mut *(world as *mut _) });
|
||||
let hierarchy = __unsafe_dw.query(&mut hierarchy_state);
|
||||
pub fn add_components_from_gltf_extras(
|
||||
world: &mut World,
|
||||
mut queries_state: Local<Option<SystemState<ExtrasComponentQueries<'_, '_>>>>,
|
||||
) {
|
||||
let state = queries_state.get_or_insert_with(|| SystemState::new(world));
|
||||
let ExtrasComponentQueries {
|
||||
extras,
|
||||
scene_extras,
|
||||
mesh_extras,
|
||||
material_extras,
|
||||
bad_world_access,
|
||||
hierarchy,
|
||||
scene_instances,
|
||||
type_registry,
|
||||
} = state.get_mut(world);
|
||||
|
||||
let mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>> =
|
||||
HashMap::new();
|
||||
|
@ -80,11 +119,11 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
// let gltf_components_config = world.resource::<GltfComponentsConfig>();
|
||||
|
||||
unsafe {
|
||||
// SAFETY: we don't do anything harmful until taking this, and have full world access
|
||||
fake_entity::BAD_WORLD_ACCESS.set(Some(BadWorldAccess::new(world)));
|
||||
// SAFETY: we set this to `None` again before using world again and fake_entity just uses it in that time.
|
||||
fake_entity::BAD_WORLD_ACCESS.set(Some(core::mem::transmute(bad_world_access)));
|
||||
}
|
||||
|
||||
for (entity, name, extra) in extras.iter(world) {
|
||||
for (entity, name, extra) in extras.iter() {
|
||||
let parent = hierarchy.get(entity).ok();
|
||||
debug!(
|
||||
"Gltf Extra: Name: {:?}, entity {:?}, parent: {:?}, extras {:?}",
|
||||
|
@ -93,7 +132,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
|
||||
if let Some(instance) = hierarchy
|
||||
.iter_ancestors(entity)
|
||||
.find_map(|p| scene_instances.get(world, p).ok())
|
||||
.find_map(|p| scene_instances.get(p).ok())
|
||||
{
|
||||
fake_entity::INSTANCE_ID.set(Some(*instance.deref()));
|
||||
} else {
|
||||
|
@ -101,7 +140,6 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
fake_entity::INSTANCE_ID.set(None);
|
||||
};
|
||||
|
||||
let type_registry: &AppTypeRegistry = world.resource();
|
||||
let mut type_registry = type_registry.write();
|
||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &mut type_registry);
|
||||
// let name = name.unwrap_or(&Name::new(""));
|
||||
|
@ -112,7 +150,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
entity_components.insert(target_entity, updated_components);
|
||||
}
|
||||
|
||||
for (entity, name, extra) in scene_extras.iter(world) {
|
||||
for (entity, name, extra) in scene_extras.iter() {
|
||||
let parent = hierarchy.get(entity).ok();
|
||||
debug!(
|
||||
"Gltf Scene Extra: Name: {:?}, entity {:?}, parent: {:?}, scene_extras {:?}",
|
||||
|
@ -121,7 +159,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
|
||||
if let Some(instance) = hierarchy
|
||||
.iter_ancestors(entity)
|
||||
.find_map(|p| scene_instances.get(world, p).ok())
|
||||
.find_map(|p| scene_instances.get(p).ok())
|
||||
{
|
||||
fake_entity::INSTANCE_ID.set(Some(*instance.deref()));
|
||||
} else {
|
||||
|
@ -129,7 +167,6 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
fake_entity::INSTANCE_ID.set(None);
|
||||
};
|
||||
|
||||
let type_registry: &AppTypeRegistry = world.resource();
|
||||
let mut type_registry = type_registry.write();
|
||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &mut type_registry);
|
||||
|
||||
|
@ -138,7 +175,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
entity_components.insert(target_entity, updated_components);
|
||||
}
|
||||
|
||||
for (entity, name, extra) in mesh_extras.iter(world) {
|
||||
for (entity, name, extra) in mesh_extras.iter() {
|
||||
let parent = hierarchy.get(entity).ok();
|
||||
debug!(
|
||||
"Gltf Mesh Extra: Name: {:?}, entity {:?}, parent: {:?}, mesh_extras {:?}",
|
||||
|
@ -147,7 +184,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
|
||||
if let Some(instance) = hierarchy
|
||||
.iter_ancestors(entity)
|
||||
.find_map(|p| scene_instances.get(world, p).ok())
|
||||
.find_map(|p| scene_instances.get(p).ok())
|
||||
{
|
||||
fake_entity::INSTANCE_ID.set(Some(*instance.deref()));
|
||||
} else {
|
||||
|
@ -155,7 +192,6 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
fake_entity::INSTANCE_ID.set(None);
|
||||
};
|
||||
|
||||
let type_registry: &AppTypeRegistry = world.resource();
|
||||
let mut type_registry = type_registry.write();
|
||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &mut type_registry);
|
||||
|
||||
|
@ -164,7 +200,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
entity_components.insert(target_entity, updated_components);
|
||||
}
|
||||
|
||||
for (entity, name, extra) in material_extras.iter(world) {
|
||||
for (entity, name, extra) in material_extras.iter() {
|
||||
let parent = hierarchy.get(entity).ok();
|
||||
debug!(
|
||||
"Name: {:?}, entity {:?}, parent: {:?}, material_extras {:?}",
|
||||
|
@ -173,7 +209,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
|
||||
if let Some(instance) = hierarchy
|
||||
.iter_ancestors(entity)
|
||||
.find_map(|p| scene_instances.get(world, p).ok())
|
||||
.find_map(|p| scene_instances.get(p).ok())
|
||||
{
|
||||
fake_entity::INSTANCE_ID.set(Some(*instance.deref()));
|
||||
} else {
|
||||
|
@ -181,7 +217,6 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||
fake_entity::INSTANCE_ID.set(None);
|
||||
};
|
||||
|
||||
let type_registry: &AppTypeRegistry = world.resource();
|
||||
let mut type_registry = type_registry.write();
|
||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &mut type_registry);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::any::TypeId;
|
||||
|
||||
use bevy::log::{debug, info, warn};
|
||||
use bevy::reflect::serde::{ReflectDeserializer, ReflectSerializer};
|
||||
use bevy::log::{debug, warn};
|
||||
use bevy::reflect::serde::ReflectDeserializer;
|
||||
use bevy::reflect::{GetTypeRegistration, Reflect, TypeRegistration, TypeRegistry};
|
||||
use bevy::utils::HashMap;
|
||||
use ron::Value;
|
||||
|
|
Loading…
Reference in New Issue