mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-24 04:40:53 +00:00
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
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -779,7 +779,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_gltf_blueprints"
|
name = "bevy_gltf_blueprints"
|
||||||
version = "0.5.0"
|
version = "0.5.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy_gltf_components 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bevy_gltf_components 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_gltf_blueprints"
|
name = "bevy_gltf_blueprints"
|
||||||
version = "0.5.0"
|
version = "0.5.1"
|
||||||
authors = ["Mark 'kaosat-dev' Moissette"]
|
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."
|
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"
|
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
|
@ -18,29 +18,31 @@ impl CloneEntity {
|
|||||||
// - the source or destination entity do not exist
|
// - the source or destination entity do not exist
|
||||||
fn clone_entity(self, world: &mut World) {
|
fn clone_entity(self, world: &mut World) {
|
||||||
let components = {
|
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
|
world
|
||||||
.get_entity(self.source)
|
.get_entity(self.source)
|
||||||
.unwrap()
|
.expect("source entity should exist")
|
||||||
.archetype()
|
.archetype()
|
||||||
.components()
|
.components()
|
||||||
.map(|component_id| {
|
.map(|component_id| {
|
||||||
world
|
let component_info = world
|
||||||
.components()
|
.components()
|
||||||
.get_info(component_id)
|
.get_info(component_id)
|
||||||
.unwrap()
|
.expect("component info should be available");
|
||||||
.type_id()
|
|
||||||
.unwrap()
|
let type_id = component_info.type_id().unwrap();
|
||||||
})
|
let type_id = registry.get(type_id).expect(
|
||||||
.map(|type_id| {
|
format!(
|
||||||
// println!("type_id {:?}", type_id);
|
"cannot clone entity: component: {:?} is not registered",
|
||||||
registry
|
component_info.name()
|
||||||
.get(type_id)
|
)
|
||||||
.unwrap()
|
.as_str(),
|
||||||
.data::<ReflectComponent>()
|
);
|
||||||
.unwrap()
|
return type_id.data::<ReflectComponent>().unwrap().clone();
|
||||||
.clone()
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
@ -51,7 +53,9 @@ impl CloneEntity {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.clone_value();
|
.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);
|
component.apply_or_insert(&mut destination, &*source);
|
||||||
}
|
}
|
||||||
|
@ -49,12 +49,10 @@ pub(crate) fn spawn_from_blueprints(
|
|||||||
assets_gltf: Res<Assets<Gltf>>,
|
assets_gltf: Res<Assets<Gltf>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
blueprints_config: Res<BluePrintsConfig>,
|
blueprints_config: Res<BluePrintsConfig>,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
for (entity, name, blupeprint_name, transform, original_parent) in spawn_placeholders.iter() {
|
for (entity, name, blupeprint_name, transform, original_parent) in spawn_placeholders.iter() {
|
||||||
debug!("need to spawn {:?}, id: {:?}", blupeprint_name.0, entity);
|
debug!("need to spawn {:?}, id: {:?}", blupeprint_name.0, entity);
|
||||||
|
|
||||||
|
|
||||||
let what = &blupeprint_name.0;
|
let what = &blupeprint_name.0;
|
||||||
let model_file_name = format!("{}.{}", &what, &blueprints_config.format);
|
let model_file_name = format!("{}.{}", &what, &blueprints_config.format);
|
||||||
let model_path =
|
let model_path =
|
||||||
@ -63,8 +61,6 @@ pub(crate) fn spawn_from_blueprints(
|
|||||||
debug!("attempting to spawn {:?}", model_path);
|
debug!("attempting to spawn {:?}", model_path);
|
||||||
let model_handle: Handle<Gltf> = asset_server.load(model_path);
|
let model_handle: Handle<Gltf> = asset_server.load(model_path);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let gltf = assets_gltf
|
let gltf = assets_gltf
|
||||||
.get(&model_handle)
|
.get(&model_handle)
|
||||||
.expect("this gltf should have been loaded");
|
.expect("this gltf should have been loaded");
|
||||||
@ -97,12 +93,12 @@ pub(crate) fn spawn_from_blueprints(
|
|||||||
|
|
||||||
let world = game_world.single_mut();
|
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
|
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
|
// 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 {
|
if let Some(original_parent) = original_parent {
|
||||||
parent = original_parent.get();
|
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)
|
next_game_state.set(GameState::InGame)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
struct UnregisteredComponent;
|
||||||
|
|
||||||
pub fn spawn_test(
|
pub fn spawn_test(
|
||||||
keycode: Res<Input<KeyCode>>,
|
keycode: Res<Input<KeyCode>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
@ -83,3 +87,48 @@ pub fn spawn_test(
|
|||||||
commands.entity(world).add_child(new_entity);
|
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)),
|
player_move_demo, //.run_if(in_state(AppState::Running)),
|
||||||
// test_collision_events
|
// test_collision_events
|
||||||
spawn_test,
|
spawn_test,
|
||||||
|
spawn_test_failing,
|
||||||
)
|
)
|
||||||
.run_if(in_state(GameState::InGame)),
|
.run_if(in_state(GameState::InGame)),
|
||||||
)
|
)
|
||||||
|
@ -6,16 +6,23 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
use super::CameraTrackingOffset;
|
use super::CameraTrackingOffset;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct SSAOSettings;
|
pub struct SSAOSettings;
|
||||||
|
|
||||||
pub fn camera_replace_proxies(
|
pub fn camera_replace_proxies(
|
||||||
mut commands: Commands,
|
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
|
added_ssao_settings: Query<&SSAOSettings, Added<SSAOSettings>>, // Move to camera
|
||||||
) {
|
) {
|
||||||
for (entity, mut camera, bloom_settings, ssao_setting) in added_cameras.iter_mut() {
|
for (entity, mut camera, bloom_settings, ssao_setting) in added_cameras.iter_mut() {
|
||||||
@ -24,27 +31,25 @@ pub fn camera_replace_proxies(
|
|||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(DebandDither::Enabled)
|
.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
|
// we only inject the scene_level bloom settings if there are no settings already on the Camera
|
||||||
if bloom_settings.is_none() {
|
if bloom_settings.is_none() {
|
||||||
for bloom_settings in added_bloom_settings.iter(){
|
for bloom_settings in added_bloom_settings.iter() {
|
||||||
commands
|
commands.entity(entity).insert(BloomSettings {
|
||||||
.entity(entity)
|
intensity: bloom_settings.intensity,
|
||||||
.insert(BloomSettings {
|
composite_mode: BloomCompositeMode::Additive,
|
||||||
intensity: bloom_settings.intensity,
|
..default()
|
||||||
composite_mode: BloomCompositeMode::Additive,
|
});
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ssao_setting.is_none() {
|
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.insert_resource(Msaa::Off); // when using SSAO, you cannot use Msaa
|
||||||
|
|
||||||
commands.entity(entity)
|
commands
|
||||||
|
.entity(entity)
|
||||||
.insert(ScreenSpaceAmbientOcclusionBundle::default())
|
.insert(ScreenSpaceAmbientOcclusionBundle::default())
|
||||||
.insert(TemporalAntiAliasBundle::default());
|
.insert(TemporalAntiAliasBundle::default());
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,26 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
use bevy::pbr::{CascadeShadowConfig, CascadeShadowConfigBuilder, DirectionalLightShadowMap};
|
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)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct AmbientLightSettings {pub color: Color, pub brightness: f32}
|
pub struct ShadowmapSettings {
|
||||||
|
pub size: usize,
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
}
|
||||||
#[reflect(Component)]
|
|
||||||
pub struct ShadowmapSettings {pub size: usize}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn lighting_replace_proxies(
|
pub fn lighting_replace_proxies(
|
||||||
mut added_dirights: Query<(Entity, &mut DirectionalLight), Added<DirectionalLight>>,
|
mut added_dirights: Query<(Entity, &mut DirectionalLight), Added<DirectionalLight>>,
|
||||||
mut added_spotlights: Query<&mut SpotLight, Added<SpotLight>>,
|
mut added_spotlights: Query<&mut SpotLight, Added<SpotLight>>,
|
||||||
mut added_pointlights: Query<&mut PointLight, Added<PointLight>>,
|
mut added_pointlights: Query<&mut PointLight, Added<PointLight>>,
|
||||||
|
|
||||||
added_ambient_proxies : Query<&AmbientLightSettings, Added<AmbientLightSettings>>,
|
added_ambient_proxies: Query<&AmbientLightSettings, Added<AmbientLightSettings>>,
|
||||||
added_shadowmap_settings : Query<&ShadowmapSettings, Added<ShadowmapSettings>>,
|
added_shadowmap_settings: Query<&ShadowmapSettings, Added<ShadowmapSettings>>,
|
||||||
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
@ -42,12 +45,11 @@ pub fn lighting_replace_proxies(
|
|||||||
light.shadows_enabled = true;
|
light.shadows_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for setting in added_shadowmap_settings.iter() {
|
for setting in added_shadowmap_settings.iter() {
|
||||||
commands.insert_resource(DirectionalLightShadowMap { size: setting.size });
|
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 {
|
commands.insert_resource(AmbientLight {
|
||||||
color: ambient.color,
|
color: ambient.color,
|
||||||
brightness: ambient.brightness,
|
brightness: ambient.brightness,
|
||||||
@ -55,5 +57,4 @@ pub fn lighting_replace_proxies(
|
|||||||
// FIXME: does this belong here ?
|
// FIXME: does this belong here ?
|
||||||
commands.insert_resource(ClearColor(ambient.color * ambient.brightness));
|
commands.insert_resource(ClearColor(ambient.color * ambient.brightness));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,10 @@ use bevy::prelude::*;
|
|||||||
pub struct LightingPlugin;
|
pub struct LightingPlugin;
|
||||||
impl Plugin for LightingPlugin {
|
impl Plugin for LightingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<AmbientLightSettings>()
|
||||||
.register_type::<AmbientLightSettings>()
|
.register_type::<ShadowmapSettings>()
|
||||||
.register_type::<ShadowmapSettings>()
|
// FIXME: adding these since they are missing
|
||||||
// FIXME: adding these since they are missing
|
.register_type::<NotShadowCaster>()
|
||||||
.register_type::<NotShadowCaster>()
|
.add_systems(PreUpdate, lighting_replace_proxies);
|
||||||
|
|
||||||
.add_systems(PreUpdate, lighting_replace_proxies)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ use bevy::prelude::*;
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct Marker;
|
struct Marker;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct Enemy;
|
struct Enemy;
|
||||||
@ -13,7 +12,6 @@ struct Enemy;
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct NestingTest;
|
struct NestingTest;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, Deref, DerefMut)]
|
#[derive(Component, Reflect, Default, Debug, Deref, DerefMut)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleTestF32(f32);
|
struct TuppleTestF32(f32);
|
||||||
@ -77,7 +75,6 @@ impl Plugin for ComponentsTestPlugin {
|
|||||||
.register_type::<Marker>()
|
.register_type::<Marker>()
|
||||||
.register_type::<Enemy>()
|
.register_type::<Enemy>()
|
||||||
.register_type::<NestingTest>()
|
.register_type::<NestingTest>()
|
||||||
|
|
||||||
.register_type::<TuppleTestF32>()
|
.register_type::<TuppleTestF32>()
|
||||||
.register_type::<TuppleTestU64>()
|
.register_type::<TuppleTestU64>()
|
||||||
.register_type::<TuppleTestStr>()
|
.register_type::<TuppleTestStr>()
|
||||||
|
Loading…
Reference in New Issue
Block a user