feat(bevy_registry_export): added boilerplate to make registry path relative to assets folder

* for bevy_gltf_components: registered GltfProcessed component (supresses a few warnings etc)
 * for the rest: cargo fmt
This commit is contained in:
kaosat.dev 2024-02-29 23:38:55 +01:00
parent a705a238fd
commit 7f824c47fe
6 changed files with 71 additions and 38 deletions

View File

@ -30,11 +30,14 @@ pub struct MaterialInfo {
pub(crate) fn materials_inject(
mut blueprints_config: ResMut<BluePrintsConfig>,
material_infos: Query<(&MaterialInfo, &Children), Added<MaterialInfo>>,
with_materials_and_meshes: Query<(), (
With<Parent>,
With<Handle<StandardMaterial>>,
With<Handle<Mesh>>,
)>,
with_materials_and_meshes: Query<
(),
(
With<Parent>,
With<Handle<StandardMaterial>>,
With<Handle<Mesh>>,
),
>,
models: Res<Assets<bevy::gltf::Gltf>>,
asset_server: Res<AssetServer>,

View File

@ -8,8 +8,9 @@ pub mod process_gltfs;
pub use process_gltfs::*;
use bevy::{
ecs::system::Resource,
ecs::{component::Component, reflect::ReflectComponent, system::Resource},
prelude::{App, IntoSystemConfigs, Plugin, SystemSet, Update},
reflect::Reflect,
};
/// A Bevy plugin for extracting components from gltf files and automatically adding them to the relevant entities
@ -45,6 +46,11 @@ use bevy::{
///}
/// ```
/// this is a flag component to tag a processed gltf, to avoid processing things multiple times
#[derive(Component, Reflect, Default, Debug)]
#[reflect(Component)]
pub struct GltfProcessed;
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
/// systemset to order your systems after the component injection when needed
pub enum GltfComponentsSet {
@ -68,12 +74,13 @@ impl Default for ComponentsFromGltfPlugin {
impl Plugin for ComponentsFromGltfPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(GltfComponentsConfig {
legacy_mode: self.legacy_mode,
})
.add_systems(
Update,
(add_components_from_gltf_extras).in_set(GltfComponentsSet::Injection),
);
app.register_type::<GltfProcessed>()
.insert_resource(GltfComponentsConfig {
legacy_mode: self.legacy_mode,
})
.add_systems(
Update,
(add_components_from_gltf_extras).in_set(GltfComponentsSet::Injection),
);
}
}

View File

@ -5,7 +5,6 @@ use bevy::{
query::{Added, Without},
reflect::{AppTypeRegistry, ReflectComponent},
world::World,
component::Component
},
gltf::GltfExtras,
hierarchy::Parent,
@ -14,11 +13,7 @@ use bevy::{
utils::HashMap,
};
use crate::{ronstring_to_reflect_component, GltfComponentsConfig};
/// this is a flag component to tag a processed gltf, to avoid processing things multiple times
#[derive(Component)]
pub struct GltfProcessed;
use crate::{ronstring_to_reflect_component, GltfComponentsConfig, GltfProcessed};
/// 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) {
@ -37,7 +32,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
let type_registry: &AppTypeRegistry = world.resource();
let type_registry = type_registry.read();
let reflect_components = ronstring_to_reflect_component(
&extra.value,
&type_registry,
@ -81,7 +76,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
if !components.is_empty() {
debug!("--entity {:?}, components {}", entity, components.len());
}
for (component, type_registration) in components {
for (component, type_registration) in components {
debug!(
"------adding {} {:?}",
component.get_represented_type_info().unwrap().type_path(),
@ -91,13 +86,12 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
{
let mut entity_mut = world.entity_mut(entity);
type_registration
.data::<ReflectComponent>()
.expect("Unable to reflect component")
.insert(&mut entity_mut, &*component, &type_registry);
.data::<ReflectComponent>()
.expect("Unable to reflect component")
.insert(&mut entity_mut, &*component, &type_registry);
entity_mut.insert(GltfProcessed); // this is how can we insert any additional components
}
}
}
}

View File

@ -113,7 +113,8 @@ pub fn ronstring_to_reflect_component(
println!("serialized Component {}", serialized);*/
debug!("component data ron string {}", ron_string);
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str()).expect("deserialzer should have been generated from string");
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str())
.expect("deserialzer should have been generated from string");
let reflect_deserializer = UntypedReflectDeserializer::new(type_registry);
let component = reflect_deserializer
.deserialize(&mut deserializer)

View File

@ -1,4 +1,4 @@
use std::fs::File;
use std::{fs::File, path::Path};
use bevy::log::info;
use bevy_ecs::{
@ -8,14 +8,17 @@ use bevy_ecs::{
use bevy_reflect::{TypeInfo, TypeRegistration, VariantInfo}; // TypePath // DynamicTypePath
use serde_json::{json, Map, Value};
use crate::ExportComponentsConfig;
use crate::{AssetRoot, ExportComponentsConfig};
pub fn export_types(world: &mut World) {
let config = world
.get_resource::<ExportComponentsConfig>()
.expect("ExportComponentsConfig should exist at this stage");
let writer = File::create(&config.save_path).expect("should have created schema file");
let asset_root = world.resource::<AssetRoot>();
let registry_save_path = Path::join(&asset_root.0, &config.save_path);
println!("registry_save_path {:?}", registry_save_path);
let writer = File::create(registry_save_path).expect("should have created schema file");
let types = world.resource_mut::<AppTypeRegistry>();
let types = types.read();

View File

@ -6,6 +6,7 @@ use bevy_ecs::system::Resource;
pub use export_types::*;
use bevy::{
asset::AssetPlugin,
prelude::{App, Plugin},
scene::SceneFilter,
};
@ -29,20 +30,44 @@ pub struct ExportRegistryPlugin {
impl Default for ExportRegistryPlugin {
fn default() -> Self {
Self {
component_filter: SceneFilter::default(), // unused for now
resource_filter: SceneFilter::default(), // unused for now
save_path: PathBuf::from("assets/registry.json"),
component_filter: SceneFilter::default(), // unused for now
resource_filter: SceneFilter::default(), // unused for now
save_path: PathBuf::from("registry.json"), // relative to assets folder
}
}
}
impl Plugin for ExportRegistryPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(ExportComponentsConfig {
save_path: self.save_path.clone(),
component_filter: self.component_filter.clone(),
resource_filter: self.resource_filter.clone(),
})
.add_systems(Startup, export_types);
app.register_asset_root()
.insert_resource(ExportComponentsConfig {
save_path: self.save_path.clone(),
component_filter: self.component_filter.clone(),
resource_filter: self.resource_filter.clone(),
})
.add_systems(Startup, export_types);
}
}
trait RegistryExportApp {
fn register_asset_root(&mut self) -> &mut Self;
}
impl RegistryExportApp for App {
fn register_asset_root(&mut self) -> &mut Self {
let asset_plugin = get_asset_plugin(self);
let path_str = asset_plugin.file_path.clone();
let path = PathBuf::from(path_str);
self.insert_resource(AssetRoot(path))
}
}
fn get_asset_plugin(app: &App) -> &AssetPlugin {
let asset_plugins: Vec<&AssetPlugin> = app.get_added_plugins();
asset_plugins.into_iter().next().expect(ASSET_ERROR)
}
const ASSET_ERROR: &str = "Bevy_registry_export requires access to the Bevy asset plugin. \
Please add `ExportRegistryPlugin` after `AssetPlugin`, which is commonly added as part of the `DefaultPlugins`";
#[derive(Debug, Clone, PartialEq, Eq, Hash, Resource)]
pub(crate) struct AssetRoot(pub(crate) PathBuf);