feat(bevy_gltf_blueprints): improved error handling for clone_entity (#82)
* feat(bevy_gltf_blueprints): improved error handling for clone_entity * you will now get component name for components that have not been registered & thus cannot be cloned * added a small example (in examples/bevy_gltf_blueprints/basic), just press 'U' at runtime to try to spawn an entity with unregistered components * closes #81
This commit is contained in:
parent
6047959b3f
commit
20b34dde20
|
@ -779,7 +779,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_gltf_blueprints"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"bevy_gltf_components 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "bevy_gltf_blueprints"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
authors = ["Mark 'kaosat-dev' Moissette"]
|
||||
description = "Adds the ability to define Blueprints/Prefabs for [Bevy](https://bevyengine.org/) inside gltf files and spawn them in Bevy."
|
||||
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||
|
|
|
@ -18,29 +18,31 @@ impl CloneEntity {
|
|||
// - the source or destination entity do not exist
|
||||
fn clone_entity(self, world: &mut World) {
|
||||
let components = {
|
||||
let registry = world.get_resource::<AppTypeRegistry>().unwrap().read();
|
||||
let registry = world
|
||||
.get_resource::<AppTypeRegistry>()
|
||||
.expect("the world should have a type registry")
|
||||
.read();
|
||||
|
||||
world
|
||||
.get_entity(self.source)
|
||||
.unwrap()
|
||||
.expect("source entity should exist")
|
||||
.archetype()
|
||||
.components()
|
||||
.map(|component_id| {
|
||||
world
|
||||
let component_info = world
|
||||
.components()
|
||||
.get_info(component_id)
|
||||
.unwrap()
|
||||
.type_id()
|
||||
.unwrap()
|
||||
})
|
||||
.map(|type_id| {
|
||||
// println!("type_id {:?}", type_id);
|
||||
registry
|
||||
.get(type_id)
|
||||
.unwrap()
|
||||
.data::<ReflectComponent>()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.expect("component info should be available");
|
||||
|
||||
let type_id = component_info.type_id().unwrap();
|
||||
let type_id = registry.get(type_id).expect(
|
||||
format!(
|
||||
"cannot clone entity: component: {:?} is not registered",
|
||||
component_info.name()
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
return type_id.data::<ReflectComponent>().unwrap().clone();
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
@ -51,7 +53,9 @@ impl CloneEntity {
|
|||
.unwrap()
|
||||
.clone_value();
|
||||
|
||||
let mut destination = world.get_entity_mut(self.destination).unwrap();
|
||||
let mut destination = world
|
||||
.get_entity_mut(self.destination)
|
||||
.expect("destination entity should exist");
|
||||
|
||||
component.apply_or_insert(&mut destination, &*source);
|
||||
}
|
||||
|
|
|
@ -49,12 +49,10 @@ pub(crate) fn spawn_from_blueprints(
|
|||
assets_gltf: Res<Assets<Gltf>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
blueprints_config: Res<BluePrintsConfig>,
|
||||
|
||||
) {
|
||||
for (entity, name, blupeprint_name, transform, original_parent) in spawn_placeholders.iter() {
|
||||
debug!("need to spawn {:?}, id: {:?}", blupeprint_name.0, entity);
|
||||
|
||||
|
||||
let what = &blupeprint_name.0;
|
||||
let model_file_name = format!("{}.{}", &what, &blueprints_config.format);
|
||||
let model_path =
|
||||
|
@ -63,8 +61,6 @@ pub(crate) fn spawn_from_blueprints(
|
|||
debug!("attempting to spawn {:?}", model_path);
|
||||
let model_handle: Handle<Gltf> = asset_server.load(model_path);
|
||||
|
||||
|
||||
|
||||
let gltf = assets_gltf
|
||||
.get(&model_handle)
|
||||
.expect("this gltf should have been loaded");
|
||||
|
@ -97,12 +93,12 @@ pub(crate) fn spawn_from_blueprints(
|
|||
|
||||
let world = game_world.single_mut();
|
||||
let mut parent = world.1[0]; // FIXME: dangerous hack because our gltf data have a single child like this, but might not always be the case
|
||||
|
||||
|
||||
// ideally, insert the newly created entity as a child of the original parent, if any, the world otherwise
|
||||
if let Some(original_parent) = original_parent {
|
||||
parent = original_parent.get();
|
||||
}
|
||||
|
||||
commands.entity(parent).add_child(child_scene);
|
||||
|
||||
commands.entity(parent).add_child(child_scene);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,10 @@ pub fn setup_game(
|
|||
next_game_state.set(GameState::InGame)
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
struct UnregisteredComponent;
|
||||
|
||||
pub fn spawn_test(
|
||||
keycode: Res<Input<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
@ -83,3 +87,48 @@ pub fn spawn_test(
|
|||
commands.entity(world).add_child(new_entity);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_test_failing(
|
||||
keycode: Res<Input<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::U) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 0.8;
|
||||
let vel_x: f32 = rng.gen_range(-range..range);
|
||||
let vel_y: f32 = rng.gen_range(2.0..2.5);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("Health_Pickup".to_string()),
|
||||
transform: TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
..Default::default()
|
||||
},
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
// BlueprintName("Health_Pickup".to_string()),
|
||||
// SpawnHere,
|
||||
// TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
Velocity {
|
||||
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||
},
|
||||
UnregisteredComponent,
|
||||
))
|
||||
.id();
|
||||
commands.entity(world).add_child(new_entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ impl Plugin for GamePlugin {
|
|||
player_move_demo, //.run_if(in_state(AppState::Running)),
|
||||
// test_collision_events
|
||||
spawn_test,
|
||||
spawn_test_failing,
|
||||
)
|
||||
.run_if(in_state(GameState::InGame)),
|
||||
)
|
||||
|
|
|
@ -6,16 +6,23 @@ use bevy::prelude::*;
|
|||
|
||||
use super::CameraTrackingOffset;
|
||||
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
pub struct SSAOSettings;
|
||||
|
||||
pub fn camera_replace_proxies(
|
||||
mut commands: Commands,
|
||||
mut added_cameras: Query<(Entity, &mut Camera, Option<&BloomSettings>, Option<&SSAOSettings>), (Added<Camera>, With<CameraTrackingOffset>)>,
|
||||
mut added_cameras: Query<
|
||||
(
|
||||
Entity,
|
||||
&mut Camera,
|
||||
Option<&BloomSettings>,
|
||||
Option<&SSAOSettings>,
|
||||
),
|
||||
(Added<Camera>, With<CameraTrackingOffset>),
|
||||
>,
|
||||
|
||||
added_bloom_settings : Query<&BloomSettings, Added<BloomSettings>>,
|
||||
added_bloom_settings: Query<&BloomSettings, Added<BloomSettings>>,
|
||||
added_ssao_settings: Query<&SSAOSettings, Added<SSAOSettings>>, // Move to camera
|
||||
) {
|
||||
for (entity, mut camera, bloom_settings, ssao_setting) in added_cameras.iter_mut() {
|
||||
|
@ -24,27 +31,25 @@ pub fn camera_replace_proxies(
|
|||
commands
|
||||
.entity(entity)
|
||||
.insert(DebandDither::Enabled)
|
||||
.insert(Tonemapping::BlenderFilmic)
|
||||
;
|
||||
.insert(Tonemapping::BlenderFilmic);
|
||||
|
||||
// we only inject the scene_level bloom settings if there are no settings already on the Camera
|
||||
if bloom_settings.is_none() {
|
||||
for bloom_settings in added_bloom_settings.iter(){
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BloomSettings {
|
||||
intensity: bloom_settings.intensity,
|
||||
composite_mode: BloomCompositeMode::Additive,
|
||||
..default()
|
||||
});
|
||||
for bloom_settings in added_bloom_settings.iter() {
|
||||
commands.entity(entity).insert(BloomSettings {
|
||||
intensity: bloom_settings.intensity,
|
||||
composite_mode: BloomCompositeMode::Additive,
|
||||
..default()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ssao_setting.is_none() {
|
||||
for _ in added_ssao_settings.iter(){
|
||||
for _ in added_ssao_settings.iter() {
|
||||
commands.insert_resource(Msaa::Off); // when using SSAO, you cannot use Msaa
|
||||
|
||||
commands.entity(entity)
|
||||
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(ScreenSpaceAmbientOcclusionBundle::default())
|
||||
.insert(TemporalAntiAliasBundle::default());
|
||||
}
|
||||
|
|
|
@ -2,23 +2,26 @@ use bevy::prelude::*;
|
|||
|
||||
use bevy::pbr::{CascadeShadowConfig, CascadeShadowConfigBuilder, DirectionalLightShadowMap};
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
pub struct AmbientLightSettings {
|
||||
pub color: Color,
|
||||
pub brightness: f32,
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
pub struct AmbientLightSettings {pub color: Color, pub brightness: f32}
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
pub struct ShadowmapSettings {pub size: usize}
|
||||
|
||||
pub struct ShadowmapSettings {
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
pub fn lighting_replace_proxies(
|
||||
mut added_dirights: Query<(Entity, &mut DirectionalLight), Added<DirectionalLight>>,
|
||||
mut added_spotlights: Query<&mut SpotLight, Added<SpotLight>>,
|
||||
mut added_pointlights: Query<&mut PointLight, Added<PointLight>>,
|
||||
|
||||
added_ambient_proxies : Query<&AmbientLightSettings, Added<AmbientLightSettings>>,
|
||||
added_shadowmap_settings : Query<&ShadowmapSettings, Added<ShadowmapSettings>>,
|
||||
added_ambient_proxies: Query<&AmbientLightSettings, Added<AmbientLightSettings>>,
|
||||
added_shadowmap_settings: Query<&ShadowmapSettings, Added<ShadowmapSettings>>,
|
||||
|
||||
mut commands: Commands,
|
||||
) {
|
||||
|
@ -42,12 +45,11 @@ pub fn lighting_replace_proxies(
|
|||
light.shadows_enabled = true;
|
||||
}
|
||||
|
||||
|
||||
for setting in added_shadowmap_settings.iter() {
|
||||
commands.insert_resource(DirectionalLightShadowMap { size: setting.size });
|
||||
}
|
||||
|
||||
for ambient in added_ambient_proxies.iter(){
|
||||
for ambient in added_ambient_proxies.iter() {
|
||||
commands.insert_resource(AmbientLight {
|
||||
color: ambient.color,
|
||||
brightness: ambient.brightness,
|
||||
|
@ -55,5 +57,4 @@ pub fn lighting_replace_proxies(
|
|||
// FIXME: does this belong here ?
|
||||
commands.insert_resource(ClearColor(ambient.color * ambient.brightness));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,13 +7,10 @@ use bevy::prelude::*;
|
|||
pub struct LightingPlugin;
|
||||
impl Plugin for LightingPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app
|
||||
.register_type::<AmbientLightSettings>()
|
||||
.register_type::<ShadowmapSettings>()
|
||||
// FIXME: adding these since they are missing
|
||||
.register_type::<NotShadowCaster>()
|
||||
|
||||
.add_systems(PreUpdate, lighting_replace_proxies)
|
||||
;
|
||||
app.register_type::<AmbientLightSettings>()
|
||||
.register_type::<ShadowmapSettings>()
|
||||
// FIXME: adding these since they are missing
|
||||
.register_type::<NotShadowCaster>()
|
||||
.add_systems(PreUpdate, lighting_replace_proxies);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ use bevy::prelude::*;
|
|||
#[reflect(Component)]
|
||||
struct Marker;
|
||||
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
struct Enemy;
|
||||
|
@ -13,7 +12,6 @@ struct Enemy;
|
|||
#[reflect(Component)]
|
||||
struct NestingTest;
|
||||
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug, Deref, DerefMut)]
|
||||
#[reflect(Component)]
|
||||
struct TuppleTestF32(f32);
|
||||
|
@ -77,7 +75,6 @@ impl Plugin for ComponentsTestPlugin {
|
|||
.register_type::<Marker>()
|
||||
.register_type::<Enemy>()
|
||||
.register_type::<NestingTest>()
|
||||
|
||||
.register_type::<TuppleTestF32>()
|
||||
.register_type::<TuppleTestU64>()
|
||||
.register_type::<TuppleTestStr>()
|
||||
|
|
Loading…
Reference in New Issue