HOLY SHIT THAT WORKS

This commit is contained in:
DasLixou 2024-08-22 15:45:26 +02:00
parent 3e14cc06bf
commit 4aa2ef382c
8 changed files with 674 additions and 12 deletions

View File

@ -1,11 +1,41 @@
use std::{alloc::Layout, num::NonZeroU32};
use std::{alloc::Layout, cell::Cell, num::NonZeroU32};
use bevy::{
core::Name,
ecs::world::DeferredWorld,
gltf::GltfExtras,
log::{info, warn},
prelude::{HierarchyQueryExt, Parent, QueryState, With, World},
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>(),
}
}
}
thread_local! {
pub(crate) static BAD_WORLD_ACCESS: Cell<Option<BadWorldAccess>> = Cell::new(None);
pub(crate) static INSTANCE_ID: Cell<Option<InstanceId>> = Cell::new(None);
}
const _: () = {
let real = Layout::new::<bevy::ecs::entity::Entity>();
let fake = Layout::new::<Entity>();
@ -39,7 +69,46 @@ 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,
} = 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) {
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 {
continue;
};
if instance.eq(id) {
target = Some(e);
break 'search;
}
}
}
BAD_WORLD_ACCESS.set(Some(BadWorldAccess {
world,
names,
hierarchy,
scene_instances,
}));
target.unwrap_or_else(|| {
warn!("No entity found for '{name}' - perhaps it doesn't contain any components from blender?");
bevy::ecs::entity::Entity::PLACEHOLDER
})
} else {
warn!("No object was specified for Entity relation, using `Entity::PLACEHOLDER`.");
bevy::ecs::entity::Entity::PLACEHOLDER

View File

@ -1,20 +1,26 @@
use std::ops::Deref;
use bevy::{
core::Name,
ecs::{
entity::Entity,
query::{Added, Without},
reflect::{AppTypeRegistry, ReflectComponent},
world::World,
world::{DeferredWorld, World},
},
gltf::{GltfExtras, GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras},
hierarchy::Parent,
log::{debug, warn},
prelude::HierarchyQueryExt,
reflect::{Reflect, TypeRegistration},
scene::SceneInstance,
utils::HashMap,
};
use crate::{ronstring_to_reflect_component, GltfProcessed};
use super::fake_entity::{self, BadWorldAccess};
// , mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>
fn find_entity_components(
entity: Entity,
@ -57,22 +63,44 @@ fn find_entity_components(
/// 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, Option<&Parent>), (Added<GltfExtras>, Without<GltfProcessed>)>();
let mut scene_extras = world.query_filtered::<(Entity, Option<&Name>, &GltfSceneExtras, Option<&Parent>), (Added<GltfSceneExtras>, Without<GltfProcessed>)>();
let mut mesh_extras = world.query_filtered::<(Entity, Option<&Name>, &GltfMeshExtras, Option<&Parent>), (Added<GltfMeshExtras>, Without<GltfProcessed>)>();
let mut material_extras = world.query_filtered::<(Entity, Option<&Name>, &GltfMaterialExtras, Option<&Parent>), (Added<GltfMaterialExtras>, Without<GltfProcessed>)>();
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);
let mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>> =
HashMap::new();
// let gltf_components_config = world.resource::<GltfComponentsConfig>();
for (entity, name, extra, parent) in extras.iter(world) {
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)));
}
for (entity, name, extra) in extras.iter(world) {
let parent = hierarchy.get(entity).ok();
debug!(
"Gltf Extra: Name: {:?}, entity {:?}, parent: {:?}, extras {:?}",
name, entity, parent, extra
);
if let Some(instance) = hierarchy
.iter_ancestors(entity)
.find_map(|p| scene_instances.get(world, p).ok())
{
fake_entity::INSTANCE_ID.set(Some(*instance.deref()));
} else {
warn!("Can't find higher-hierarchy `SceneInstance` for entity '{name:?}'");
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);
@ -80,15 +108,27 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
let (target_entity, updated_components) =
find_entity_components(entity, name, parent, reflect_components, &entity_components);
entity_components.insert(target_entity, updated_components);
}
for (entity, name, extra, parent) in scene_extras.iter(world) {
for (entity, name, extra) in scene_extras.iter(world) {
let parent = hierarchy.get(entity).ok();
debug!(
"Gltf Scene Extra: Name: {:?}, entity {:?}, parent: {:?}, scene_extras {:?}",
name, entity, parent, extra
);
if let Some(instance) = hierarchy
.iter_ancestors(entity)
.find_map(|p| scene_instances.get(world, p).ok())
{
fake_entity::INSTANCE_ID.set(Some(*instance.deref()));
} else {
warn!("Can't find higher-hierarchy `SceneInstance` for entity '{name:?}'");
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);
@ -98,12 +138,23 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
entity_components.insert(target_entity, updated_components);
}
for (entity, name, extra, parent) in mesh_extras.iter(world) {
for (entity, name, extra) in mesh_extras.iter(world) {
let parent = hierarchy.get(entity).ok();
debug!(
"Gltf Mesh Extra: Name: {:?}, entity {:?}, parent: {:?}, mesh_extras {:?}",
name, entity, parent, extra
);
if let Some(instance) = hierarchy
.iter_ancestors(entity)
.find_map(|p| scene_instances.get(world, p).ok())
{
fake_entity::INSTANCE_ID.set(Some(*instance.deref()));
} else {
warn!("Can't find higher-hierarchy `SceneInstance` for entity '{name:?}'");
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);
@ -113,12 +164,23 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
entity_components.insert(target_entity, updated_components);
}
for (entity, name, extra, parent) in material_extras.iter(world) {
for (entity, name, extra) in material_extras.iter(world) {
let parent = hierarchy.get(entity).ok();
debug!(
"Name: {:?}, entity {:?}, parent: {:?}, material_extras {:?}",
name, entity, parent, extra
);
if let Some(instance) = hierarchy
.iter_ancestors(entity)
.find_map(|p| scene_instances.get(world, p).ok())
{
fake_entity::INSTANCE_ID.set(Some(*instance.deref()));
} else {
warn!("Can't find higher-hierarchy `SceneInstance` for entity '{name:?}'");
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);
@ -128,6 +190,9 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
entity_components.insert(target_entity, updated_components);
}
fake_entity::BAD_WORLD_ACCESS.set(None);
fake_entity::INSTANCE_ID.set(None);
for (entity, components) in entity_components {
let type_registry: &AppTypeRegistry = world.resource();
let type_registry = type_registry.clone();

View File

@ -6,4 +6,5 @@ license = "MIT OR Apache-2.0"
[dependencies]
bevy = { version = "0.14", features = ["dynamic_linking"] }
bevy-inspector-egui = "0.25.2"
blenvy = { path = "../../crates/blenvy" }

View File

@ -3609,6 +3609,30 @@
"type": "object",
"typeInfo": "Value"
},
"bevy_egui::EguiSettings": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "bevy_egui::EguiSettings",
"properties": {
"default_open_url_target": {
"type": {
"$ref": "#/$defs/core::option::Option<alloc::string::String>"
}
},
"scale_factor": {
"type": {
"$ref": "#/$defs/f32"
}
}
},
"required": [
"scale_factor"
],
"short_name": "EguiSettings",
"type": "object",
"typeInfo": "Struct"
},
"bevy_gizmos::aabb::AabbGizmoConfigGroup": {
"additionalProperties": false,
"isComponent": false,
@ -12776,6 +12800,14 @@
"type": "object",
"typeInfo": "Value"
},
"core::ops::Range<f64>": {
"isComponent": false,
"isResource": false,
"long_name": "core::ops::Range<f64>",
"short_name": "Range<f64>",
"type": "object",
"typeInfo": "Value"
},
"core::option::Option<(u8, u8)>": {
"isComponent": false,
"isResource": false,
@ -13490,6 +13522,295 @@
"type": "object",
"typeInfo": "Struct"
},
"glam::BVec2": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::BVec2",
"properties": {
"x": {
"type": {
"$ref": "#/$defs/bool"
}
},
"y": {
"type": {
"$ref": "#/$defs/bool"
}
}
},
"required": [
"x",
"y"
],
"short_name": "BVec2",
"type": "object",
"typeInfo": "Struct"
},
"glam::BVec3": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::BVec3",
"properties": {
"x": {
"type": {
"$ref": "#/$defs/bool"
}
},
"y": {
"type": {
"$ref": "#/$defs/bool"
}
},
"z": {
"type": {
"$ref": "#/$defs/bool"
}
}
},
"required": [
"x",
"y",
"z"
],
"short_name": "BVec3",
"type": "object",
"typeInfo": "Struct"
},
"glam::BVec3A": {
"isComponent": false,
"isResource": false,
"long_name": "glam::BVec3A",
"short_name": "BVec3A",
"type": "object",
"typeInfo": "Value"
},
"glam::BVec4": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::BVec4",
"properties": {
"w": {
"type": {
"$ref": "#/$defs/bool"
}
},
"x": {
"type": {
"$ref": "#/$defs/bool"
}
},
"y": {
"type": {
"$ref": "#/$defs/bool"
}
},
"z": {
"type": {
"$ref": "#/$defs/bool"
}
}
},
"required": [
"x",
"y",
"z",
"w"
],
"short_name": "BVec4",
"type": "object",
"typeInfo": "Struct"
},
"glam::BVec4A": {
"isComponent": false,
"isResource": false,
"long_name": "glam::BVec4A",
"short_name": "BVec4A",
"type": "object",
"typeInfo": "Value"
},
"glam::DAffine2": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::DAffine2",
"properties": {
"matrix2": {
"type": {
"$ref": "#/$defs/glam::DMat2"
}
},
"translation": {
"type": {
"$ref": "#/$defs/glam::DVec2"
}
}
},
"required": [
"matrix2",
"translation"
],
"short_name": "DAffine2",
"type": "object",
"typeInfo": "Struct"
},
"glam::DAffine3": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::DAffine3",
"properties": {
"matrix3": {
"type": {
"$ref": "#/$defs/glam::DMat3"
}
},
"translation": {
"type": {
"$ref": "#/$defs/glam::DVec3"
}
}
},
"required": [
"matrix3",
"translation"
],
"short_name": "DAffine3",
"type": "object",
"typeInfo": "Struct"
},
"glam::DMat2": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::DMat2",
"properties": {
"x_axis": {
"type": {
"$ref": "#/$defs/glam::DVec2"
}
},
"y_axis": {
"type": {
"$ref": "#/$defs/glam::DVec2"
}
}
},
"required": [
"x_axis",
"y_axis"
],
"short_name": "DMat2",
"type": "object",
"typeInfo": "Struct"
},
"glam::DMat3": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::DMat3",
"properties": {
"x_axis": {
"type": {
"$ref": "#/$defs/glam::DVec3"
}
},
"y_axis": {
"type": {
"$ref": "#/$defs/glam::DVec3"
}
},
"z_axis": {
"type": {
"$ref": "#/$defs/glam::DVec3"
}
}
},
"required": [
"x_axis",
"y_axis",
"z_axis"
],
"short_name": "DMat3",
"type": "object",
"typeInfo": "Struct"
},
"glam::DMat4": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::DMat4",
"properties": {
"w_axis": {
"type": {
"$ref": "#/$defs/glam::DVec4"
}
},
"x_axis": {
"type": {
"$ref": "#/$defs/glam::DVec4"
}
},
"y_axis": {
"type": {
"$ref": "#/$defs/glam::DVec4"
}
},
"z_axis": {
"type": {
"$ref": "#/$defs/glam::DVec4"
}
}
},
"required": [
"x_axis",
"y_axis",
"z_axis",
"w_axis"
],
"short_name": "DMat4",
"type": "object",
"typeInfo": "Struct"
},
"glam::DQuat": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::DQuat",
"properties": {
"w": {
"type": {
"$ref": "#/$defs/f64"
}
},
"x": {
"type": {
"$ref": "#/$defs/f64"
}
},
"y": {
"type": {
"$ref": "#/$defs/f64"
}
},
"z": {
"type": {
"$ref": "#/$defs/f64"
}
}
},
"required": [
"x",
"y",
"z",
"w"
],
"short_name": "DQuat",
"type": "object",
"typeInfo": "Struct"
},
"glam::DVec2": {
"additionalProperties": false,
"isComponent": false,
@ -13515,6 +13836,74 @@
"type": "object",
"typeInfo": "Struct"
},
"glam::DVec3": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::DVec3",
"properties": {
"x": {
"type": {
"$ref": "#/$defs/f64"
}
},
"y": {
"type": {
"$ref": "#/$defs/f64"
}
},
"z": {
"type": {
"$ref": "#/$defs/f64"
}
}
},
"required": [
"x",
"y",
"z"
],
"short_name": "DVec3",
"type": "object",
"typeInfo": "Struct"
},
"glam::DVec4": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::DVec4",
"properties": {
"w": {
"type": {
"$ref": "#/$defs/f64"
}
},
"x": {
"type": {
"$ref": "#/$defs/f64"
}
},
"y": {
"type": {
"$ref": "#/$defs/f64"
}
},
"z": {
"type": {
"$ref": "#/$defs/f64"
}
}
},
"required": [
"x",
"y",
"z",
"w"
],
"short_name": "DVec4",
"type": "object",
"typeInfo": "Struct"
},
"glam::IVec2": {
"additionalProperties": false,
"isComponent": false,
@ -13540,6 +13929,74 @@
"type": "object",
"typeInfo": "Struct"
},
"glam::IVec3": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::IVec3",
"properties": {
"x": {
"type": {
"$ref": "#/$defs/i32"
}
},
"y": {
"type": {
"$ref": "#/$defs/i32"
}
},
"z": {
"type": {
"$ref": "#/$defs/i32"
}
}
},
"required": [
"x",
"y",
"z"
],
"short_name": "IVec3",
"type": "object",
"typeInfo": "Struct"
},
"glam::IVec4": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::IVec4",
"properties": {
"w": {
"type": {
"$ref": "#/$defs/i32"
}
},
"x": {
"type": {
"$ref": "#/$defs/i32"
}
},
"y": {
"type": {
"$ref": "#/$defs/i32"
}
},
"z": {
"type": {
"$ref": "#/$defs/i32"
}
}
},
"required": [
"x",
"y",
"z",
"w"
],
"short_name": "IVec4",
"type": "object",
"typeInfo": "Struct"
},
"glam::Mat2": {
"additionalProperties": false,
"isComponent": false,
@ -13565,6 +14022,37 @@
"type": "object",
"typeInfo": "Struct"
},
"glam::Mat3": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::Mat3",
"properties": {
"x_axis": {
"type": {
"$ref": "#/$defs/glam::Vec3"
}
},
"y_axis": {
"type": {
"$ref": "#/$defs/glam::Vec3"
}
},
"z_axis": {
"type": {
"$ref": "#/$defs/glam::Vec3"
}
}
},
"required": [
"x_axis",
"y_axis",
"z_axis"
],
"short_name": "Mat3",
"type": "object",
"typeInfo": "Struct"
},
"glam::Mat3A": {
"additionalProperties": false,
"isComponent": false,
@ -13726,6 +14214,43 @@
"type": "object",
"typeInfo": "Struct"
},
"glam::UVec4": {
"additionalProperties": false,
"isComponent": false,
"isResource": false,
"long_name": "glam::UVec4",
"properties": {
"w": {
"type": {
"$ref": "#/$defs/u32"
}
},
"x": {
"type": {
"$ref": "#/$defs/u32"
}
},
"y": {
"type": {
"$ref": "#/$defs/u32"
}
},
"z": {
"type": {
"$ref": "#/$defs/u32"
}
}
},
"required": [
"x",
"y",
"z",
"w"
],
"short_name": "UVec4",
"type": "object",
"typeInfo": "Struct"
},
"glam::Vec2": {
"additionalProperties": false,
"isComponent": false,

View File

@ -1,4 +1,5 @@
use bevy::prelude::*;
use bevy_inspector_egui::quick::WorldInspectorPlugin;
use blenvy::{BlenvyPlugin, BlueprintInfo, GameWorldTag, HideUntilReady, SpawnBlueprint};
#[derive(Component, Reflect, Debug)]
@ -17,6 +18,7 @@ fn main() {
.add_plugins((
DefaultPlugins.set(AssetPlugin::default()),
BlenvyPlugin::default(),
WorldInspectorPlugin::new(),
))
.register_type::<TupleRelations>()
.register_type::<BigRelations>()

View File

@ -26,7 +26,7 @@ def property_group_from_infos(property_group_name, property_group_parameters):
return (property_group_pointer, property_group_class)
def is_entity_poll(self, object):
return bpy.context.scene in object.users_scene # TODO: only select `object.type`s that get converted to entities and maybe something against other collection(instances)?
return True # TODO: only select `object.type`s that get converted to entities and maybe something against other collection(instances)?
# this is where we store the information for all available components
class ComponentsRegistry(PropertyGroup):