mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-22 20:00:53 +00:00
Compare commits
5 Commits
bef709a0ed
...
2b8c239fe8
Author | SHA1 | Date | |
---|---|---|---|
|
2b8c239fe8 | ||
|
70931ee163 | ||
|
459bb868e0 | ||
|
c326a11243 | ||
|
3099f98532 |
@ -73,7 +73,7 @@ pub struct AnimationMarkerReached {
|
|||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
/// triggers events when a given animation marker is reached for INSTANCE animations
|
/// triggers events when a given animation marker is reached for INSTANCE animations
|
||||||
pub fn trigger_instance_animation_markers_events(
|
pub fn trigger_instance_animation_markers_events(
|
||||||
animation_infos: Query<(
|
animation_infos: Query<(
|
||||||
@ -218,4 +218,4 @@ pub fn trigger_blueprint_animation_markers_events(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -7,25 +7,23 @@ use crate::{BluePrintsConfig, BlueprintAnimations};
|
|||||||
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct MyAsset{
|
pub struct BlueprintAsset {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub path: String
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct LocalAssets(pub Vec<MyAsset>);
|
pub struct LocalAssets(pub Vec<BlueprintAsset>);
|
||||||
|
|
||||||
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintAssets(pub Vec<MyAsset>);
|
pub struct BlueprintAssets(pub Vec<BlueprintAsset>);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
///
|
///
|
||||||
/// flag component, usually added when a blueprint is loaded
|
/// flag component, usually added when a blueprint is loaded
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub(crate) struct BlueprintAssetsLoaded;
|
pub(crate) struct BlueprintAssetsLoaded;
|
||||||
@ -44,7 +42,6 @@ pub(crate) struct AssetLoadTracker {
|
|||||||
pub handle: Handle<LoadedUntypedAsset>,
|
pub handle: Handle<LoadedUntypedAsset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// helper component, for tracking loaded assets
|
/// helper component, for tracking loaded assets
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub(crate) struct AssetsToLoad {
|
pub(crate) struct AssetsToLoad {
|
||||||
|
@ -90,7 +90,7 @@ impl Default for BlueprintsPlugin {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
aabbs: false,
|
aabbs: false,
|
||||||
material_library: false
|
material_library: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,8 +119,8 @@ impl Plugin for BlueprintsPlugin {
|
|||||||
.register_type::<HashMap<u32, Vec<String>>>()
|
.register_type::<HashMap<u32, Vec<String>>>()
|
||||||
.register_type::<HashMap<String, HashMap<u32, Vec<String>>>>()
|
.register_type::<HashMap<String, HashMap<u32, Vec<String>>>>()
|
||||||
.add_event::<AnimationMarkerReached>()
|
.add_event::<AnimationMarkerReached>()
|
||||||
.register_type::<MyAsset>()
|
.register_type::<BlueprintAsset>()
|
||||||
.register_type::<Vec<MyAsset>>()
|
.register_type::<Vec<BlueprintAsset>>()
|
||||||
.register_type::<Vec<String>>()
|
.register_type::<Vec<String>>()
|
||||||
.register_type::<LocalAssets>()
|
.register_type::<LocalAssets>()
|
||||||
.register_type::<BlueprintAssets>()
|
.register_type::<BlueprintAssets>()
|
||||||
|
@ -41,8 +41,6 @@ pub(crate) fn materials_inject(
|
|||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
||||||
for (entity, material_info) in material_infos.iter() {
|
for (entity, material_info) in material_infos.iter() {
|
||||||
println!("Entity with material info {:?} {:?}", entity, material_info);
|
println!("Entity with material info {:?} {:?}", entity, material_info);
|
||||||
let material_full_path = format!("{}#{}", material_info.path, material_info.name);
|
let material_full_path = format!("{}#{}", material_info.path, material_info.name);
|
||||||
@ -59,9 +57,9 @@ pub(crate) fn materials_inject(
|
|||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(BlueprintMaterialAssetsLoaded);
|
.insert(BlueprintMaterialAssetsLoaded);
|
||||||
} else {
|
} else {
|
||||||
let material_file_handle = asset_server.load_untyped(&material_info.path.clone()); // : Handle<Gltf>
|
let material_file_handle = asset_server.load_untyped(&material_info.path.clone()); // : Handle<Gltf>
|
||||||
let material_file_id = material_file_handle.id();
|
let material_file_id = material_file_handle.id();
|
||||||
|
|
||||||
let asset_infos: Vec<AssetLoadTracker> = vec![AssetLoadTracker {
|
let asset_infos: Vec<AssetLoadTracker> = vec![AssetLoadTracker {
|
||||||
name: material_info.name.clone(),
|
name: material_info.name.clone(),
|
||||||
id: material_file_id,
|
id: material_file_id,
|
||||||
@ -77,7 +75,6 @@ pub(crate) fn materials_inject(
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.insert(BlueprintMaterialAssetsNotLoaded);
|
.insert(BlueprintMaterialAssetsNotLoaded);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,7 +157,10 @@ pub(crate) fn materials_inject2(
|
|||||||
let mat_gltf = assets_gltf
|
let mat_gltf = assets_gltf
|
||||||
.get(model_handle.id())
|
.get(model_handle.id())
|
||||||
.expect("material should have been preloaded");
|
.expect("material should have been preloaded");
|
||||||
if mat_gltf.named_materials.contains_key(&material_info.name as &str) {
|
if mat_gltf
|
||||||
|
.named_materials
|
||||||
|
.contains_key(&material_info.name as &str)
|
||||||
|
{
|
||||||
let material = mat_gltf
|
let material = mat_gltf
|
||||||
.named_materials
|
.named_materials
|
||||||
.get(&material_info.name as &str)
|
.get(&material_info.name as &str)
|
||||||
|
@ -2,7 +2,10 @@ use std::path::{Path, PathBuf};
|
|||||||
|
|
||||||
use bevy::{gltf::Gltf, prelude::*, utils::hashbrown::HashMap};
|
use bevy::{gltf::Gltf, prelude::*, utils::hashbrown::HashMap};
|
||||||
|
|
||||||
use crate::{BlueprintAssets, AssetsToLoad, AssetLoadTracker, BluePrintsConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
use crate::{
|
||||||
|
AssetLoadTracker, AssetsToLoad, BluePrintsConfig, BlueprintAnimations, BlueprintAssets,
|
||||||
|
BlueprintAssetsLoaded, BlueprintAssetsNotLoaded,
|
||||||
|
};
|
||||||
|
|
||||||
/// this is a flag component for our levels/game world
|
/// this is a flag component for our levels/game world
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
@ -27,9 +30,8 @@ pub struct SpawnHere;
|
|||||||
/// flag component for dynamically spawned scenes
|
/// flag component for dynamically spawned scenes
|
||||||
pub struct Spawned;
|
pub struct Spawned;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
/// flag component added when a Blueprint instance ist Ready : ie :
|
/// flag component added when a Blueprint instance ist Ready : ie :
|
||||||
/// - its assets have loaded
|
/// - its assets have loaded
|
||||||
/// - it has finished spawning
|
/// - it has finished spawning
|
||||||
pub struct BlueprintInstanceReady;
|
pub struct BlueprintInstanceReady;
|
||||||
@ -58,15 +60,11 @@ pub struct AddToGameWorld;
|
|||||||
/// helper component, just to transfer child data
|
/// helper component, just to transfer child data
|
||||||
pub(crate) struct OriginalChildren(pub Vec<Entity>);
|
pub(crate) struct OriginalChildren(pub Vec<Entity>);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn test_thingy(
|
pub(crate) fn test_thingy(
|
||||||
spawn_placeholders: Query<
|
spawn_placeholders: Query<
|
||||||
(
|
(Entity, &BlueprintPath),
|
||||||
Entity,
|
(Added<BlueprintPath>, Without<Spawned>, Without<SpawnHere>),
|
||||||
&BlueprintPath,
|
>,
|
||||||
),
|
|
||||||
(Added<BlueprintPath>, Without<Spawned>, Without<SpawnHere>)>,
|
|
||||||
|
|
||||||
// before 0.14 we have to use a seperate query, after migrating we can query at the root level
|
// before 0.14 we have to use a seperate query, after migrating we can query at the root level
|
||||||
entities_with_assets: Query<
|
entities_with_assets: Query<
|
||||||
@ -81,17 +79,12 @@ pub(crate) fn test_thingy(
|
|||||||
(Added<BlueprintAssets>), // Added<BlueprintAssets>
|
(Added<BlueprintAssets>), // Added<BlueprintAssets>
|
||||||
>,
|
>,
|
||||||
|
|
||||||
|
bla_bla: Query<
|
||||||
bla_bla : Query<
|
(Entity, &BlueprintName, &BlueprintPath, Option<&Parent>),
|
||||||
(Entity,
|
(Added<BlueprintPath>),
|
||||||
&BlueprintName,
|
|
||||||
&BlueprintPath,
|
|
||||||
Option<&Parent>,),(Added<BlueprintPath>)
|
|
||||||
>,
|
>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
for (entity, blueprint_path) in spawn_placeholders.iter() {
|
for (entity, blueprint_path) in spawn_placeholders.iter() {
|
||||||
//println!("added blueprint_path {:?}", blueprint_path);
|
//println!("added blueprint_path {:?}", blueprint_path);
|
||||||
@ -105,7 +98,10 @@ asset_server: Res<AssetServer>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (entity, blueprint_name, blueprint_path, parent) in bla_bla.iter() {
|
for (entity, blueprint_name, blueprint_path, parent) in bla_bla.iter() {
|
||||||
println!("added blueprint to spawn {:?} {:?}", blueprint_name, blueprint_path);
|
println!(
|
||||||
|
"added blueprint to spawn {:?} {:?}",
|
||||||
|
blueprint_name, blueprint_path
|
||||||
|
);
|
||||||
let untyped_handle = asset_server.load_untyped(&blueprint_path.0);
|
let untyped_handle = asset_server.load_untyped(&blueprint_path.0);
|
||||||
let asset_id = untyped_handle.id();
|
let asset_id = untyped_handle.id();
|
||||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
@ -135,7 +131,7 @@ asset_server: Res<AssetServer>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (child_entity, child_entity_name, all_assets) in entities_with_assets.iter(){
|
for (child_entity, child_entity_name, all_assets) in entities_with_assets.iter() {
|
||||||
println!("added assets {:?} to {:?}", all_assets, child_entity_name);
|
println!("added assets {:?} to {:?}", all_assets, child_entity_name);
|
||||||
if all_assets.is_some() {
|
if all_assets.is_some() {
|
||||||
let mut asset_infos: Vec<AssetLoadTracker> = vec![];
|
let mut asset_infos: Vec<AssetLoadTracker> = vec![];
|
||||||
@ -184,21 +180,23 @@ pub(crate) fn check_for_loaded2(
|
|||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
for (entity,entity_name, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
for (entity, entity_name, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||||
let mut all_loaded = true;
|
let mut all_loaded = true;
|
||||||
let mut loaded_amount = 0;
|
let mut loaded_amount = 0;
|
||||||
let total = assets_to_load.asset_infos.len();
|
let total = assets_to_load.asset_infos.len();
|
||||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||||
let asset_id = tracker.id;
|
let asset_id = tracker.id;
|
||||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
println!("loading {}: // load state: {:?}", tracker.name, asset_server.load_state(asset_id));
|
println!(
|
||||||
|
"loading {}: // load state: {:?}",
|
||||||
|
tracker.name,
|
||||||
|
asset_server.load_state(asset_id)
|
||||||
|
);
|
||||||
|
|
||||||
// FIXME: hack for now
|
// FIXME: hack for now
|
||||||
let mut failed = false;// asset_server.load_state(asset_id) == bevy::asset::LoadState::Failed(_error);
|
let mut failed = false; // asset_server.load_state(asset_id) == bevy::asset::LoadState::Failed(_error);
|
||||||
match asset_server.load_state(asset_id) {
|
match asset_server.load_state(asset_id) {
|
||||||
bevy::asset::LoadState::Failed(_) => {
|
bevy::asset::LoadState::Failed(_) => failed = true,
|
||||||
failed = true
|
|
||||||
},
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
tracker.loaded = loaded || failed;
|
tracker.loaded = loaded || failed;
|
||||||
@ -209,7 +207,7 @@ pub(crate) fn check_for_loaded2(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let progress: f32 = loaded_amount as f32 / total as f32;
|
let progress: f32 = loaded_amount as f32 / total as f32;
|
||||||
println!("progress: {}",progress);
|
println!("progress: {}", progress);
|
||||||
assets_to_load.progress = progress;
|
assets_to_load.progress = progress;
|
||||||
|
|
||||||
if all_loaded {
|
if all_loaded {
|
||||||
@ -219,14 +217,11 @@ pub(crate) fn check_for_loaded2(
|
|||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(BlueprintAssetsLoaded)
|
.insert(BlueprintAssetsLoaded)
|
||||||
.remove::<BlueprintAssetsNotLoaded>()
|
.remove::<BlueprintAssetsNotLoaded>()
|
||||||
.remove::<AssetsToLoad>()
|
.remove::<AssetsToLoad>();
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn spawn_from_blueprints2(
|
pub(crate) fn spawn_from_blueprints2(
|
||||||
spawn_placeholders: Query<
|
spawn_placeholders: Query<
|
||||||
(
|
(
|
||||||
@ -254,15 +249,8 @@ pub(crate) fn spawn_from_blueprints2(
|
|||||||
|
|
||||||
children: Query<&Children>,
|
children: Query<&Children>,
|
||||||
) {
|
) {
|
||||||
for (
|
for (entity, blupeprint_name, blueprint_path, transform, original_parent, add_to_world, name) in
|
||||||
entity,
|
spawn_placeholders.iter()
|
||||||
blupeprint_name,
|
|
||||||
blueprint_path,
|
|
||||||
transform,
|
|
||||||
original_parent,
|
|
||||||
add_to_world,
|
|
||||||
name,
|
|
||||||
) in spawn_placeholders.iter()
|
|
||||||
{
|
{
|
||||||
info!(
|
info!(
|
||||||
"attempting to spawn blueprint {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
"attempting to spawn blueprint {:?} for entity {:?}, id: {:?}, parent:{:?}",
|
||||||
@ -272,12 +260,9 @@ pub(crate) fn spawn_from_blueprints2(
|
|||||||
// info!("attempting to spawn {:?}", model_path);
|
// info!("attempting to spawn {:?}", model_path);
|
||||||
let model_handle: Handle<Gltf> = asset_server.load(blueprint_path.0.clone()); // FIXME: kinda weird now
|
let model_handle: Handle<Gltf> = asset_server.load(blueprint_path.0.clone()); // FIXME: kinda weird now
|
||||||
|
|
||||||
let gltf = assets_gltf.get(&model_handle).unwrap_or_else(|| {
|
let gltf = assets_gltf
|
||||||
panic!(
|
.get(&model_handle)
|
||||||
"gltf file {:?} should have been loaded",
|
.unwrap_or_else(|| panic!("gltf file {:?} should have been loaded", &blueprint_path.0));
|
||||||
&blueprint_path.0
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
// WARNING we work under the assumtion that there is ONLY ONE named scene, and that the first one is the right one
|
// WARNING we work under the assumtion that there is ONLY ONE named scene, and that the first one is the right one
|
||||||
let main_scene_name = gltf
|
let main_scene_name = gltf
|
||||||
@ -301,7 +286,7 @@ pub(crate) fn spawn_from_blueprints2(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut named_animations:HashMap<String, Handle<AnimationClip>> = HashMap::new() ;
|
let mut named_animations: HashMap<String, Handle<AnimationClip>> = HashMap::new();
|
||||||
for (key, value) in gltf.named_animations.iter() {
|
for (key, value) in gltf.named_animations.iter() {
|
||||||
named_animations.insert(key.to_string(), value.clone());
|
named_animations.insert(key.to_string(), value.clone());
|
||||||
}
|
}
|
||||||
@ -317,7 +302,7 @@ pub(crate) fn spawn_from_blueprints2(
|
|||||||
OriginalChildren(original_children),
|
OriginalChildren(original_children),
|
||||||
BlueprintAnimations {
|
BlueprintAnimations {
|
||||||
// these are animations specific to the inside of the blueprint
|
// these are animations specific to the inside of the blueprint
|
||||||
named_animations: named_animations//gltf.named_animations.clone(),
|
named_animations: named_animations, //gltf.named_animations.clone(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -329,8 +314,3 @@ pub(crate) fn spawn_from_blueprints2(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,36 +16,42 @@ use bevy::{
|
|||||||
use crate::{ronstring_to_reflect_component, GltfProcessed};
|
use crate::{ronstring_to_reflect_component, GltfProcessed};
|
||||||
|
|
||||||
// , mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>
|
// , mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>
|
||||||
fn find_entity_components(entity: Entity, name: &Name, parent: &Parent, reflect_components: Vec<(Box<dyn Reflect>, TypeRegistration)>, entity_components: &HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>) -> (Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>){
|
fn find_entity_components(
|
||||||
// we assign the components specified /xxx_components objects to their parent node
|
entity: Entity,
|
||||||
let mut target_entity = entity;
|
name: &Name,
|
||||||
// if the node contains "components" or ends with "_pa" (ie add to parent), the components will not be added to the entity itself but to its parent
|
parent: &Parent,
|
||||||
// this is mostly used for Blender collections
|
reflect_components: Vec<(Box<dyn Reflect>, TypeRegistration)>,
|
||||||
if name.as_str().contains("components") || name.as_str().ends_with("_pa") {
|
entity_components: &HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>,
|
||||||
debug!("adding components to parent");
|
) -> (Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>) {
|
||||||
target_entity = parent.get();
|
// we assign the components specified /xxx_components objects to their parent node
|
||||||
}
|
let mut target_entity = entity;
|
||||||
debug!("adding to {:?}", target_entity);
|
// if the node contains "components" or ends with "_pa" (ie add to parent), the components will not be added to the entity itself but to its parent
|
||||||
|
// this is mostly used for Blender collections
|
||||||
|
if name.as_str().contains("components") || name.as_str().ends_with("_pa") {
|
||||||
|
debug!("adding components to parent");
|
||||||
|
target_entity = parent.get();
|
||||||
|
}
|
||||||
|
debug!("adding to {:?}", target_entity);
|
||||||
|
|
||||||
// if there where already components set to be added to this entity (for example when entity_data was refering to a parent), update the vec of entity_components accordingly
|
// if there where already components set to be added to this entity (for example when entity_data was refering to a parent), update the vec of entity_components accordingly
|
||||||
// this allows for example blender collection to provide basic ecs data & the instances to override/ define their own values
|
// this allows for example blender collection to provide basic ecs data & the instances to override/ define their own values
|
||||||
if entity_components.contains_key(&target_entity) {
|
if entity_components.contains_key(&target_entity) {
|
||||||
let mut updated_components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new();
|
let mut updated_components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new();
|
||||||
let current_components = &entity_components[&target_entity];
|
let current_components = &entity_components[&target_entity];
|
||||||
// first inject the current components
|
// first inject the current components
|
||||||
for (component, type_registration) in current_components {
|
for (component, type_registration) in current_components {
|
||||||
updated_components.push((component.clone_value(), type_registration.clone()));
|
updated_components.push((component.clone_value(), type_registration.clone()));
|
||||||
}
|
}
|
||||||
// then inject the new components: this also enables overwrite components set in the collection
|
// then inject the new components: this also enables overwrite components set in the collection
|
||||||
for (component, type_registration) in reflect_components {
|
for (component, type_registration) in reflect_components {
|
||||||
updated_components.push((component.clone_value(), type_registration));
|
updated_components.push((component.clone_value(), type_registration));
|
||||||
}
|
}
|
||||||
return (target_entity, updated_components)
|
return (target_entity, updated_components);
|
||||||
//entity_components.insert(target_entity, updated_components);
|
//entity_components.insert(target_entity, updated_components);
|
||||||
} else {
|
} else {
|
||||||
return (target_entity, reflect_components);
|
return (target_entity, reflect_components);
|
||||||
// entity_components.insert(target_entity, reflect_components);
|
// entity_components.insert(target_entity, reflect_components);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// main function: injects components into each entity in gltf files that have `gltf_extras`, using reflection
|
/// main function: injects components into each entity in gltf files that have `gltf_extras`, using reflection
|
||||||
@ -72,11 +78,11 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
let type_registry = type_registry.read();
|
let type_registry = type_registry.read();
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
let (target_entity, updated_components) =
|
||||||
|
find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
||||||
entity_components.insert(target_entity, updated_components);
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (entity, name, extra, parent) in scene_extras.iter(world) {
|
for (entity, name, extra, parent) in scene_extras.iter(world) {
|
||||||
debug!(
|
debug!(
|
||||||
"Name: {}, entity {:?}, parent: {:?}, scene_extras {:?}",
|
"Name: {}, entity {:?}, parent: {:?}, scene_extras {:?}",
|
||||||
@ -87,7 +93,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
let type_registry = type_registry.read();
|
let type_registry = type_registry.read();
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
let (target_entity, updated_components) =
|
||||||
|
find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
||||||
entity_components.insert(target_entity, updated_components);
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +108,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
let type_registry = type_registry.read();
|
let type_registry = type_registry.read();
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
let (target_entity, updated_components) =
|
||||||
|
find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
||||||
entity_components.insert(target_entity, updated_components);
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,11 +123,11 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
let type_registry = type_registry.read();
|
let type_registry = type_registry.read();
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
let (target_entity, updated_components) =
|
||||||
|
find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
||||||
entity_components.insert(target_entity, updated_components);
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (entity, components) in entity_components {
|
for (entity, components) in entity_components {
|
||||||
let type_registry: &AppTypeRegistry = world.resource();
|
let type_registry: &AppTypeRegistry = world.resource();
|
||||||
let type_registry = type_registry.clone();
|
let type_registry = type_registry.clone();
|
||||||
|
@ -16,9 +16,7 @@ pub fn ronstring_to_reflect_component(
|
|||||||
// println!("ron_string {:?}", ron_string);
|
// println!("ron_string {:?}", ron_string);
|
||||||
for (name, value) in lookup.into_iter() {
|
for (name, value) in lookup.into_iter() {
|
||||||
let parsed_value: String = match value.clone() {
|
let parsed_value: String = match value.clone() {
|
||||||
Value::String(str) => {
|
Value::String(str) => str,
|
||||||
str
|
|
||||||
}
|
|
||||||
_ => ron::to_string(&value).unwrap().to_string(),
|
_ => ron::to_string(&value).unwrap().to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -95,9 +93,7 @@ fn bevy_components_string_to_components(
|
|||||||
let lookup: HashMap<String, Value> = ron::from_str(&parsed_value).unwrap();
|
let lookup: HashMap<String, Value> = ron::from_str(&parsed_value).unwrap();
|
||||||
for (key, value) in lookup.into_iter() {
|
for (key, value) in lookup.into_iter() {
|
||||||
let parsed_value: String = match value.clone() {
|
let parsed_value: String = match value.clone() {
|
||||||
Value::String(str) => {
|
Value::String(str) => str,
|
||||||
str
|
|
||||||
}
|
|
||||||
_ => ron::to_string(&value).unwrap().to_string(),
|
_ => ron::to_string(&value).unwrap().to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ fn spawn_blueprint(
|
|||||||
if keycode.just_pressed(KeyCode::S) {
|
if keycode.just_pressed(KeyCode::S) {
|
||||||
let new_entity = commands.spawn((
|
let new_entity = commands.spawn((
|
||||||
BlueprintInfo(name: "Health_Pickup".to_string(), path:""), // mandatory !!
|
BlueprintInfo(name: "Health_Pickup".to_string(), path:""), // mandatory !!
|
||||||
SpawnHere, // mandatory !!
|
SpawnBlueprint, // mandatory !!
|
||||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)), // VERY important !!
|
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)), // VERY important !!
|
||||||
// any other component you want to insert
|
// any other component you want to insert
|
||||||
));
|
));
|
||||||
@ -115,7 +115,7 @@ You can spawn entities from blueprints like this:
|
|||||||
```rust no_run
|
```rust no_run
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
BlueprintInfo("Health_Pickup".to_string()), // mandatory !!
|
BlueprintInfo("Health_Pickup".to_string()), // mandatory !!
|
||||||
SpawnHere, // mandatory !!
|
SpawnBlueprint, // mandatory !!
|
||||||
|
|
||||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)), // optional
|
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)), // optional
|
||||||
// any other component you want to insert
|
// any other component you want to insert
|
||||||
@ -135,7 +135,7 @@ you can just add any additional components you need when spawning :
|
|||||||
```rust no_run
|
```rust no_run
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
BlueprintInfo("Health_Pickup".to_string()),
|
BlueprintInfo("Health_Pickup".to_string()),
|
||||||
SpawnHere,
|
SpawnBlueprint,
|
||||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||||
// from Rapier/bevy_xpbd: this means the entity will also have a velocity component when inserted into the world
|
// from Rapier/bevy_xpbd: this means the entity will also have a velocity component when inserted into the world
|
||||||
Velocity {
|
Velocity {
|
||||||
@ -153,7 +153,7 @@ for example
|
|||||||
```rust no_run
|
```rust no_run
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
BlueprintInfo("Health_Pickup".to_string()),
|
BlueprintInfo("Health_Pickup".to_string()),
|
||||||
SpawnHere,
|
SpawnBlueprint,
|
||||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||||
HealthPowerUp(20)// if this is component is also present inside the "Health_Pickup" blueprint, that one will be replaced with this component during spawning
|
HealthPowerUp(20)// if this is component is also present inside the "Health_Pickup" blueprint, that one will be replaced with this component during spawning
|
||||||
))
|
))
|
||||||
@ -164,7 +164,7 @@ commands.spawn((
|
|||||||
|
|
||||||
There is also a ```BluePrintBundle``` for convenience , which just has
|
There is also a ```BluePrintBundle``` for convenience , which just has
|
||||||
* a ```BlueprintInfo``` component
|
* a ```BlueprintInfo``` component
|
||||||
* a ```SpawnHere``` component
|
* a ```SpawnBlueprint``` component
|
||||||
|
|
||||||
## Additional information
|
## Additional information
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ pub(crate) fn prepare_blueprints(
|
|||||||
Option<&Name>,
|
Option<&Name>,
|
||||||
Option<&BlueprintsList>,
|
Option<&BlueprintsList>,
|
||||||
),
|
),
|
||||||
(Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>),
|
(Added<BlueprintName>, Added<SpawnBlueprint>, Without<Spawned>),
|
||||||
>,
|
>,
|
||||||
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
@ -22,7 +22,7 @@ pub struct BlueprintPath(pub String);
|
|||||||
/// flag component needed to signify the intent to spawn a Blueprint
|
/// flag component needed to signify the intent to spawn a Blueprint
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct SpawnHere;
|
pub struct SpawnBlueprint;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
/// flag component for dynamically spawned scenes
|
/// flag component for dynamically spawned scenes
|
||||||
@ -93,7 +93,7 @@ pub(crate) fn blueprints_prepare_spawn(
|
|||||||
Entity,
|
Entity,
|
||||||
&BlueprintPath,
|
&BlueprintPath,
|
||||||
),
|
),
|
||||||
(Added<BlueprintPath>, Without<Spawned>, Without<SpawnHere>)>,
|
(Added<BlueprintPath>, Without<Spawned>, Without<SpawnBlueprint>)>,
|
||||||
|
|
||||||
// before 0.14 we have to use a seperate query, after migrating we can query at the root level
|
// before 0.14 we have to use a seperate query, after migrating we can query at the root level
|
||||||
entities_with_assets: Query<
|
entities_with_assets: Query<
|
||||||
|
@ -5,8 +5,8 @@ use bevy::prelude::*;
|
|||||||
use bevy::scene::SceneInstance;
|
use bevy::scene::SceneInstance;
|
||||||
// use bevy::utils::hashbrown::HashSet;
|
// use bevy::utils::hashbrown::HashSet;
|
||||||
|
|
||||||
use crate::{BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintInfo, BlueprintReadyForPostProcess, BlueprintInstanceReady, BlueprintSpawning, SpawnTrackRoot, SubBlueprintsSpawnTracker};
|
use crate::{BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintInfo, BlueprintReadyForPostProcess, BlueprintInstanceReady, BlueprintSpawning, SubBlueprintSpawnRoot, SubBlueprintsSpawnTracker};
|
||||||
use crate::{SpawnHere, Spawned};
|
use crate::{SpawnBlueprint, Spawned};
|
||||||
use crate::{
|
use crate::{
|
||||||
BlueprintEvent, CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren
|
BlueprintEvent, CopyComponents, InBlueprint, NoInBlueprint, OriginalChildren
|
||||||
};
|
};
|
||||||
@ -32,9 +32,9 @@ pub(crate) fn spawned_blueprint_post_process( // rename to '
|
|||||||
&BlueprintInfo,
|
&BlueprintInfo,
|
||||||
|
|
||||||
// sub blueprint instances tracker
|
// sub blueprint instances tracker
|
||||||
Option<&SpawnTrackRoot>
|
Option<&SubBlueprintSpawnRoot>
|
||||||
),
|
),
|
||||||
(With<SpawnHere>, With<SceneInstance>, Added<BlueprintReadyForPostProcess>),
|
(With<SpawnBlueprint>, With<SceneInstance>, Added<BlueprintReadyForPostProcess>),
|
||||||
>,
|
>,
|
||||||
added_animation_players: Query<(Entity, &Parent), Added<AnimationPlayer>>,
|
added_animation_players: Query<(Entity, &Parent), Added<AnimationPlayer>>,
|
||||||
all_children: Query<&Children>,
|
all_children: Query<&Children>,
|
||||||
@ -103,7 +103,7 @@ pub(crate) fn spawned_blueprint_post_process( // rename to '
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commands.entity(original).remove::<SpawnHere>();
|
commands.entity(original).remove::<SpawnBlueprint>();
|
||||||
commands.entity(original).remove::<Spawned>();
|
commands.entity(original).remove::<Spawned>();
|
||||||
// commands.entity(original).remove::<Handle<Scene>>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want
|
// commands.entity(original).remove::<Handle<Scene>>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want
|
||||||
//commands.entity(original).remove::<BlueprintAssetsLoadState>(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ?
|
//commands.entity(original).remove::<BlueprintAssetsLoadState>(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ?
|
||||||
|
@ -22,13 +22,18 @@ pub fn compute_scene_aabbs(
|
|||||||
.aabb_cache
|
.aabb_cache
|
||||||
.get(&name.to_string())
|
.get(&name.to_string())
|
||||||
.expect("we should have the aabb available");
|
.expect("we should have the aabb available");
|
||||||
commands.entity(root_entity).insert(*aabb).insert(BlueprintReadyForFinalizing);
|
commands
|
||||||
|
.entity(root_entity)
|
||||||
|
.insert(*aabb)
|
||||||
|
.insert(BlueprintReadyForFinalizing);
|
||||||
} else {
|
} else {
|
||||||
let aabb = compute_descendant_aabb(root_entity, &children, &existing_aabbs);
|
let aabb = compute_descendant_aabb(root_entity, &children, &existing_aabbs);
|
||||||
blenvy_config.aabb_cache.insert(name.to_string(), aabb);
|
blenvy_config.aabb_cache.insert(name.to_string(), aabb);
|
||||||
info!("generating aabb for {:?}", name);
|
info!("generating aabb for {:?}", name);
|
||||||
commands.entity(root_entity).insert(aabb).insert(BlueprintReadyForFinalizing);
|
commands
|
||||||
|
.entity(root_entity)
|
||||||
|
.insert(aabb)
|
||||||
|
.insert(BlueprintReadyForFinalizing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for entity in other_entities.iter() {
|
for entity in other_entities.iter() {
|
||||||
|
@ -6,6 +6,8 @@ use bevy::utils::HashMap;
|
|||||||
/// storage for animations for a given entity's BLUEPRINT (ie for example a characters animations), essentially a clone of gltf's `named_animations`
|
/// storage for animations for a given entity's BLUEPRINT (ie for example a characters animations), essentially a clone of gltf's `named_animations`
|
||||||
pub struct BlueprintAnimations {
|
pub struct BlueprintAnimations {
|
||||||
pub named_animations: HashMap<String, Handle<AnimationClip>>,
|
pub named_animations: HashMap<String, Handle<AnimationClip>>,
|
||||||
|
pub named_indices: HashMap<String, AnimationNodeIndex>,
|
||||||
|
pub graph: Handle<AnimationGraph>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
@ -20,6 +22,7 @@ pub struct BlueprintAnimationPlayerLink(pub Entity);
|
|||||||
/// storage for scene level animations for a given entity (hierarchy), essentially a clone of gltf's `named_animations`
|
/// storage for scene level animations for a given entity (hierarchy), essentially a clone of gltf's `named_animations`
|
||||||
pub struct SceneAnimations {
|
pub struct SceneAnimations {
|
||||||
pub named_animations: HashMap<String, Handle<AnimationClip>>,
|
pub named_animations: HashMap<String, Handle<AnimationClip>>,
|
||||||
|
pub named_indices: HashMap<String, AnimationNodeIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
@ -73,7 +76,7 @@ pub struct AnimationMarkerReached {
|
|||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
/// triggers events when a given animation marker is reached for INSTANCE animations
|
/// triggers events when a given animation marker is reached for INSTANCE animations
|
||||||
pub fn trigger_instance_animation_markers_events(
|
pub fn trigger_instance_animation_markers_events(
|
||||||
animation_infos: Query<(
|
animation_infos: Query<(
|
||||||
@ -218,4 +221,4 @@ pub fn trigger_blueprint_animation_markers_events(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use bevy::{asset::LoadedUntypedAsset, prelude::*};
|
||||||
|
|
||||||
use bevy::{asset::LoadedUntypedAsset, gltf::Gltf, prelude::*, utils::HashMap};
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{BlenvyConfig, BlueprintAnimations};
|
|
||||||
|
|
||||||
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
||||||
#[derive(Component, Reflect, Default, Debug, Deserialize)]
|
#[derive(Component, Reflect, Default, Debug, Deserialize)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct MyAsset{
|
pub struct BlueprintAsset {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub path: String
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
/// helper component, is used to store the list of sub blueprints to enable automatic loading of dependend blueprints
|
||||||
@ -18,7 +14,7 @@ pub struct MyAsset{
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintAssets {
|
pub struct BlueprintAssets {
|
||||||
/// only this field should get filled in from the Blender side
|
/// only this field should get filled in from the Blender side
|
||||||
pub assets: Vec<MyAsset>,
|
pub assets: Vec<BlueprintAsset>,
|
||||||
/// set to default when deserializing
|
/// set to default when deserializing
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[reflect(default)]
|
#[reflect(default)]
|
||||||
@ -27,16 +23,14 @@ pub struct BlueprintAssets {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[reflect(default)]
|
#[reflect(default)]
|
||||||
pub progress: f32,
|
pub progress: f32,
|
||||||
#[reflect(ignore)]
|
#[reflect(ignore)]
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub asset_infos: Vec<AssetLoadTracker>,
|
pub asset_infos: Vec<AssetLoadTracker>,
|
||||||
}
|
}
|
||||||
//(pub Vec<MyAsset>);
|
//(pub Vec<BlueprintAsset>);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
///
|
///
|
||||||
/// flag component, usually added when a blueprint is loaded
|
/// flag component, usually added when a blueprint is loaded
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub(crate) struct BlueprintAssetsLoaded;
|
pub(crate) struct BlueprintAssetsLoaded;
|
||||||
@ -46,7 +40,7 @@ pub(crate) struct BlueprintAssetsNotLoaded;
|
|||||||
|
|
||||||
/// helper component, for tracking loaded assets's loading state, id , handle etc
|
/// helper component, for tracking loaded assets's loading state, id , handle etc
|
||||||
#[derive(Debug, Reflect)]
|
#[derive(Debug, Reflect)]
|
||||||
pub(crate) struct AssetLoadTracker {
|
pub struct AssetLoadTracker {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
53
crates/blenvy/src/blueprints/hot_reload.rs
Normal file
53
crates/blenvy/src/blueprints/hot_reload.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use crate::{BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintInfo, SpawnBlueprint};
|
||||||
|
use bevy::asset::AssetEvent;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy::scene::SceneInstance;
|
||||||
|
|
||||||
|
pub(crate) fn react_to_asset_changes(
|
||||||
|
mut gltf_events: EventReader<AssetEvent<Gltf>>,
|
||||||
|
// mut untyped_events: EventReader<AssetEvent<LoadedUntypedAsset>>,
|
||||||
|
mut blueprint_assets: Query<(
|
||||||
|
Entity,
|
||||||
|
Option<&Name>,
|
||||||
|
&BlueprintInfo,
|
||||||
|
&mut BlueprintAssetsLoadState,
|
||||||
|
Option<&Children>,
|
||||||
|
)>,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
for event in gltf_events.read() {
|
||||||
|
// LoadedUntypedAsset
|
||||||
|
match event {
|
||||||
|
AssetEvent::Modified { id } => {
|
||||||
|
// React to the image being modified
|
||||||
|
// println!("Modified gltf {:?}", asset_server.get_path(*id));
|
||||||
|
for (entity, entity_name, _blueprint_info, mut assets_to_load, children) in
|
||||||
|
blueprint_assets.iter_mut()
|
||||||
|
{
|
||||||
|
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||||
|
if asset_server.get_path(*id).is_some() {
|
||||||
|
if tracker.path == asset_server.get_path(*id).unwrap().to_string() {
|
||||||
|
println!("HOLY MOLY IT DETECTS !!, now respawn {:?}", entity_name);
|
||||||
|
if children.is_some() {
|
||||||
|
for child in children.unwrap().iter() {
|
||||||
|
commands.entity(*child).despawn_recursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
|
.remove::<BlueprintAssetsLoaded>()
|
||||||
|
.remove::<SceneInstance>()
|
||||||
|
.remove::<BlueprintAssetsLoadState>()
|
||||||
|
.insert(SpawnBlueprint);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::{BlenvyConfig, BlueprintReadyForPostProcess};
|
use crate::BlenvyConfig;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
@ -13,18 +13,16 @@ pub struct MaterialInfo {
|
|||||||
#[derive(Component, Default, Debug)]
|
#[derive(Component, Default, Debug)]
|
||||||
pub struct MaterialProcessed;
|
pub struct MaterialProcessed;
|
||||||
|
|
||||||
|
|
||||||
/// system that injects / replaces materials from material library
|
/// system that injects / replaces materials from material library
|
||||||
pub(crate) fn inject_materials(
|
pub(crate) fn inject_materials(
|
||||||
mut blenvy_config: ResMut<BlenvyConfig>,
|
mut blenvy_config: ResMut<BlenvyConfig>,
|
||||||
material_infos: Query<
|
material_infos: Query<
|
||||||
(Entity, &MaterialInfo, &Children),
|
(Entity, &MaterialInfo, &Children),
|
||||||
Without<MaterialProcessed>
|
Without<MaterialProcessed>, // (With<BlueprintReadyForPostProcess>)
|
||||||
// (With<BlueprintReadyForPostProcess>)
|
/*(
|
||||||
/*(
|
Added<BlueprintMaterialAssetsLoaded>,
|
||||||
Added<BlueprintMaterialAssetsLoaded>,
|
With<BlueprintMaterialAssetsLoaded>,
|
||||||
With<BlueprintMaterialAssetsLoaded>,
|
),*/
|
||||||
),*/
|
|
||||||
>,
|
>,
|
||||||
with_materials_and_meshes: Query<
|
with_materials_and_meshes: Query<
|
||||||
(),
|
(),
|
||||||
@ -55,10 +53,14 @@ pub(crate) fn inject_materials(
|
|||||||
material_found = Some(material);
|
material_found = Some(material);
|
||||||
} else {
|
} else {
|
||||||
let model_handle: Handle<Gltf> = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now
|
let model_handle: Handle<Gltf> = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now
|
||||||
let mat_gltf = assets_gltf
|
let mat_gltf = assets_gltf.get(model_handle.id()).expect(&format!(
|
||||||
.get(model_handle.id())
|
"materials file {} should have been preloaded",
|
||||||
.expect(&format!("materials file {} should have been preloaded", material_info.path));
|
material_info.path
|
||||||
if mat_gltf.named_materials.contains_key(&material_info.name as &str) {
|
));
|
||||||
|
if mat_gltf
|
||||||
|
.named_materials
|
||||||
|
.contains_key(&material_info.name as &str)
|
||||||
|
{
|
||||||
let material = mat_gltf
|
let material = mat_gltf
|
||||||
.named_materials
|
.named_materials
|
||||||
.get(&material_info.name as &str)
|
.get(&material_info.name as &str)
|
||||||
@ -86,4 +88,4 @@ pub(crate) fn inject_materials(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@ pub use materials::*;
|
|||||||
pub mod copy_components;
|
pub mod copy_components;
|
||||||
pub use copy_components::*;
|
pub use copy_components::*;
|
||||||
|
|
||||||
use core::fmt;
|
pub(crate) mod hot_reload;
|
||||||
use std::path::PathBuf;
|
pub(crate) use hot_reload::*;
|
||||||
|
|
||||||
use bevy::{prelude::*, render::primitives::Aabb, utils::HashMap};
|
use bevy::{prelude::*, utils::HashMap};
|
||||||
|
|
||||||
use crate::{BlenvyConfig, GltfComponentsSet};
|
use crate::{BlenvyConfig, GltfComponentsSet};
|
||||||
|
|
||||||
@ -33,24 +33,26 @@ pub enum GltfBlueprintsSet {
|
|||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct BluePrintBundle {
|
pub struct BluePrintBundle {
|
||||||
pub blueprint: BlueprintInfo,
|
pub blueprint: BlueprintInfo,
|
||||||
pub spawn_here: SpawnHere,
|
pub spawn_here: SpawnBlueprint,
|
||||||
}
|
}
|
||||||
impl Default for BluePrintBundle {
|
impl Default for BluePrintBundle {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
BluePrintBundle {
|
BluePrintBundle {
|
||||||
blueprint: BlueprintInfo{ name: "default".into(), path:"".into()},
|
blueprint: BlueprintInfo {
|
||||||
spawn_here: SpawnHere,
|
name: "default".into(),
|
||||||
|
path: "".into(),
|
||||||
|
},
|
||||||
|
spawn_here: SpawnBlueprint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
/// Plugin for gltf blueprints
|
/// Plugin for gltf blueprints
|
||||||
pub struct BlueprintsPlugin {
|
pub struct BlueprintsPlugin {
|
||||||
/// Automatically generate aabbs for the blueprints root objects
|
/// Automatically generate aabbs for the blueprints root objects
|
||||||
pub aabbs: bool,
|
pub aabbs: bool,
|
||||||
///
|
/// use library of materials
|
||||||
pub material_library: bool,
|
pub material_library: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +60,7 @@ impl Default for BlueprintsPlugin {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
aabbs: false,
|
aabbs: false,
|
||||||
material_library: false
|
material_library: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,7 +73,6 @@ fn hot_reload(watching_for_changes: Res<WatchingForChanges>) -> bool {
|
|||||||
watching_for_changes.0
|
watching_for_changes.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trait BlenvyApp {
|
trait BlenvyApp {
|
||||||
fn register_watching_for_changes(&mut self) -> &mut Self;
|
fn register_watching_for_changes(&mut self) -> &mut Self;
|
||||||
}
|
}
|
||||||
@ -92,16 +93,13 @@ impl BlenvyApp for App {
|
|||||||
pub(crate) struct WatchingForChanges(pub(crate) bool);
|
pub(crate) struct WatchingForChanges(pub(crate) bool);
|
||||||
const ASSET_ERROR: &str = ""; // TODO
|
const ASSET_ERROR: &str = ""; // TODO
|
||||||
|
|
||||||
|
|
||||||
impl Plugin for BlueprintsPlugin {
|
impl Plugin for BlueprintsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_watching_for_changes()
|
||||||
.register_watching_for_changes()
|
.add_event::<BlueprintEvent>()
|
||||||
|
|
||||||
|
|
||||||
.register_type::<BlueprintInfo>()
|
.register_type::<BlueprintInfo>()
|
||||||
.register_type::<MaterialInfo>()
|
.register_type::<MaterialInfo>()
|
||||||
.register_type::<SpawnHere>()
|
.register_type::<SpawnBlueprint>()
|
||||||
.register_type::<BlueprintAnimations>()
|
.register_type::<BlueprintAnimations>()
|
||||||
.register_type::<SceneAnimations>()
|
.register_type::<SceneAnimations>()
|
||||||
.register_type::<AnimationInfo>()
|
.register_type::<AnimationInfo>()
|
||||||
@ -111,15 +109,12 @@ impl Plugin for BlueprintsPlugin {
|
|||||||
.register_type::<HashMap<u32, Vec<String>>>()
|
.register_type::<HashMap<u32, Vec<String>>>()
|
||||||
.register_type::<HashMap<String, HashMap<u32, Vec<String>>>>()
|
.register_type::<HashMap<String, HashMap<u32, Vec<String>>>>()
|
||||||
.add_event::<AnimationMarkerReached>()
|
.add_event::<AnimationMarkerReached>()
|
||||||
.register_type::<MyAsset>()
|
.register_type::<BlueprintAsset>()
|
||||||
.register_type::<Vec<MyAsset>>()
|
.register_type::<Vec<BlueprintAsset>>()
|
||||||
.register_type::<Vec<String>>()
|
.register_type::<Vec<String>>()
|
||||||
.register_type::<BlueprintAssets>()
|
.register_type::<BlueprintAssets>()
|
||||||
|
|
||||||
.add_event::<BlueprintEvent>()
|
|
||||||
|
|
||||||
|
|
||||||
.register_type::<HashMap<String, Vec<String>>>()
|
.register_type::<HashMap<String, Vec<String>>>()
|
||||||
|
.register_type::<HideUntilReady>()
|
||||||
.configure_sets(
|
.configure_sets(
|
||||||
Update,
|
Update,
|
||||||
(GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)
|
(GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)
|
||||||
@ -133,14 +128,11 @@ impl Plugin for BlueprintsPlugin {
|
|||||||
blueprints_check_assets_loading,
|
blueprints_check_assets_loading,
|
||||||
blueprints_assets_ready,
|
blueprints_assets_ready,
|
||||||
blueprints_scenes_spawned,
|
blueprints_scenes_spawned,
|
||||||
blueprints_transfer_components,
|
blueprints_cleanup_spawned_scene,
|
||||||
|
|
||||||
// post process
|
// post process
|
||||||
inject_materials,
|
inject_materials,
|
||||||
compute_scene_aabbs,// .run_if(aabbs_enabled),
|
compute_scene_aabbs, // .run_if(aabbs_enabled),
|
||||||
|
|
||||||
blueprints_finalize_instances,
|
blueprints_finalize_instances,
|
||||||
|
|
||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
.in_set(GltfBlueprintsSet::Spawn),
|
.in_set(GltfBlueprintsSet::Spawn),
|
||||||
@ -153,7 +145,6 @@ impl Plugin for BlueprintsPlugin {
|
|||||||
),
|
),
|
||||||
)*/
|
)*/
|
||||||
// hot reload
|
// hot reload
|
||||||
.add_systems(Update, react_to_asset_changes.run_if(hot_reload))
|
.add_systems(Update, react_to_asset_changes.run_if(hot_reload));
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use bevy::{asset::LoadedUntypedAsset, ecs::entity, gltf::Gltf, prelude::*, render::view::visibility, scene::SceneInstance, transform::commands, utils::hashbrown::HashMap};
|
use bevy::{gltf::Gltf, prelude::*, scene::SceneInstance, utils::hashbrown::HashMap};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{BlueprintAssets, BlueprintAssetsLoadState, AssetLoadTracker, BlenvyConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
use crate::{
|
||||||
|
AssetLoadTracker, BlenvyConfig, BlueprintAnimationPlayerLink, BlueprintAnimations,
|
||||||
|
BlueprintAssets, BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded,
|
||||||
|
};
|
||||||
|
|
||||||
/// this is a flag component for our levels/game world
|
/// this is a flag component for our levels/game world
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
@ -11,7 +14,7 @@ pub struct GameWorldTag;
|
|||||||
|
|
||||||
/// Main component for the blueprints
|
/// Main component for the blueprints
|
||||||
/// has both name & path of the blueprint to enable injecting the data from the correct blueprint
|
/// has both name & path of the blueprint to enable injecting the data from the correct blueprint
|
||||||
/// into the entity that contains this component
|
/// into the entity that contains this component
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintInfo {
|
pub struct BlueprintInfo {
|
||||||
@ -22,15 +25,10 @@ pub struct BlueprintInfo {
|
|||||||
/// flag component needed to signify the intent to spawn a Blueprint
|
/// flag component needed to signify the intent to spawn a Blueprint
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct SpawnHere;
|
pub struct SpawnBlueprint;
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
/// flag component for dynamically spawned scenes
|
|
||||||
pub struct Spawned;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
/// flag component added when a Blueprint instance ist Ready : ie :
|
/// flag component added when a Blueprint instance ist Ready : ie :
|
||||||
/// - its assets have loaded
|
/// - its assets have loaded
|
||||||
/// - it has finished spawning
|
/// - it has finished spawning
|
||||||
pub struct BlueprintInstanceReady;
|
pub struct BlueprintInstanceReady;
|
||||||
@ -59,76 +57,73 @@ pub struct AddToGameWorld;
|
|||||||
/// helper component, just to transfer child data
|
/// helper component, just to transfer child data
|
||||||
pub(crate) struct OriginalChildren(pub Vec<Entity>);
|
pub(crate) struct OriginalChildren(pub Vec<Entity>);
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[derive(Component)]
|
#[reflect(Component)]
|
||||||
/// You can add this component to a blueprint instance, and the instance will be hidden until it is ready
|
/// You can add this component to a blueprint instance, and the instance will be hidden until it is ready
|
||||||
/// You usually want to use this for worlds/level spawning , or dynamic spawning at runtime, but not when you are adding blueprint instances to an existing entity
|
/// You usually want to use this for worlds/level spawning , or dynamic spawning at runtime, but not when you are adding blueprint instances to an existing entity
|
||||||
/// as it would first become invisible before re-appearing again
|
/// as it would first become invisible before re-appearing again
|
||||||
pub struct HideUntilReady;
|
pub struct HideUntilReady;
|
||||||
|
|
||||||
#[derive(Event, Debug)]
|
#[derive(Event, Debug)]
|
||||||
pub enum BlueprintEvent {
|
pub enum BlueprintEvent {
|
||||||
|
/// event fired when a blueprint has finished loading all of its assets & before it attempts spawning
|
||||||
/// event fired when a blueprint has finished loading its assets & before it attempts spawning
|
|
||||||
AssetsLoaded {
|
AssetsLoaded {
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
blueprint_name: String,
|
blueprint_name: String,
|
||||||
blueprint_path: String,
|
blueprint_path: String,
|
||||||
// TODO: add assets list ?
|
// TODO: add assets list ?
|
||||||
},
|
},
|
||||||
/// event fired when a blueprint is COMPLETELY done spawning ie
|
|
||||||
/// - all its assets have been loaded
|
|
||||||
/// - the spawning attempt has been sucessfull
|
|
||||||
Spawned {
|
|
||||||
entity: Entity,
|
|
||||||
blueprint_name: String,
|
|
||||||
blueprint_path: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
///
|
///
|
||||||
InstanceReady {
|
InstanceReady {
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
blueprint_name: String,
|
blueprint_name: String,
|
||||||
blueprint_path: String,
|
blueprint_path: String,
|
||||||
}
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: move this somewhere else ?
|
// TODO: move this somewhere else ?
|
||||||
#[derive(Component, Reflect, Debug, Default)]
|
#[derive(Component, Reflect, Debug, Default)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// component used to mark any entity as Dynamic: aka add this to make sure your entity is going to be saved
|
/// component used to mark any entity as Dynamic: aka add this to make sure your entity is going to be saved
|
||||||
pub struct DynamicBlueprintInstance;
|
pub struct DynamicBlueprintInstance;
|
||||||
|
|
||||||
|
|
||||||
// TODO: move these somewhere else ?
|
// TODO: move these somewhere else ?
|
||||||
#[derive(Component, Reflect, Debug, Default)]
|
#[derive(Component, Reflect, Debug, Default)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// component gets added when a blueprint starts spawning, removed when spawning is done
|
/// component gets added when a blueprint starts spawning, removed when spawning is completely done
|
||||||
pub struct BlueprintSpawning;
|
pub struct BlueprintSpawning;
|
||||||
|
|
||||||
|
|
||||||
use gltf::Gltf as RawGltf;
|
use gltf::Gltf as RawGltf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Overview of the Blueprint Spawning process
|
||||||
|
- Blueprint Load Assets
|
||||||
|
- Blueprint Assets Ready: spawn Blueprint's scene
|
||||||
|
- Blueprint Scene Ready (SceneInstance component is present):
|
||||||
|
- get list of sub Blueprints if any, inject sub blueprints spawn tracker
|
||||||
|
- Blueprint copy components to original entity, remove useless nodes
|
||||||
|
- Blueprint post process
|
||||||
|
- generate aabb (need full hierarchy in its final form)
|
||||||
|
- inject materials from library if needed
|
||||||
|
- Blueprint Ready
|
||||||
|
- bubble information up to parent blueprint instance
|
||||||
|
- if all sub_blueprints are ready => Parent blueprint Instance is ready
|
||||||
|
=> distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ??
|
||||||
|
*/
|
||||||
|
|
||||||
pub(crate) fn blueprints_prepare_spawn(
|
pub(crate) fn blueprints_prepare_spawn(
|
||||||
blueprint_instances_to_spawn : Query<
|
blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo), Added<SpawnBlueprint>>,
|
||||||
(
|
mut commands: Commands,
|
||||||
Entity,
|
asset_server: Res<AssetServer>,
|
||||||
&BlueprintInfo,
|
|
||||||
Option<&Parent>,
|
|
||||||
Option<&BlueprintAssets>,
|
|
||||||
),(Added<SpawnHere>)
|
|
||||||
>,
|
|
||||||
mut commands: Commands,
|
|
||||||
asset_server: Res<AssetServer>,
|
|
||||||
) {
|
) {
|
||||||
|
for (entity, blueprint_info) in blueprint_instances_to_spawn.iter() {
|
||||||
for (entity, blueprint_info, parent, all_assets) in blueprint_instances_to_spawn.iter() {
|
info!(
|
||||||
info!("BLUEPRINT: to spawn detected: {:?} path:{:?}", blueprint_info.name, blueprint_info.path);
|
"BLUEPRINT: to spawn detected: {:?} path:{:?}",
|
||||||
|
blueprint_info.name, blueprint_info.path
|
||||||
|
);
|
||||||
//println!("all assets {:?}", all_assets);
|
//println!("all assets {:?}", all_assets);
|
||||||
//////////////
|
//////////////
|
||||||
|
|
||||||
// we add the asset of the blueprint itself
|
// we add the asset of the blueprint itself
|
||||||
// TODO: add detection of already loaded data
|
// TODO: add detection of already loaded data
|
||||||
let untyped_handle = asset_server.load_untyped(&blueprint_info.path);
|
let untyped_handle = asset_server.load_untyped(&blueprint_info.path);
|
||||||
@ -150,27 +145,20 @@ asset_server: Res<AssetServer>,
|
|||||||
/* prefetch attempt */
|
/* prefetch attempt */
|
||||||
let gltf = RawGltf::open(format!("assets/{}", blueprint_info.path)).unwrap();
|
let gltf = RawGltf::open(format!("assets/{}", blueprint_info.path)).unwrap();
|
||||||
for scene in gltf.scenes() {
|
for scene in gltf.scenes() {
|
||||||
let foo_extras = scene.extras().clone().unwrap();
|
let scene_extras = scene.extras().clone().unwrap();
|
||||||
|
let lookup: HashMap<String, Value> = serde_json::from_str(&scene_extras.get()).unwrap();
|
||||||
|
|
||||||
let lookup: HashMap<String, Value> = serde_json::from_str(&foo_extras.get()).unwrap();
|
if lookup.contains_key("BlueprintAssets") {
|
||||||
/*for (key, value) in lookup.clone().into_iter() {
|
|
||||||
println!("{} / {}", key, value);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if lookup.contains_key("BlueprintAssets"){
|
|
||||||
let assets_raw = &lookup["BlueprintAssets"];
|
let assets_raw = &lookup["BlueprintAssets"];
|
||||||
//println!("ASSETS RAW {}", assets_raw);
|
//println!("ASSETS RAW {}", assets_raw);
|
||||||
let all_assets: BlueprintAssets = ron::from_str(&assets_raw.as_str().unwrap()).unwrap();
|
let all_assets: BlueprintAssets =
|
||||||
|
ron::from_str(&assets_raw.as_str().unwrap()).unwrap();
|
||||||
// println!("all_assets {:?}", all_assets);
|
// println!("all_assets {:?}", all_assets);
|
||||||
|
|
||||||
for asset in all_assets.assets.iter() {
|
for asset in all_assets.assets.iter() {
|
||||||
let untyped_handle = asset_server.load_untyped(&asset.path);
|
let untyped_handle = asset_server.load_untyped(&asset.path);
|
||||||
//println!("untyped handle {:?}", untyped_handle);
|
|
||||||
//asset_server.load(asset.path);
|
|
||||||
let asset_id = untyped_handle.id();
|
let asset_id = untyped_handle.id();
|
||||||
//println!("ID {:?}", asset_id);
|
|
||||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
//println!("Loaded ? {:?}", loaded);
|
|
||||||
if !loaded {
|
if !loaded {
|
||||||
asset_infos.push(AssetLoadTracker {
|
asset_infos.push(AssetLoadTracker {
|
||||||
name: asset.name.clone(),
|
name: asset.name.clone(),
|
||||||
@ -185,50 +173,46 @@ asset_server: Res<AssetServer>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now insert load tracker
|
// now insert load tracker
|
||||||
|
// if there are assets to load
|
||||||
if !asset_infos.is_empty() {
|
if !asset_infos.is_empty() {
|
||||||
commands
|
commands.entity(entity).insert((
|
||||||
.entity(entity)
|
BlueprintAssetsLoadState {
|
||||||
.insert(BlueprintAssetsLoadState {
|
|
||||||
all_loaded: false,
|
all_loaded: false,
|
||||||
asset_infos,
|
asset_infos,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
},
|
||||||
.insert(BlueprintAssetsNotLoaded)
|
BlueprintAssetsNotLoaded,
|
||||||
;
|
));
|
||||||
} else {
|
} else {
|
||||||
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
||||||
}
|
}
|
||||||
|
// add the blueprint spawning marker
|
||||||
|
|
||||||
commands.entity(entity).insert(BlueprintSpawning);
|
commands.entity(entity).insert(BlueprintSpawning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This system tracks & updates the loading state of all blueprints assets
|
||||||
pub(crate) fn blueprints_check_assets_loading(
|
pub(crate) fn blueprints_check_assets_loading(
|
||||||
mut blueprint_assets_to_load: Query<
|
mut blueprint_assets_to_load: Query<
|
||||||
(Entity, Option<&Name>, &BlueprintInfo, &mut BlueprintAssetsLoadState),
|
(Entity, &BlueprintInfo, &mut BlueprintAssetsLoadState),
|
||||||
With<BlueprintAssetsNotLoaded>,
|
With<BlueprintAssetsNotLoaded>,
|
||||||
>,
|
>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut blueprint_events: EventWriter<BlueprintEvent>,
|
mut blueprint_events: EventWriter<BlueprintEvent>,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
for (entity, entity_name, blueprint_info, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
for (entity, blueprint_info, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||||
let mut all_loaded = true;
|
let mut all_loaded = true;
|
||||||
let mut loaded_amount = 0;
|
let mut loaded_amount = 0;
|
||||||
let total = assets_to_load.asset_infos.len();
|
let total = assets_to_load.asset_infos.len();
|
||||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
for tracker in assets_to_load.asset_infos.iter_mut() {
|
||||||
let asset_id = tracker.id;
|
let asset_id = tracker.id;
|
||||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
// println!("loading {}: // load state: {:?}", tracker.name, asset_server.load_state(asset_id));
|
|
||||||
|
|
||||||
// FIXME: hack for now
|
// FIXME: hack for now
|
||||||
let mut failed = false;// asset_server.load_state(asset_id) == bevy::asset::LoadState::Failed(_error);
|
let mut failed = false; // asset_server.load_state(asset_id) == bevy::asset::LoadState::Failed(_error);
|
||||||
match asset_server.load_state(asset_id) {
|
match asset_server.load_state(asset_id) {
|
||||||
bevy::asset::LoadState::Failed(_) => {
|
bevy::asset::LoadState::Failed(_) => failed = true,
|
||||||
failed = true
|
|
||||||
},
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
tracker.loaded = loaded || failed;
|
tracker.loaded = loaded || failed;
|
||||||
@ -240,49 +224,53 @@ pub(crate) fn blueprints_check_assets_loading(
|
|||||||
}
|
}
|
||||||
let progress: f32 = loaded_amount as f32 / total as f32;
|
let progress: f32 = loaded_amount as f32 / total as f32;
|
||||||
assets_to_load.progress = progress;
|
assets_to_load.progress = progress;
|
||||||
|
// println!("LOADING: in progress for ALL assets of {:?} (instance of {}): {} ",entity_name, blueprint_info.path, progress * 100.0);
|
||||||
|
|
||||||
if all_loaded {
|
if all_loaded {
|
||||||
assets_to_load.all_loaded = true;
|
assets_to_load.all_loaded = true;
|
||||||
// println!("LOADING: DONE for ALL assets of {:?} (instance of {}), preparing for spawn", entity_name, blueprint_info.path);
|
// println!("LOADING: DONE for ALL assets of {:?} (instance of {}), preparing for spawn", entity_name, blueprint_info.path);
|
||||||
// blueprint_events.send(BlueprintEvent::AssetsLoaded {blueprint_name:"".into(), blueprint_path: blueprint_info.path.clone() });
|
blueprint_events.send(BlueprintEvent::AssetsLoaded {
|
||||||
|
entity,
|
||||||
|
blueprint_name: blueprint_info.name.clone(),
|
||||||
|
blueprint_path: blueprint_info.path.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(BlueprintAssetsLoaded)
|
.insert(BlueprintAssetsLoaded)
|
||||||
.remove::<BlueprintAssetsNotLoaded>()
|
.remove::<BlueprintAssetsNotLoaded>()
|
||||||
//.remove::<BlueprintAssetsLoadState>() //REMOVE it in release mode/ when hot reload is off, keep it for dev/hot reload
|
//.remove::<BlueprintAssetsLoadState>() //REMOVE this component in release mode/ when hot reload is off, keep it for dev/hot reload
|
||||||
;
|
;
|
||||||
}else {
|
|
||||||
// println!("LOADING: in progress for ALL assets of {:?} (instance of {}): {} ",entity_name, blueprint_info.path, progress * 100.0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn blueprints_assets_ready(
|
||||||
pub(crate) fn blueprints_assets_ready(spawn_placeholders: Query<
|
spawn_placeholders: Query<
|
||||||
(
|
(
|
||||||
Entity,
|
Entity,
|
||||||
&BlueprintInfo,
|
&BlueprintInfo,
|
||||||
Option<&Transform>,
|
Option<&Transform>,
|
||||||
Option<&Parent>,
|
Option<&Parent>,
|
||||||
Option<&AddToGameWorld>,
|
Option<&AddToGameWorld>,
|
||||||
Option<&Name>,
|
Option<&Name>,
|
||||||
Option<&HideUntilReady>
|
Option<&HideUntilReady>,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
With<BlueprintAssetsLoaded>,
|
With<BlueprintAssetsLoaded>,
|
||||||
Added<BlueprintAssetsLoaded>,
|
Added<BlueprintAssetsLoaded>,
|
||||||
Without<BlueprintAssetsNotLoaded>,
|
Without<BlueprintAssetsNotLoaded>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
|
all_children: Query<&Children>,
|
||||||
mut commands: Commands,
|
|
||||||
mut game_world: Query<Entity, With<GameWorldTag>>,
|
mut game_world: Query<Entity, With<GameWorldTag>>,
|
||||||
|
|
||||||
assets_gltf: Res<Assets<Gltf>>,
|
assets_gltf: Res<Assets<Gltf>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
children: Query<&Children>,)
|
|
||||||
{
|
mut graphs: ResMut<Assets<AnimationGraph>>,
|
||||||
|
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
for (
|
for (
|
||||||
entity,
|
entity,
|
||||||
blueprint_info,
|
blueprint_info,
|
||||||
@ -329,16 +317,24 @@ pub(crate) fn blueprints_assets_ready(spawn_placeholders: Query<
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut original_children: Vec<Entity> = vec![];
|
let mut original_children: Vec<Entity> = vec![];
|
||||||
if let Ok(c) = children.get(entity) {
|
if let Ok(c) = all_children.get(entity) {
|
||||||
for child in c.iter() {
|
for child in c.iter() {
|
||||||
original_children.push(*child);
|
original_children.push(*child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut named_animations:HashMap<String, Handle<AnimationClip>> = HashMap::new() ;
|
// TODO: not a fan of this
|
||||||
for (key, value) in gltf.named_animations.iter() {
|
// prepare data for animations
|
||||||
named_animations.insert(key.to_string(), value.clone());
|
let mut graph = AnimationGraph::new();
|
||||||
|
let mut named_animations: HashMap<String, Handle<AnimationClip>> = HashMap::new();
|
||||||
|
let mut animation_indices: HashMap<String, AnimationNodeIndex> = HashMap::new();
|
||||||
|
|
||||||
|
for (key, clip) in gltf.named_animations.iter() {
|
||||||
|
named_animations.insert(key.to_string(), clip.clone());
|
||||||
|
let animation_index = graph.add_clip(clip.clone(), 1.0, graph.root);
|
||||||
|
animation_indices.insert(key.to_string(), animation_index);
|
||||||
}
|
}
|
||||||
|
let graph = graphs.add(graph);
|
||||||
|
|
||||||
commands.entity(entity).insert((
|
commands.entity(entity).insert((
|
||||||
SceneBundle {
|
SceneBundle {
|
||||||
@ -348,99 +344,108 @@ pub(crate) fn blueprints_assets_ready(spawn_placeholders: Query<
|
|||||||
},
|
},
|
||||||
OriginalChildren(original_children),
|
OriginalChildren(original_children),
|
||||||
BlueprintAnimations {
|
BlueprintAnimations {
|
||||||
// these are animations specific to the inside of the blueprint
|
// these are animations specific to the blueprint
|
||||||
named_animations: named_animations//gltf.named_animations.clone(),
|
named_animations,
|
||||||
|
named_indices: animation_indices,
|
||||||
|
graph,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
if hide_until_ready.is_some() {
|
if original_parent.is_none() {
|
||||||
commands.entity(entity).insert(Visibility::Hidden); // visibility:
|
// only allow hiding until ready when the entity does not have a parent (?)
|
||||||
|
if hide_until_ready.is_some() {
|
||||||
|
commands.entity(entity).insert(Visibility::Hidden); // visibility:
|
||||||
|
}
|
||||||
|
|
||||||
|
// only allow automatically adding a newly spawned blueprint instance to the "world", if the entity does not have a parent
|
||||||
|
if add_to_world.is_some() {
|
||||||
|
let world = game_world
|
||||||
|
.get_single_mut()
|
||||||
|
.expect("there should be a game world present");
|
||||||
|
commands.entity(world).add_child(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only allow automatically adding a newly spawned blueprint instance to the "world", if the entity does not have a parent
|
|
||||||
if add_to_world.is_some() && original_parent.is_some() {
|
|
||||||
let world = game_world
|
|
||||||
.get_single_mut()
|
|
||||||
.expect("there should be a game world present");
|
|
||||||
commands.entity(world).add_child(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug, Default)]
|
#[derive(Component, Reflect, Debug, Default)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct SubBlueprintsSpawnTracker{
|
pub struct SubBlueprintsSpawnTracker {
|
||||||
pub sub_blueprint_instances: HashMap<Entity, bool>
|
pub sub_blueprint_instances: HashMap<Entity, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug)]
|
#[derive(Component, Reflect, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct SpawnTrackRoot(pub Entity);
|
pub struct SubBlueprintSpawnRoot(pub Entity);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug)]
|
#[derive(Component, Reflect, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintSceneSpawned;
|
pub struct BlueprintSceneSpawned;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug)]
|
#[derive(Component, Reflect, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintChildrenReady;
|
pub struct BlueprintChildrenReady;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug)]
|
|
||||||
#[reflect(Component)]
|
|
||||||
pub struct BlueprintReadyForPostProcess;
|
|
||||||
|
|
||||||
pub(crate) fn blueprints_scenes_spawned(
|
pub(crate) fn blueprints_scenes_spawned(
|
||||||
spawned_blueprint_scene_instances: Query<(Entity, Option<&Name>, Option<&Children>, Option<&SpawnTrackRoot>), (With<BlueprintSpawning>, Added<SceneInstance>)>,
|
spawned_blueprint_scene_instances: Query<
|
||||||
with_blueprint_infos : Query<(Entity, Option<&Name>), With<BlueprintInfo>>,
|
(
|
||||||
|
Entity,
|
||||||
|
Option<&Name>,
|
||||||
|
Option<&Children>,
|
||||||
|
Option<&SubBlueprintSpawnRoot>,
|
||||||
|
),
|
||||||
|
(With<BlueprintSpawning>, Added<SceneInstance>),
|
||||||
|
>,
|
||||||
|
with_blueprint_infos: Query<(Entity, Option<&Name>), With<BlueprintInfo>>,
|
||||||
|
|
||||||
all_children: Query<&Children>,
|
all_children: Query<&Children>,
|
||||||
all_parents: Query<&Parent>,
|
all_parents: Query<&Parent>,
|
||||||
|
|
||||||
mut sub_blueprint_trackers: Query<(Entity, &mut SubBlueprintsSpawnTracker, &BlueprintInfo)>,
|
// mut sub_blueprint_trackers: Query<(Entity, &mut SubBlueprintsSpawnTracker, &BlueprintInfo)>,
|
||||||
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
|
||||||
all_names: Query<&Name>
|
all_names: Query<&Name>,
|
||||||
) {
|
) {
|
||||||
for (entity, name, children, track_root) in spawned_blueprint_scene_instances.iter(){
|
for (entity, name, children, track_root) in spawned_blueprint_scene_instances.iter() {
|
||||||
info!("Done spawning blueprint scene for entity named {:?} (track root: {:?})", name, track_root);
|
info!(
|
||||||
|
"Done spawning blueprint scene for entity named {:?} (track root: {:?})",
|
||||||
|
name, track_root
|
||||||
|
);
|
||||||
let mut sub_blueprint_instances: Vec<Entity> = vec![];
|
let mut sub_blueprint_instances: Vec<Entity> = vec![];
|
||||||
let mut sub_blueprint_instance_names: Vec<Name> = vec![];
|
let mut sub_blueprint_instance_names: Vec<Name> = vec![];
|
||||||
|
|
||||||
let mut tracker_data: HashMap<Entity, bool> = HashMap::new();
|
let mut tracker_data: HashMap<Entity, bool> = HashMap::new();
|
||||||
|
|
||||||
if track_root.is_none() {
|
if track_root.is_none() {
|
||||||
for parent in all_parents.iter_ancestors(entity) {
|
for parent in all_parents.iter_ancestors(entity) {
|
||||||
if with_blueprint_infos.get(parent).is_ok() {
|
if with_blueprint_infos.get(parent).is_ok() {
|
||||||
|
println!(
|
||||||
println!("found a parent with blueprint_info {:?} for {:?}", all_names.get(parent), all_names.get(entity));
|
"found a parent with blueprint_info {:?} for {:?}",
|
||||||
commands.entity(entity).insert(SpawnTrackRoot(parent));// Injecting to know which entity is the root
|
all_names.get(parent),
|
||||||
|
all_names.get(entity)
|
||||||
|
);
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
|
.insert(SubBlueprintSpawnRoot(parent)); // Injecting to know which entity is the root
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if children.is_some() {
|
if children.is_some() {
|
||||||
for child in all_children.iter_descendants(entity) {
|
for child in all_children.iter_descendants(entity) {
|
||||||
if with_blueprint_infos.get(child).is_ok() {
|
if with_blueprint_infos.get(child).is_ok() {
|
||||||
// println!("Parent blueprint instance of {:?} is {:?}", all_names.get(child), all_names.get(entity));
|
// println!("Parent blueprint instance of {:?} is {:?}", all_names.get(child), all_names.get(entity));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for parent in all_parents.iter_ancestors(child) {
|
for parent in all_parents.iter_ancestors(child) {
|
||||||
if with_blueprint_infos.get(parent).is_ok() {
|
if with_blueprint_infos.get(parent).is_ok() {
|
||||||
|
|
||||||
if parent == entity {
|
if parent == entity {
|
||||||
//println!("yohoho");
|
//println!("yohoho");
|
||||||
println!("Parent blueprint instance of {:?} is {:?}", all_names.get(child), all_names.get(parent));
|
println!(
|
||||||
|
"Parent blueprint instance of {:?} is {:?}",
|
||||||
|
all_names.get(child),
|
||||||
|
all_names.get(parent)
|
||||||
|
);
|
||||||
|
|
||||||
commands.entity(child).insert(SpawnTrackRoot(entity));// Injecting to know which entity is the root
|
commands.entity(child).insert(SubBlueprintSpawnRoot(entity)); // Injecting to know which entity is the root
|
||||||
|
|
||||||
tracker_data.insert(child, false);
|
tracker_data.insert(child, false);
|
||||||
|
|
||||||
@ -448,7 +453,6 @@ pub(crate) fn blueprints_scenes_spawned(
|
|||||||
if let Ok(nname) = all_names.get(child) {
|
if let Ok(nname) = all_names.get(child) {
|
||||||
sub_blueprint_instance_names.push(nname.clone());
|
sub_blueprint_instance_names.push(nname.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if track_root.is_some() {
|
/*if track_root.is_some() {
|
||||||
let prev_root = track_root.unwrap().0;
|
let prev_root = track_root.unwrap().0;
|
||||||
// if we already had a track root, and it is different from the current entity , change the previous track root's list of children
|
// if we already had a track root, and it is different from the current entity , change the previous track root's list of children
|
||||||
@ -457,62 +461,65 @@ pub(crate) fn blueprints_scenes_spawned(
|
|||||||
tracker.1.sub_blueprint_instances.remove(&child);
|
tracker.1.sub_blueprint_instances.remove(&child);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
println!("sub blueprint instances {:?}", sub_blueprint_instance_names);
|
println!("sub blueprint instances {:?}", sub_blueprint_instance_names);
|
||||||
|
|
||||||
// TODO: how about when no sub blueprints are present
|
|
||||||
if tracker_data.keys().len() > 0 {
|
if tracker_data.keys().len() > 0 {
|
||||||
commands.entity(entity)
|
commands.entity(entity).insert(SubBlueprintsSpawnTracker {
|
||||||
.insert(SubBlueprintsSpawnTracker{sub_blueprint_instances: tracker_data.clone()});
|
sub_blueprint_instances: tracker_data.clone(),
|
||||||
}else {
|
});
|
||||||
commands.entity(entity).insert(BlueprintChildrenReady);
|
} else {
|
||||||
|
commands.entity(entity).insert(BlueprintChildrenReady);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// could be done differently, by notifying each parent of a spawning blueprint that this child is done spawning ?
|
// could be done differently, by notifying each parent of a spawning blueprint that this child is done spawning ?
|
||||||
// perhaps using component hooks or observers (ie , if a ComponentSpawning + Parent)
|
// perhaps using component hooks or observers (ie , if a ComponentSpawning + Parent)
|
||||||
|
use crate::CopyComponents;
|
||||||
use crate:: CopyComponents;
|
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct BlueprintReadyForPostProcess;
|
||||||
|
|
||||||
/// this system is in charge of doing component transfers & co
|
/// this system is in charge of doing component transfers & co
|
||||||
/// - it removes one level of useless nesting
|
/// - it removes one level of useless nesting
|
||||||
/// - it copies the blueprint's root components to the entity it was spawned on (original entity)
|
/// - it copies the blueprint's root components to the entity it was spawned on (original entity)
|
||||||
/// - it copies the children of the blueprint scene into the original entity
|
/// - it copies the children of the blueprint scene into the original entity
|
||||||
/// - it add `AnimationLink` components so that animations can be controlled from the original entity
|
/// - it adds an `AnimationLink` component containing the entity that has the AnimationPlayer so that animations can be controlled from the original entity
|
||||||
pub(crate) fn blueprints_transfer_components(
|
pub(crate) fn blueprints_cleanup_spawned_scene(
|
||||||
foo: Query<(
|
foo: Query<
|
||||||
Entity,
|
(
|
||||||
&Children,
|
Entity,
|
||||||
&OriginalChildren,
|
&Children,
|
||||||
Option<&Name>,
|
&OriginalChildren,
|
||||||
Option<&SpawnTrackRoot>),
|
Option<&Name>,
|
||||||
Added<BlueprintChildrenReady>
|
Option<&SubBlueprintSpawnRoot>,
|
||||||
|
&BlueprintAnimations,
|
||||||
|
Option<&NoInBlueprint>,
|
||||||
|
),
|
||||||
|
Added<BlueprintChildrenReady>,
|
||||||
>,
|
>,
|
||||||
mut sub_blueprint_trackers: Query<(Entity, &mut SubBlueprintsSpawnTracker, &BlueprintInfo)>,
|
added_animation_players: Query<(Entity, &Parent), Added<AnimationPlayer>>,
|
||||||
|
|
||||||
|
mut sub_blueprint_trackers: Query<&mut SubBlueprintsSpawnTracker, With<BlueprintInfo>>,
|
||||||
all_children: Query<&Children>,
|
all_children: Query<&Children>,
|
||||||
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
|
||||||
all_names: Query<&Name>
|
all_names: Query<&Name>,
|
||||||
) {
|
) {
|
||||||
|
for (original, children, original_children, name, track_root, animations, no_inblueprint) in
|
||||||
for (original, children, original_children, name, track_root) in foo.iter() {
|
foo.iter()
|
||||||
|
{
|
||||||
info!("YOOO ready !! removing empty nodes {:?}", name);
|
info!("YOOO ready !! removing empty nodes {:?}", name);
|
||||||
|
|
||||||
if children.len() == 0 {
|
if children.len() == 0 {
|
||||||
@ -521,8 +528,8 @@ pub(crate) fn blueprints_transfer_components(
|
|||||||
}
|
}
|
||||||
// the root node is the first & normally only child inside a scene, it is the one that has all relevant components
|
// the root node is the first & normally only child inside a scene, it is the one that has all relevant components
|
||||||
let mut blueprint_root_entity = Entity::PLACEHOLDER; //FIXME: and what about childless ones ?? => should not be possible normally
|
let mut blueprint_root_entity = Entity::PLACEHOLDER; //FIXME: and what about childless ones ?? => should not be possible normally
|
||||||
// let diff = HashSet::from_iter(original_children.0).difference(HashSet::from_iter(children));
|
// let diff = HashSet::from_iter(original_children.0).difference(HashSet::from_iter(children));
|
||||||
// we find the first child that was not in the entity before (aka added during the scene spawning)
|
// we find the first child that was not in the entity before (aka added during the scene spawning)
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
if !original_children.0.contains(child) {
|
if !original_children.0.contains(child) {
|
||||||
blueprint_root_entity = *child;
|
blueprint_root_entity = *child;
|
||||||
@ -530,6 +537,14 @@ pub(crate) fn blueprints_transfer_components(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we flag all children of the blueprint instance with 'InBlueprint'
|
||||||
|
// can be usefull to filter out anything that came from blueprints vs normal children
|
||||||
|
if no_inblueprint.is_none() {
|
||||||
|
for child in all_children.iter_descendants(blueprint_root_entity) {
|
||||||
|
commands.entity(child).insert(InBlueprint); // we do this here in order to avoid doing it to normal children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// copy components into from blueprint instance's blueprint_root_entity to original entity
|
// copy components into from blueprint instance's blueprint_root_entity to original entity
|
||||||
commands.add(CopyComponents {
|
commands.add(CopyComponents {
|
||||||
source: blueprint_root_entity,
|
source: blueprint_root_entity,
|
||||||
@ -546,13 +561,30 @@ pub(crate) fn blueprints_transfer_components(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commands.entity(original)
|
if animations.named_animations.keys().len() > 0 {
|
||||||
.insert(BlueprintReadyForPostProcess); // Tag the entity so any systems dealing with post processing can know it is now their "turn"
|
for (added, parent) in added_animation_players.iter() {
|
||||||
// commands.entity(original).remove::<Handle<Scene>>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want
|
if parent.get() == blueprint_root_entity {
|
||||||
//commands.entity(original).remove::<BlueprintAssetsLoadState>(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ?
|
// FIXME: stopgap solution: since we cannot use an AnimationPlayer at the root entity level
|
||||||
//commands.entity(original).remove::<BlueprintAssetsLoaded>();
|
// and we cannot update animation clips so that the EntityPaths point to one level deeper,
|
||||||
commands.entity(blueprint_root_entity).despawn_recursive(); // Remove the root entity that comes from the spawned-in scene
|
// BUT we still want to have some marker/control at the root entity level, we add this
|
||||||
|
commands
|
||||||
|
.entity(original)
|
||||||
|
.insert((BlueprintAnimationPlayerLink(added),));
|
||||||
|
|
||||||
|
// since v0.14 you need both AnimationTransitions and AnimationGraph components/handle on the same entity as the animationPlayer
|
||||||
|
let transitions = AnimationTransitions::new();
|
||||||
|
commands
|
||||||
|
.entity(added)
|
||||||
|
.insert((transitions, animations.graph.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands
|
||||||
|
.entity(original)
|
||||||
|
.insert(BlueprintReadyForPostProcess); // Tag the entity so any systems dealing with post processing can know it is now their "turn"
|
||||||
|
|
||||||
|
commands.entity(blueprint_root_entity).despawn_recursive(); // Remove the root entity that comes from the spawned-in scene
|
||||||
|
|
||||||
// now check if the current entity is a child blueprint instance of another entity
|
// now check if the current entity is a child blueprint instance of another entity
|
||||||
// this should always be done last, as children should be finished before the parent can be processed correctly
|
// this should always be done last, as children should be finished before the parent can be processed correctly
|
||||||
@ -560,8 +592,11 @@ pub(crate) fn blueprints_transfer_components(
|
|||||||
if let Some(track_root) = track_root {
|
if let Some(track_root) = track_root {
|
||||||
let root_name = all_names.get(track_root.0);
|
let root_name = all_names.get(track_root.0);
|
||||||
println!("got some root {:?}", root_name);
|
println!("got some root {:?}", root_name);
|
||||||
if let Ok((s_entity, mut tracker, bp_info)) = sub_blueprint_trackers.get_mut(track_root.0) {
|
if let Ok(mut tracker) = sub_blueprint_trackers.get_mut(track_root.0) {
|
||||||
tracker.sub_blueprint_instances.entry(original).or_insert(true);
|
tracker
|
||||||
|
.sub_blueprint_instances
|
||||||
|
.entry(original)
|
||||||
|
.or_insert(true);
|
||||||
tracker.sub_blueprint_instances.insert(original, true);
|
tracker.sub_blueprint_instances.insert(original, true);
|
||||||
|
|
||||||
// TODO: ugh, my limited rust knowledge, this is bad code
|
// TODO: ugh, my limited rust knowledge, this is bad code
|
||||||
@ -575,103 +610,49 @@ pub(crate) fn blueprints_transfer_components(
|
|||||||
if all_spawned {
|
if all_spawned {
|
||||||
// println!("ALLLLL SPAAAAWNED for {} named {:?}", track_root.0, root_name);
|
// println!("ALLLLL SPAAAAWNED for {} named {:?}", track_root.0, root_name);
|
||||||
commands.entity(track_root.0).insert(BlueprintChildrenReady);
|
commands.entity(track_root.0).insert(BlueprintChildrenReady);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug)]
|
#[derive(Component, Reflect, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintReadyForFinalizing;
|
pub struct BlueprintReadyForFinalizing;
|
||||||
|
|
||||||
pub(crate) fn blueprints_finalize_instances(
|
pub(crate) fn blueprints_finalize_instances(
|
||||||
blueprint_instances: Query<(Entity, Option<&Name>, &BlueprintInfo, Option<&HideUntilReady>), (With<BlueprintSpawning>, With<BlueprintReadyForFinalizing>)>,
|
blueprint_instances: Query<
|
||||||
|
(
|
||||||
|
Entity,
|
||||||
|
Option<&Name>,
|
||||||
|
&BlueprintInfo,
|
||||||
|
Option<&HideUntilReady>,
|
||||||
|
),
|
||||||
|
(With<BlueprintSpawning>, With<BlueprintReadyForFinalizing>),
|
||||||
|
>,
|
||||||
mut blueprint_events: EventWriter<BlueprintEvent>,
|
mut blueprint_events: EventWriter<BlueprintEvent>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
for (entity, name, blueprint_info, hide_until_ready) in blueprint_instances.iter() {
|
for (entity, name, blueprint_info, hide_until_ready) in blueprint_instances.iter() {
|
||||||
info!("Finalizing blueprint instance {:?}", name);
|
info!("Finalizing blueprint instance {:?}", name);
|
||||||
commands.entity(entity)
|
commands
|
||||||
.remove::<SpawnHere>()
|
.entity(entity)
|
||||||
|
.remove::<SpawnBlueprint>()
|
||||||
.remove::<BlueprintSpawning>()
|
.remove::<BlueprintSpawning>()
|
||||||
.remove::<BlueprintReadyForPostProcess>()
|
.remove::<BlueprintReadyForPostProcess>()
|
||||||
.insert(BlueprintInstanceReady)
|
//.remove::<Handle<Scene>>(); // FIXME: if we delete the handle to the scene, things get despawned ! not what we want
|
||||||
;
|
//.remove::<BlueprintAssetsLoadState>(); // also clear the sub assets tracker to free up handles, perhaps just freeing up the handles and leave the rest would be better ?
|
||||||
|
//.remove::<BlueprintAssetsLoaded>();
|
||||||
|
.insert(BlueprintInstanceReady);
|
||||||
|
|
||||||
if hide_until_ready.is_some() {
|
if hide_until_ready.is_some() {
|
||||||
println!("REVEAAAL");
|
|
||||||
commands.entity(entity).insert(Visibility::Visible);
|
commands.entity(entity).insert(Visibility::Visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blueprint_events.send(BlueprintEvent::InstanceReady {
|
||||||
blueprint_events.send(BlueprintEvent::InstanceReady {entity: entity, blueprint_name: blueprint_info.name.clone(), blueprint_path: blueprint_info.path.clone()});
|
entity,
|
||||||
|
blueprint_name: blueprint_info.name.clone(),
|
||||||
|
blueprint_path: blueprint_info.path.clone(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
=> annoying issue with the "nested" useless root node created by blender
|
|
||||||
=> distinguish between blueprint instances inside blueprint instances vs blueprint instances inside blueprints ??
|
|
||||||
|
|
||||||
BlueprintSpawning
|
|
||||||
- Blueprint Load Assets
|
|
||||||
- Blueprint Assets Ready: spawn Blueprint's scene
|
|
||||||
- Blueprint Scene Ready (SceneInstance component is present):
|
|
||||||
- get list of sub Blueprints if any, inject sub blueprints spawn tracker
|
|
||||||
- Blueprint copy components to original entity, remove useless nodes
|
|
||||||
- Blueprint post process
|
|
||||||
- generate aabb (need full hierarchy in its final form)
|
|
||||||
- inject materials from library if needed
|
|
||||||
- Blueprint Ready
|
|
||||||
- bubble information up to parent blueprint instance
|
|
||||||
- if all sub_blueprints are ready => Parent blueprint Instance is ready
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// HOT RELOAD
|
|
||||||
|
|
||||||
|
|
||||||
use bevy::asset::AssetEvent;
|
|
||||||
|
|
||||||
pub(crate) fn react_to_asset_changes(
|
|
||||||
mut gltf_events: EventReader<AssetEvent<Gltf>>,
|
|
||||||
mut untyped_events: EventReader<AssetEvent<LoadedUntypedAsset>>,
|
|
||||||
mut blueprint_assets: Query<(Entity, Option<&Name>, &BlueprintInfo, &mut BlueprintAssetsLoadState, Option<&Children>)>,
|
|
||||||
asset_server: Res<AssetServer>,
|
|
||||||
mut commands: Commands,
|
|
||||||
|
|
||||||
) {
|
|
||||||
|
|
||||||
for event in gltf_events.read() {
|
|
||||||
// LoadedUntypedAsset
|
|
||||||
match event {
|
|
||||||
AssetEvent::Modified { id } => {
|
|
||||||
// React to the image being modified
|
|
||||||
// println!("Modified gltf {:?}", asset_server.get_path(*id));
|
|
||||||
for (entity, entity_name, blueprint_info, mut assets_to_load, children) in blueprint_assets.iter_mut() {
|
|
||||||
for tracker in assets_to_load.asset_infos.iter_mut() {
|
|
||||||
if asset_server.get_path(*id).is_some() {
|
|
||||||
if tracker.path == asset_server.get_path(*id).unwrap().to_string() {
|
|
||||||
println!("HOLY MOLY IT DETECTS !!, now respawn {:?}", entity_name);
|
|
||||||
if children.is_some() {
|
|
||||||
for child in children.unwrap().iter(){
|
|
||||||
commands.entity(*child).despawn_recursive();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
commands.entity(entity)
|
|
||||||
.remove::<BlueprintAssetsLoaded>()
|
|
||||||
.remove::<SceneInstance>()
|
|
||||||
.remove::<BlueprintAssetsLoadState>()
|
|
||||||
.insert(SpawnHere);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,10 +11,15 @@ pub(crate) fn plugin(app: &mut App) {
|
|||||||
.register_type::<BlenderLightShadows>()
|
.register_type::<BlenderLightShadows>()
|
||||||
.register_type::<BlenderToneMapping>()
|
.register_type::<BlenderToneMapping>()
|
||||||
.register_type::<BlenderColorGrading>()
|
.register_type::<BlenderColorGrading>()
|
||||||
|
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(process_lights, process_shadowmap, process_background_shader, process_tonemapping, process_colorgrading)
|
(
|
||||||
|
process_lights,
|
||||||
|
process_shadowmap,
|
||||||
|
process_background_shader,
|
||||||
|
process_tonemapping,
|
||||||
|
process_colorgrading,
|
||||||
|
)
|
||||||
.after(GltfComponentsSet::Injection),
|
.after(GltfComponentsSet::Injection),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -45,26 +50,25 @@ pub struct BlenderShadowSettings {
|
|||||||
pub cascade_size: usize,
|
pub cascade_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Not all possible Blender ToneMappings are available in Bevy & vice versa
|
/// Not all possible Blender `ToneMappings` are available in Bevy & vice versa
|
||||||
#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)]
|
#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum BlenderToneMapping {
|
pub enum BlenderToneMapping {
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
AgX,
|
AgX,
|
||||||
Filmic
|
Filmic,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)]
|
#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct BlenderColorGrading {
|
pub struct BlenderColorGrading {
|
||||||
exposure: f32,
|
exposure: f32,
|
||||||
gamma: f32,
|
gamma: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn process_lights(
|
fn process_lights(
|
||||||
mut directional_lights: Query<
|
mut directional_lights: Query<
|
||||||
(&mut DirectionalLight, Option<&BlenderLightShadows>),
|
(&mut DirectionalLight, Option<&BlenderLightShadows>),
|
||||||
@ -76,12 +80,12 @@ fn process_lights(
|
|||||||
for (mut light, blender_light_shadows) in directional_lights.iter_mut() {
|
for (mut light, blender_light_shadows) in directional_lights.iter_mut() {
|
||||||
if let Some(blender_light_shadows) = blender_light_shadows {
|
if let Some(blender_light_shadows) = blender_light_shadows {
|
||||||
light.shadows_enabled = blender_light_shadows.enabled;
|
light.shadows_enabled = blender_light_shadows.enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (mut light, blender_light_shadows) in spot_lights.iter_mut() {
|
for (mut light, blender_light_shadows) in spot_lights.iter_mut() {
|
||||||
if let Some(blender_light_shadows) = blender_light_shadows {
|
if let Some(blender_light_shadows) = blender_light_shadows {
|
||||||
light.shadows_enabled = blender_light_shadows.enabled;
|
light.shadows_enabled = blender_light_shadows.enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (mut light, blender_light_shadows) in point_lights.iter_mut() {
|
for (mut light, blender_light_shadows) in point_lights.iter_mut() {
|
||||||
@ -113,19 +117,17 @@ fn process_background_shader(
|
|||||||
brightness: background_shader.strength * 400.0,
|
brightness: background_shader.strength * 400.0,
|
||||||
});
|
});
|
||||||
commands.insert_resource(ClearColor(background_shader.color));
|
commands.insert_resource(ClearColor(background_shader.color));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this logic should not depend on if toneMapping or Cameras where added first
|
// FIXME: this logic should not depend on if toneMapping or Cameras where added first
|
||||||
fn process_tonemapping(
|
fn process_tonemapping(
|
||||||
tonemappings: Query<(Entity, &BlenderToneMapping) , Added<BlenderToneMapping>>,
|
tonemappings: Query<(Entity, &BlenderToneMapping), Added<BlenderToneMapping>>,
|
||||||
cameras: Query<Entity, With<Camera>>,
|
cameras: Query<Entity, With<Camera>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
){
|
) {
|
||||||
|
for entity in cameras.iter() {
|
||||||
for entity in cameras.iter(){
|
for (scene_id, tone_mapping) in tonemappings.iter() {
|
||||||
for (scene_id, tone_mapping) in tonemappings.iter(){
|
|
||||||
match tone_mapping {
|
match tone_mapping {
|
||||||
BlenderToneMapping::None => {
|
BlenderToneMapping::None => {
|
||||||
//println!("TONEMAPPING NONE");
|
//println!("TONEMAPPING NONE");
|
||||||
@ -143,42 +145,37 @@ fn process_tonemapping(
|
|||||||
commands.entity(scene_id).remove::<BlenderToneMapping>();
|
commands.entity(scene_id).remove::<BlenderToneMapping>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this logic should not depend on if toneMapping or Cameras where added first
|
// FIXME: this logic should not depend on if toneMapping or Cameras where added first
|
||||||
fn process_colorgrading(
|
fn process_colorgrading(
|
||||||
blender_colorgradings: Query<(Entity, &BlenderColorGrading) , Added<BlenderColorGrading>>,
|
blender_colorgradings: Query<(Entity, &BlenderColorGrading), Added<BlenderColorGrading>>,
|
||||||
cameras: Query<Entity, With<Camera>>,
|
cameras: Query<Entity, With<Camera>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
){
|
) {
|
||||||
|
for entity in cameras.iter() {
|
||||||
for entity in cameras.iter(){
|
for (scene_id, blender_colorgrading) in blender_colorgradings.iter() {
|
||||||
for (scene_id, blender_colorgrading) in blender_colorgradings.iter(){
|
commands.entity(entity).insert(ColorGrading {
|
||||||
commands.entity(entity).insert(
|
global: ColorGradingGlobal {
|
||||||
ColorGrading{
|
exposure: blender_colorgrading.exposure,
|
||||||
global: ColorGradingGlobal{
|
|
||||||
exposure: blender_colorgrading.exposure,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
shadows: ColorGradingSection{
|
|
||||||
gamma: blender_colorgrading.gamma,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
midtones: ColorGradingSection{
|
|
||||||
gamma: blender_colorgrading.gamma,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
highlights: ColorGradingSection{
|
|
||||||
gamma: blender_colorgrading.gamma,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
);
|
shadows: ColorGradingSection {
|
||||||
commands.entity(scene_id).remove::<ColorGrading>();
|
gamma: blender_colorgrading.gamma,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
midtones: ColorGradingSection {
|
||||||
|
gamma: blender_colorgrading.gamma,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
highlights: ColorGradingSection {
|
||||||
|
gamma: blender_colorgrading.gamma,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
commands.entity(scene_id).remove::<ColorGrading>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ pub use process_gltfs::*;
|
|||||||
pub mod blender_settings;
|
pub mod blender_settings;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
ecs::{component::Component, reflect::ReflectComponent, system::Resource},
|
ecs::{component::Component, reflect::ReflectComponent},
|
||||||
prelude::{App, IntoSystemConfigs, Plugin, SystemSet, Update},
|
prelude::{App, IntoSystemConfigs, Plugin, SystemSet, Update},
|
||||||
reflect::Reflect,
|
reflect::Reflect,
|
||||||
};
|
};
|
||||||
|
@ -16,36 +16,40 @@ use bevy::{
|
|||||||
use crate::{ronstring_to_reflect_component, GltfProcessed};
|
use crate::{ronstring_to_reflect_component, GltfProcessed};
|
||||||
|
|
||||||
// , mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>
|
// , mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>
|
||||||
fn find_entity_components(entity: Entity, name: &Name, parent: Option<&Parent>, reflect_components: Vec<(Box<dyn Reflect>, TypeRegistration)>, entity_components: &HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>) -> (Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>){
|
fn find_entity_components(
|
||||||
// we assign the components specified /xxx_components objects to their parent node
|
entity: Entity,
|
||||||
let mut target_entity = entity;
|
name: &Name,
|
||||||
// if the node contains "components" or ends with "_pa" (ie add to parent), the components will not be added to the entity itself but to its parent
|
parent: Option<&Parent>,
|
||||||
// this is mostly used for Blender collections
|
reflect_components: Vec<(Box<dyn Reflect>, TypeRegistration)>,
|
||||||
if parent.is_some() && (name.as_str().contains("components") || name.as_str().ends_with("_pa")) {
|
entity_components: &HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>,
|
||||||
debug!("adding components to parent");
|
) -> (Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>) {
|
||||||
target_entity = parent.expect("the target entity had a parent ").get();
|
// we assign the components specified /xxx_components objects to their parent node
|
||||||
}
|
let mut target_entity = entity;
|
||||||
debug!("adding to {:?}", target_entity);
|
// if the node contains "components" or ends with "_pa" (ie add to parent), the components will not be added to the entity itself but to its parent
|
||||||
|
// this is mostly used for Blender collections
|
||||||
|
if parent.is_some() && (name.as_str().contains("components") || name.as_str().ends_with("_pa"))
|
||||||
|
{
|
||||||
|
debug!("adding components to parent");
|
||||||
|
target_entity = parent.expect("the target entity had a parent ").get();
|
||||||
|
}
|
||||||
|
debug!("adding to {:?}", target_entity);
|
||||||
|
|
||||||
// if there where already components set to be added to this entity (for example when entity_data was refering to a parent), update the vec of entity_components accordingly
|
// if there where already components set to be added to this entity (for example when entity_data was refering to a parent), update the vec of entity_components accordingly
|
||||||
// this allows for example blender collection to provide basic ecs data & the instances to override/ define their own values
|
// this allows for example blender collection to provide basic ecs data & the instances to override/ define their own values
|
||||||
if entity_components.contains_key(&target_entity) {
|
if entity_components.contains_key(&target_entity) {
|
||||||
let mut updated_components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new();
|
let mut updated_components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new();
|
||||||
let current_components = &entity_components[&target_entity];
|
let current_components = &entity_components[&target_entity];
|
||||||
// first inject the current components
|
// first inject the current components
|
||||||
for (component, type_registration) in current_components {
|
for (component, type_registration) in current_components {
|
||||||
updated_components.push((component.clone_value(), type_registration.clone()));
|
updated_components.push((component.clone_value(), type_registration.clone()));
|
||||||
}
|
}
|
||||||
// then inject the new components: this also enables overwrite components set in the collection
|
// then inject the new components: this also enables overwrite components set in the collection
|
||||||
for (component, type_registration) in reflect_components {
|
for (component, type_registration) in reflect_components {
|
||||||
updated_components.push((component.clone_value(), type_registration));
|
updated_components.push((component.clone_value(), type_registration));
|
||||||
}
|
}
|
||||||
return (target_entity, updated_components)
|
return (target_entity, updated_components);
|
||||||
//entity_components.insert(target_entity, updated_components);
|
}
|
||||||
} else {
|
(target_entity, reflect_components)
|
||||||
return (target_entity, reflect_components);
|
|
||||||
// entity_components.insert(target_entity, reflect_components);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// main function: injects components into each entity in gltf files that have `gltf_extras`, using reflection
|
/// main function: injects components into each entity in gltf files that have `gltf_extras`, using reflection
|
||||||
@ -70,11 +74,11 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
let type_registry = type_registry.read();
|
let type_registry = type_registry.read();
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
let (target_entity, updated_components) =
|
||||||
|
find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
||||||
entity_components.insert(target_entity, updated_components);
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (entity, name, extra, parent) in scene_extras.iter(world) {
|
for (entity, name, extra, parent) in scene_extras.iter(world) {
|
||||||
debug!(
|
debug!(
|
||||||
"Name: {}, entity {:?}, parent: {:?}, scene_extras {:?}",
|
"Name: {}, entity {:?}, parent: {:?}, scene_extras {:?}",
|
||||||
@ -85,7 +89,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
let type_registry = type_registry.read();
|
let type_registry = type_registry.read();
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
let (target_entity, updated_components) =
|
||||||
|
find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
||||||
entity_components.insert(target_entity, updated_components);
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +104,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
let type_registry = type_registry.read();
|
let type_registry = type_registry.read();
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
let (target_entity, updated_components) =
|
||||||
|
find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
||||||
entity_components.insert(target_entity, updated_components);
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,11 +119,11 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
let type_registry = type_registry.read();
|
let type_registry = type_registry.read();
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
let (target_entity, updated_components) = find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
let (target_entity, updated_components) =
|
||||||
|
find_entity_components(entity, name, parent, reflect_components, &entity_components);
|
||||||
entity_components.insert(target_entity, updated_components);
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (entity, components) in entity_components {
|
for (entity, components) in entity_components {
|
||||||
let type_registry: &AppTypeRegistry = world.resource();
|
let type_registry: &AppTypeRegistry = world.resource();
|
||||||
let type_registry = type_registry.clone();
|
let type_registry = type_registry.clone();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use bevy::log::{debug, warn};
|
use bevy::log::{debug, warn};
|
||||||
use bevy::reflect::serde::{ReflectDeserializer, ReflectSerializer};
|
use bevy::reflect::serde::ReflectDeserializer;
|
||||||
use bevy::reflect::{Reflect, TypeRegistration, TypeRegistry};
|
use bevy::reflect::{Reflect, TypeRegistration, TypeRegistry};
|
||||||
use bevy::utils::HashMap;
|
use bevy::utils::HashMap;
|
||||||
use ron::Value;
|
use ron::Value;
|
||||||
@ -16,9 +16,7 @@ pub fn ronstring_to_reflect_component(
|
|||||||
// println!("ron_string {:?}", ron_string);
|
// println!("ron_string {:?}", ron_string);
|
||||||
for (name, value) in lookup.into_iter() {
|
for (name, value) in lookup.into_iter() {
|
||||||
let parsed_value: String = match value.clone() {
|
let parsed_value: String = match value.clone() {
|
||||||
Value::String(str) => {
|
Value::String(str) => str,
|
||||||
str
|
|
||||||
}
|
|
||||||
_ => ron::to_string(&value).unwrap().to_string(),
|
_ => ron::to_string(&value).unwrap().to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,7 +56,7 @@ fn components_string_to_components(
|
|||||||
parsed_value
|
parsed_value
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// usefull to determine what an entity looks like Serialized
|
// usefull to determine what an entity looks like Serialized
|
||||||
let test_struct = Color::Srgba(Srgba { red: 0.2, green: 0.2, blue: 0.2, alpha: 0.2 });
|
let test_struct = Color::Srgba(Srgba { red: 0.2, green: 0.2, blue: 0.2, alpha: 0.2 });
|
||||||
//CameraRenderGraph::new("name");
|
//CameraRenderGraph::new("name");
|
||||||
@ -68,7 +66,6 @@ fn components_string_to_components(
|
|||||||
println!("serialized Component {}", serialized);
|
println!("serialized Component {}", serialized);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
debug!("component data ron string {}", ron_string);
|
debug!("component data ron string {}", ron_string);
|
||||||
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str())
|
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str())
|
||||||
.expect("deserialzer should have been generated from string");
|
.expect("deserialzer should have been generated from string");
|
||||||
@ -99,9 +96,7 @@ fn bevy_components_string_to_components(
|
|||||||
let lookup: HashMap<String, Value> = ron::from_str(&parsed_value).unwrap();
|
let lookup: HashMap<String, Value> = ron::from_str(&parsed_value).unwrap();
|
||||||
for (key, value) in lookup.into_iter() {
|
for (key, value) in lookup.into_iter() {
|
||||||
let parsed_value: String = match value.clone() {
|
let parsed_value: String = match value.clone() {
|
||||||
Value::String(str) => {
|
Value::String(str) => str,
|
||||||
str
|
|
||||||
}
|
|
||||||
_ => ron::to_string(&value).unwrap().to_string(),
|
_ => ron::to_string(&value).unwrap().to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::path::PathBuf;
|
|
||||||
use bevy::{prelude::*, render::primitives::Aabb, utils::HashMap};
|
use bevy::{prelude::*, render::primitives::Aabb, utils::HashMap};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub mod components;
|
pub mod components;
|
||||||
pub use components::*;
|
pub use components::*;
|
||||||
@ -24,7 +24,6 @@ pub struct BlenvyConfig {
|
|||||||
pub(crate) materials_cache: HashMap<String, Handle<StandardMaterial>>, // cache for materials
|
pub(crate) materials_cache: HashMap<String, Handle<StandardMaterial>>, // cache for materials
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
/// Plugin for gltf blueprints
|
/// Plugin for gltf blueprints
|
||||||
pub struct BlenvyPlugin {
|
pub struct BlenvyPlugin {
|
||||||
@ -51,9 +50,9 @@ impl Default for BlenvyPlugin {
|
|||||||
impl Plugin for BlenvyPlugin {
|
impl Plugin for BlenvyPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
ComponentsFromGltfPlugin::default(),
|
ComponentsFromGltfPlugin::default(),
|
||||||
ExportRegistryPlugin::default(),
|
ExportRegistryPlugin::default(),
|
||||||
BlueprintsPlugin::default()
|
BlueprintsPlugin::default(),
|
||||||
))
|
))
|
||||||
.insert_resource(BlenvyConfig {
|
.insert_resource(BlenvyConfig {
|
||||||
registry_save_path: self.registry_save_path.clone(),
|
registry_save_path: self.registry_save_path.clone(),
|
||||||
@ -64,8 +63,6 @@ impl Plugin for BlenvyPlugin {
|
|||||||
aabb_cache: HashMap::new(),
|
aabb_cache: HashMap::new(),
|
||||||
|
|
||||||
materials_cache: HashMap::new(),
|
materials_cache: HashMap::new(),
|
||||||
})
|
});
|
||||||
;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
use std::{fs::File, path::Path};
|
|
||||||
use bevy::{log::info, prelude::{AppTypeRegistry, ReflectComponent, ReflectResource, World}, reflect::{TypeInfo, TypeRegistration, VariantInfo}};
|
|
||||||
use serde_json::{json, Map, Value};
|
|
||||||
use crate::{AssetRoot, BlenvyConfig};
|
use crate::{AssetRoot, BlenvyConfig};
|
||||||
|
use bevy::{
|
||||||
|
log::info,
|
||||||
|
prelude::{AppTypeRegistry, ReflectComponent, ReflectResource, World},
|
||||||
|
reflect::{TypeInfo, TypeRegistration, VariantInfo},
|
||||||
|
};
|
||||||
|
use serde_json::{json, Map, Value};
|
||||||
|
use std::{fs::File, path::Path};
|
||||||
|
|
||||||
pub fn export_types(world: &mut World) {
|
pub fn export_types(world: &mut World) {
|
||||||
let config = world
|
let config = world
|
||||||
@ -37,7 +41,7 @@ pub fn export_types(world: &mut World) {
|
|||||||
)
|
)
|
||||||
.expect("valid json");
|
.expect("valid json");
|
||||||
|
|
||||||
info!("Done exporting registry schema")
|
info!("Done exporting registry schema");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export_type(reg: &TypeRegistration) -> (String, Value) {
|
pub fn export_type(reg: &TypeRegistration) -> (String, Value) {
|
||||||
|
@ -4,7 +4,10 @@ pub mod export_types;
|
|||||||
pub use export_types::*;
|
pub use export_types::*;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
app::Startup, asset::AssetPlugin, prelude::{App, Plugin, Resource}, scene::SceneFilter
|
app::Startup,
|
||||||
|
asset::AssetPlugin,
|
||||||
|
prelude::{App, Plugin, Resource},
|
||||||
|
scene::SceneFilter,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ExportRegistryPlugin {
|
pub struct ExportRegistryPlugin {
|
||||||
@ -25,8 +28,7 @@ impl Default for ExportRegistryPlugin {
|
|||||||
|
|
||||||
impl Plugin for ExportRegistryPlugin {
|
impl Plugin for ExportRegistryPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.register_asset_root()
|
app.register_asset_root().add_systems(Startup, export_types);
|
||||||
.add_systems(Startup, export_types);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
@ -250,16 +250,16 @@
|
|||||||
"type": "array",
|
"type": "array",
|
||||||
"typeInfo": "List"
|
"typeInfo": "List"
|
||||||
},
|
},
|
||||||
"alloc::vec::Vec<blenvy::blueprints::assets::MyAsset>": {
|
"alloc::vec::Vec<blenvy::blueprints::assets::BlueprintAsset>": {
|
||||||
"isComponent": false,
|
"isComponent": false,
|
||||||
"isResource": false,
|
"isResource": false,
|
||||||
"items": {
|
"items": {
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/$defs/blenvy::blueprints::assets::MyAsset"
|
"$ref": "#/$defs/blenvy::blueprints::assets::BlueprintAsset"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"long_name": "alloc::vec::Vec<blenvy::blueprints::assets::MyAsset>",
|
"long_name": "alloc::vec::Vec<blenvy::blueprints::assets::BlueprintAsset>",
|
||||||
"short_name": "Vec<MyAsset>",
|
"short_name": "Vec<BlueprintAsset>",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"typeInfo": "List"
|
"typeInfo": "List"
|
||||||
},
|
},
|
||||||
@ -12003,6 +12003,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"bevy_utils::hashbrown::HashMap<alloc::string::String, petgraph::graph::NodeIndex, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
|
||||||
|
"isComponent": false,
|
||||||
|
"isResource": false,
|
||||||
|
"keyType": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/$defs/alloc::string::String"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, petgraph::graph::NodeIndex, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
|
||||||
|
"short_name": "HashMap<String, NodeIndex, DefaultHashBuilder>",
|
||||||
|
"type": "object",
|
||||||
|
"typeInfo": "Map",
|
||||||
|
"valueType": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/$defs/petgraph::graph::NodeIndex"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"bevy_utils::hashbrown::HashMap<bevy_animation::AnimationTargetId, alloc::vec::Vec<bevy_animation::VariableCurve>, bevy_utils::NoOpHash>": {
|
"bevy_utils::hashbrown::HashMap<bevy_animation::AnimationTargetId, alloc::vec::Vec<bevy_animation::VariableCurve>, bevy_utils::NoOpHash>": {
|
||||||
"isComponent": false,
|
"isComponent": false,
|
||||||
"isResource": false,
|
"isResource": false,
|
||||||
@ -13286,14 +13304,26 @@
|
|||||||
"isResource": false,
|
"isResource": false,
|
||||||
"long_name": "blenvy::blueprints::animation::BlueprintAnimations",
|
"long_name": "blenvy::blueprints::animation::BlueprintAnimations",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"graph": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/$defs/bevy_asset::handle::Handle<bevy_animation::graph::AnimationGraph>"
|
||||||
|
}
|
||||||
|
},
|
||||||
"named_animations": {
|
"named_animations": {
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/$defs/bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_asset::handle::Handle<bevy_animation::AnimationClip>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>"
|
"$ref": "#/$defs/bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_asset::handle::Handle<bevy_animation::AnimationClip>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"named_indices": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/$defs/bevy_utils::hashbrown::HashMap<alloc::string::String, petgraph::graph::NodeIndex, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"named_animations"
|
"named_animations",
|
||||||
|
"named_indices",
|
||||||
|
"graph"
|
||||||
],
|
],
|
||||||
"short_name": "BlueprintAnimations",
|
"short_name": "BlueprintAnimations",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -13309,15 +13339,46 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/$defs/bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_asset::handle::Handle<bevy_animation::AnimationClip>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>"
|
"$ref": "#/$defs/bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_asset::handle::Handle<bevy_animation::AnimationClip>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"named_indices": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/$defs/bevy_utils::hashbrown::HashMap<alloc::string::String, petgraph::graph::NodeIndex, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"named_animations"
|
"named_animations",
|
||||||
|
"named_indices"
|
||||||
],
|
],
|
||||||
"short_name": "SceneAnimations",
|
"short_name": "SceneAnimations",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"typeInfo": "Struct"
|
"typeInfo": "Struct"
|
||||||
},
|
},
|
||||||
|
"blenvy::blueprints::assets::BlueprintAsset": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"isComponent": true,
|
||||||
|
"isResource": false,
|
||||||
|
"long_name": "blenvy::blueprints::assets::BlueprintAsset",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/$defs/alloc::string::String"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/$defs/alloc::string::String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"short_name": "BlueprintAsset",
|
||||||
|
"type": "object",
|
||||||
|
"typeInfo": "Struct"
|
||||||
|
},
|
||||||
"blenvy::blueprints::assets::BlueprintAssets": {
|
"blenvy::blueprints::assets::BlueprintAssets": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"isComponent": true,
|
"isComponent": true,
|
||||||
@ -13326,7 +13387,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"assets": {
|
"assets": {
|
||||||
"type": {
|
"type": {
|
||||||
"$ref": "#/$defs/alloc::vec::Vec<blenvy::blueprints::assets::MyAsset>"
|
"$ref": "#/$defs/alloc::vec::Vec<blenvy::blueprints::assets::BlueprintAsset>"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loaded": {
|
"loaded": {
|
||||||
@ -13349,31 +13410,6 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"typeInfo": "Struct"
|
"typeInfo": "Struct"
|
||||||
},
|
},
|
||||||
"blenvy::blueprints::assets::MyAsset": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"isComponent": true,
|
|
||||||
"isResource": false,
|
|
||||||
"long_name": "blenvy::blueprints::assets::MyAsset",
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"type": {
|
|
||||||
"$ref": "#/$defs/alloc::string::String"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"path": {
|
|
||||||
"type": {
|
|
||||||
"$ref": "#/$defs/alloc::string::String"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"name",
|
|
||||||
"path"
|
|
||||||
],
|
|
||||||
"short_name": "MyAsset",
|
|
||||||
"type": "object",
|
|
||||||
"typeInfo": "Struct"
|
|
||||||
},
|
|
||||||
"blenvy::blueprints::materials::MaterialInfo": {
|
"blenvy::blueprints::materials::MaterialInfo": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"isComponent": true,
|
"isComponent": true,
|
||||||
@ -13424,14 +13460,25 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"typeInfo": "Struct"
|
"typeInfo": "Struct"
|
||||||
},
|
},
|
||||||
"blenvy::blueprints::spawn_from_blueprints::SpawnHere": {
|
"blenvy::blueprints::spawn_from_blueprints::HideUntilReady": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"isComponent": true,
|
"isComponent": true,
|
||||||
"isResource": false,
|
"isResource": false,
|
||||||
"long_name": "blenvy::blueprints::spawn_from_blueprints::SpawnHere",
|
"long_name": "blenvy::blueprints::spawn_from_blueprints::HideUntilReady",
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"required": [],
|
"required": [],
|
||||||
"short_name": "SpawnHere",
|
"short_name": "HideUntilReady",
|
||||||
|
"type": "object",
|
||||||
|
"typeInfo": "Struct"
|
||||||
|
},
|
||||||
|
"blenvy::blueprints::spawn_from_blueprints::SpawnBlueprint": {
|
||||||
|
"additionalProperties": false,
|
||||||
|
"isComponent": true,
|
||||||
|
"isResource": false,
|
||||||
|
"long_name": "blenvy::blueprints::spawn_from_blueprints::SpawnBlueprint",
|
||||||
|
"properties": {},
|
||||||
|
"required": [],
|
||||||
|
"short_name": "SpawnBlueprint",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"typeInfo": "Struct"
|
"typeInfo": "Struct"
|
||||||
},
|
},
|
||||||
|
@ -21,22 +21,20 @@ impl Plugin for CorePlugin {
|
|||||||
// and any other commponent you want to include/exclude
|
// and any other commponent you want to include/exclude
|
||||||
])),
|
])),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}, /* ExportRegistryPlugin {
|
||||||
|
component_filter: SceneFilter::Denylist(HashSet::from([
|
||||||
/* ExportRegistryPlugin {
|
// this is using Bevy's build in SceneFilter, you can compose what components you want to allow/deny
|
||||||
component_filter: SceneFilter::Denylist(HashSet::from([
|
TypeId::of::<ComponentAToFilterOut>(),
|
||||||
// this is using Bevy's build in SceneFilter, you can compose what components you want to allow/deny
|
TypeId::of::<ComponentBToFilterOut>(),
|
||||||
TypeId::of::<ComponentAToFilterOut>(),
|
// and any other commponent you want to include/exclude
|
||||||
TypeId::of::<ComponentBToFilterOut>(),
|
])),
|
||||||
// and any other commponent you want to include/exclude
|
..Default::default()
|
||||||
])),
|
},
|
||||||
..Default::default()
|
BlueprintsPlugin {
|
||||||
},
|
material_library: true,
|
||||||
BlueprintsPlugin {
|
aabbs: true,
|
||||||
material_library: true,
|
..Default::default()
|
||||||
aabbs: true,
|
}, */
|
||||||
..Default::default()
|
|
||||||
}, */
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use std::time::Duration;
|
|||||||
SceneAnimationPlayerLink, SceneAnimations,
|
SceneAnimationPlayerLink, SceneAnimations,
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
use bevy::{gltf::Gltf, prelude::*};
|
use bevy::{animation::RepeatAnimation, gltf::Gltf, prelude::*};
|
||||||
|
|
||||||
use blenvy::{
|
use blenvy::{
|
||||||
AnimationInfos, AnimationMarkerReached, BlueprintAnimationPlayerLink, BlueprintAnimations,
|
AnimationInfos, AnimationMarkerReached, BlueprintAnimationPlayerLink, BlueprintAnimations,
|
||||||
@ -39,7 +39,7 @@ pub fn setup_main_scene_animations(asset_server: Res<AssetServer>, mut commands:
|
|||||||
commands.insert_resource(AnimTest(asset_server.load("levels/World.glb")));
|
commands.insert_resource(AnimTest(asset_server.load("levels/World.glb")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn animations(
|
pub fn animations(
|
||||||
added_animation_players: Query<(Entity, &Name, &AnimationPlayer)>,
|
added_animation_players: Query<(Entity, &Name, &AnimationPlayer)>,
|
||||||
@ -79,11 +79,13 @@ pub fn animations(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn play_animations(
|
pub fn play_animations(
|
||||||
animated_marker1: Query<
|
animated_fox: Query<(&BlueprintAnimationPlayerLink, &BlueprintAnimations), With<MarkerFox>>,
|
||||||
|
|
||||||
|
/*animated_marker1: Query<
|
||||||
(&SceneAnimationPlayerLink, &SceneAnimations),
|
(&SceneAnimationPlayerLink, &SceneAnimations),
|
||||||
(With<AnimationInfos>, With<Marker1>),
|
(With<AnimationInfos>, With<Marker1>),
|
||||||
>,
|
>,
|
||||||
@ -99,32 +101,42 @@ pub fn play_animations(
|
|||||||
&BlueprintAnimations,
|
&BlueprintAnimations,
|
||||||
),
|
),
|
||||||
(With<AnimationInfos>, With<Marker3>),
|
(With<AnimationInfos>, With<Marker3>),
|
||||||
>,
|
>, */
|
||||||
|
mut animation_players: Query<(&mut AnimationPlayer, &mut AnimationTransitions)>,
|
||||||
animated_fox: Query<(&BlueprintAnimationPlayerLink, &BlueprintAnimations), With<MarkerFox>>,
|
|
||||||
|
|
||||||
mut animation_players: Query<&mut AnimationPlayer>,
|
|
||||||
keycode: Res<ButtonInput<KeyCode>>,
|
keycode: Res<ButtonInput<KeyCode>>,
|
||||||
) {
|
) {
|
||||||
if keycode.just_pressed(KeyCode::KeyP) {
|
if keycode.just_pressed(KeyCode::KeyP) {
|
||||||
|
println!("playing fox animation requested");
|
||||||
for (link, animations) in animated_fox.iter() {
|
for (link, animations) in animated_fox.iter() {
|
||||||
println!("animations {:?}", animations.named_animations);
|
println!("animations {:?}", animations.named_animations);
|
||||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
println!("LINK target {}", link.0);
|
||||||
let anim_name = "Run";
|
let (mut animation_player, mut animation_transitions) =
|
||||||
animation_player
|
animation_players.get_mut(link.0).unwrap();
|
||||||
.play_with_transition(
|
let anim_name = "Survey";
|
||||||
animations
|
let animation_index = animations
|
||||||
.named_animations
|
.named_indices
|
||||||
.get(anim_name)
|
.get(anim_name)
|
||||||
.expect("animation name should be in the list")
|
.expect("animation name should be in the list")
|
||||||
.clone(),
|
.clone();
|
||||||
|
|
||||||
|
animation_transitions
|
||||||
|
.play(
|
||||||
|
&mut animation_player,
|
||||||
|
animation_index,
|
||||||
Duration::from_secs(5),
|
Duration::from_secs(5),
|
||||||
)
|
)
|
||||||
.repeat();
|
.repeat();
|
||||||
|
|
||||||
|
/*let Some((&playing_animation_index, _)) = animation_player.playing_animations().next() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let playing_animation = animation_player.animation_mut(playing_animation_index).unwrap();
|
||||||
|
println!("Playing animation {:?}", playing_animation);
|
||||||
|
playing_animation.set_repeat(RepeatAnimation::Forever);*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if keycode.just_pressed(KeyCode::KeyM) {
|
/*if keycode.just_pressed(KeyCode::KeyM) {
|
||||||
for (link, animations) in animated_marker1.iter() {
|
for (link, animations) in animated_marker1.iter() {
|
||||||
println!("animations {:?}", animations.named_animations);
|
println!("animations {:?}", animations.named_animations);
|
||||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
||||||
@ -229,9 +241,9 @@ pub fn play_animations(
|
|||||||
)
|
)
|
||||||
.repeat();
|
.repeat();
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
pub fn react_to_animation_markers(
|
pub fn react_to_animation_markers(
|
||||||
mut animation_marker_events: EventReader<AnimationMarkerReached>,
|
mut animation_marker_events: EventReader<AnimationMarkerReached>,
|
||||||
) {
|
) {
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use bevy::prelude::*;
|
|
||||||
use blenvy::{BluePrintBundle, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag, HideUntilReady, SpawnHere};
|
|
||||||
use crate::{GameState, InAppRunning};
|
use crate::{GameState, InAppRunning};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use blenvy::{
|
||||||
|
AddToGameWorld, BluePrintBundle, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag,
|
||||||
|
HideUntilReady, SpawnBlueprint,
|
||||||
|
};
|
||||||
|
|
||||||
//use bevy_rapier3d::prelude::Velocity;
|
//use bevy_rapier3d::prelude::Velocity;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
@ -22,10 +25,13 @@ pub fn setup_game(
|
|||||||
));*/
|
));*/
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
BlueprintInfo{name: "World".into(), path: "levels/World.glb".into()},
|
BlueprintInfo {
|
||||||
|
name: "World".into(),
|
||||||
|
path: "levels/World.glb".into(),
|
||||||
|
},
|
||||||
HideUntilReady,
|
HideUntilReady,
|
||||||
bevy::prelude::Name::from("world"), //FIXME: not really needed ? could be infered from blueprint's name/ path
|
bevy::prelude::Name::from("world"), //FIXME: not really needed ? could be infered from blueprint's name/ path
|
||||||
SpawnHere,
|
SpawnBlueprint,
|
||||||
GameWorldTag,
|
GameWorldTag,
|
||||||
InAppRunning,
|
InAppRunning,
|
||||||
));
|
));
|
||||||
@ -43,7 +49,7 @@ pub fn spawn_test(
|
|||||||
|
|
||||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||||
) {
|
) {
|
||||||
if keycode.just_pressed(KeyCode::KeyT) {
|
if keycode.just_pressed(KeyCode::KeyS) {
|
||||||
let world = game_world.single_mut();
|
let world = game_world.single_mut();
|
||||||
let world = world.1[0];
|
let world = world.1[0];
|
||||||
|
|
||||||
@ -63,13 +69,16 @@ pub fn spawn_test(
|
|||||||
let new_entity = commands
|
let new_entity = commands
|
||||||
.spawn((
|
.spawn((
|
||||||
BluePrintBundle {
|
BluePrintBundle {
|
||||||
blueprint: BlueprintInfo{name: "Blueprint1".into() , path:"blueprints/Blueprint1.glb".into()}, // FIXME
|
blueprint: BlueprintInfo {
|
||||||
|
name: "Blueprint1".into(),
|
||||||
|
path: "blueprints/Blueprint1.glb".into(),
|
||||||
|
}, // FIXME
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
DynamicBlueprintInstance,
|
DynamicBlueprintInstance,
|
||||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||||
HideUntilReady,
|
HideUntilReady,
|
||||||
// SpawnHere,
|
AddToGameWorld,
|
||||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||||
/*Velocity {
|
/*Velocity {
|
||||||
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||||
@ -77,6 +86,6 @@ pub fn spawn_test(
|
|||||||
},*/
|
},*/
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
commands.entity(world).add_child(new_entity);
|
//commands.entity(world).add_child(new_entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,15 @@ pub use animation::*;
|
|||||||
use std::{collections::HashMap, fs, time::Duration};
|
use std::{collections::HashMap, fs, time::Duration};
|
||||||
|
|
||||||
use blenvy::{
|
use blenvy::{
|
||||||
BlueprintAssets, BlueprintAnimationPlayerLink, BlueprintEvent, BlueprintInfo, GltfBlueprintsSet, SceneAnimations
|
BlueprintAnimationPlayerLink, BlueprintAssets, BlueprintEvent, BlueprintInfo,
|
||||||
|
GltfBlueprintsSet, SceneAnimations,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::{AppState, GameState};
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::*, render::view::screenshot::ScreenshotManager, time::common_conditions::on_timer,
|
prelude::*, render::view::screenshot::ScreenshotManager, time::common_conditions::on_timer,
|
||||||
window::PrimaryWindow,
|
window::PrimaryWindow,
|
||||||
};
|
};
|
||||||
use crate::{AppState, GameState};
|
|
||||||
|
|
||||||
use json_writer::to_json_string;
|
use json_writer::to_json_string;
|
||||||
|
|
||||||
@ -130,15 +131,32 @@ fn exit_game(mut app_exit_events: ResMut<Events<bevy::app::AppExit>>) {
|
|||||||
fn check_for_gltf_events(
|
fn check_for_gltf_events(
|
||||||
mut blueprint_events: EventReader<BlueprintEvent>,
|
mut blueprint_events: EventReader<BlueprintEvent>,
|
||||||
all_names: Query<&Name>,
|
all_names: Query<&Name>,
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
for event in blueprint_events.read() {
|
for event in blueprint_events.read() {
|
||||||
match event {
|
match event {
|
||||||
BlueprintEvent::InstanceReady{entity, blueprint_name, blueprint_path} => {
|
BlueprintEvent::InstanceReady {
|
||||||
info!("BLUEPRINT EVENT: {:?} for {:?}", event, all_names.get(*entity));
|
entity,
|
||||||
|
blueprint_name,
|
||||||
|
blueprint_path,
|
||||||
|
} => {
|
||||||
|
info!(
|
||||||
|
"BLUEPRINT EVENT: {:?} for {:?}",
|
||||||
|
event,
|
||||||
|
all_names.get(*entity)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_=> {
|
BlueprintEvent::AssetsLoaded {
|
||||||
|
entity,
|
||||||
|
blueprint_name,
|
||||||
|
blueprint_path,
|
||||||
|
} => {
|
||||||
|
info!(
|
||||||
|
"BLUEPRINT EVENT: {:?} for {:?}",
|
||||||
|
event,
|
||||||
|
all_names.get(*entity)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
info!("BLUEPRINT EVENT: {:?}", event);
|
info!("BLUEPRINT EVENT: {:?}", event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,9 +182,9 @@ impl Plugin for GamePlugin {
|
|||||||
/* .add_systems(Update, (animations)
|
/* .add_systems(Update, (animations)
|
||||||
.run_if(in_state(AppState::AppRunning))
|
.run_if(in_state(AppState::AppRunning))
|
||||||
.after(GltfBlueprintsSet::AfterSpawn)
|
.after(GltfBlueprintsSet::AfterSpawn)
|
||||||
)
|
)*/
|
||||||
.add_systems(Update, play_animations)
|
.add_systems(Update, play_animations)
|
||||||
.add_systems(Update, react_to_animation_markers)*/
|
//.add_systems(Update, react_to_animation_markers)
|
||||||
|
|
||||||
/*.add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once
|
/*.add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once
|
||||||
.add_systems(
|
.add_systems(
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use bevy::{gltf::{GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras}, prelude::*};
|
use bevy::{
|
||||||
|
gltf::{GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
use blenvy::{BlueprintAssets, BlueprintInstanceReady};
|
use blenvy::{BlueprintAssets, BlueprintInstanceReady};
|
||||||
|
|
||||||
use crate::{BasicTest, EnumComplex, RedirectPropHitImpulse};
|
use crate::{BasicTest, EnumComplex, RedirectPropHitImpulse};
|
||||||
@ -6,13 +9,19 @@ use crate::{BasicTest, EnumComplex, RedirectPropHitImpulse};
|
|||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct HiearchyDebugTag;
|
pub struct HiearchyDebugTag;
|
||||||
|
|
||||||
pub fn setup_hierarchy_debug(mut commands: Commands, asset_server: Res<AssetServer>){
|
pub fn setup_hierarchy_debug(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
// a place to display the extras on screen
|
// a place to display the extras on screen
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
TextBundle::from_section(
|
TextBundle::from_section(
|
||||||
"",
|
"",
|
||||||
TextStyle {
|
TextStyle {
|
||||||
color: LinearRgba { red: 1.0, green:1.0, blue: 1.0, alpha: 1.0}.into(),
|
color: LinearRgba {
|
||||||
|
red: 1.0,
|
||||||
|
green: 1.0,
|
||||||
|
blue: 1.0,
|
||||||
|
alpha: 1.0,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
font_size: 15.,
|
font_size: 15.,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
@ -27,38 +36,45 @@ pub fn setup_hierarchy_debug(mut commands: Commands, asset_server: Res<AssetServ
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_descendants(
|
pub fn get_descendants(
|
||||||
all_children: &Query<&Children>,
|
all_children: &Query<&Children>,
|
||||||
all_names:&Query<&Name>,
|
all_names: &Query<&Name>,
|
||||||
root: &Entity,
|
root: &Entity,
|
||||||
all_transforms: &Query<&Transform>,
|
all_transforms: &Query<&Transform>,
|
||||||
all_global_transforms: &Query<&GlobalTransform>,
|
all_global_transforms: &Query<&GlobalTransform>,
|
||||||
nesting: usize,
|
nesting: usize,
|
||||||
to_check: &Query<&BasicTest>//&Query<(&BlueprintInstanceReady, &BlueprintAssets)>,
|
to_check: &Query<&BasicTest>, //&Query<(&BlueprintInstanceReady, &BlueprintAssets)>,
|
||||||
)
|
) -> String {
|
||||||
-> String
|
|
||||||
{
|
|
||||||
|
|
||||||
let mut hierarchy_display: Vec<String> = vec![];
|
let mut hierarchy_display: Vec<String> = vec![];
|
||||||
let root_name = all_names.get(*root);
|
let root_name = all_names.get(*root);
|
||||||
let name;
|
let name;
|
||||||
if root_name.is_ok() {
|
if root_name.is_ok() {
|
||||||
name = root_name.unwrap().to_string();
|
name = root_name.unwrap().to_string();
|
||||||
}else {
|
} else {
|
||||||
name = "no_name".to_string()
|
name = "no_name".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
let components_to_check = to_check.get(*root);
|
let components_to_check = to_check.get(*root);
|
||||||
|
|
||||||
hierarchy_display.push( format!("{}{} ({:?}) ({:?})", " ".repeat(nesting), name, all_transforms.get(*root), all_global_transforms.get(*root)) ); //components_to_check ({:?})
|
hierarchy_display.push(format!(
|
||||||
|
"{}{} ({:?}) ({:?})",
|
||||||
|
" ".repeat(nesting),
|
||||||
|
name,
|
||||||
|
all_transforms.get(*root),
|
||||||
|
all_global_transforms.get(*root)
|
||||||
|
)); //components_to_check ({:?})
|
||||||
|
|
||||||
if let Ok(children) = all_children.get(*root) {
|
if let Ok(children) = all_children.get(*root) {
|
||||||
|
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
|
let child_descendants_display = get_descendants(
|
||||||
let child_descendants_display = get_descendants(&all_children, &all_names, &child, &all_transforms, &all_global_transforms, nesting + 4, &to_check);
|
&all_children,
|
||||||
|
&all_names,
|
||||||
|
&child,
|
||||||
|
&all_transforms,
|
||||||
|
&all_global_transforms,
|
||||||
|
nesting + 4,
|
||||||
|
&to_check,
|
||||||
|
);
|
||||||
hierarchy_display.push(child_descendants_display);
|
hierarchy_display.push(child_descendants_display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,94 +84,99 @@ pub fn get_descendants(
|
|||||||
pub fn draw_hierarchy_debug(
|
pub fn draw_hierarchy_debug(
|
||||||
root: Query<(Entity, Option<&Name>, &Children), (Without<Parent>)>,
|
root: Query<(Entity, Option<&Name>, &Children), (Without<Parent>)>,
|
||||||
all_children: Query<&Children>,
|
all_children: Query<&Children>,
|
||||||
all_names:Query<&Name>,
|
all_names: Query<&Name>,
|
||||||
all_transforms: Query<&Transform>,
|
all_transforms: Query<&Transform>,
|
||||||
all_global_transforms: Query<&GlobalTransform>,
|
all_global_transforms: Query<&GlobalTransform>,
|
||||||
|
|
||||||
to_check: Query<&BasicTest>,//Query<(&BlueprintInstanceReady, &BlueprintAssets)>,
|
to_check: Query<&BasicTest>, //Query<(&BlueprintInstanceReady, &BlueprintAssets)>,
|
||||||
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
||||||
){
|
) {
|
||||||
let mut hierarchy_display: Vec<String> = vec![];
|
let mut hierarchy_display: Vec<String> = vec![];
|
||||||
|
|
||||||
for (root_entity, name, children) in root.iter() {
|
for (root_entity, name, children) in root.iter() {
|
||||||
// hierarchy_display.push( format!("Hierarchy root{:?}", name) );
|
// hierarchy_display.push( format!("Hierarchy root{:?}", name) );
|
||||||
|
|
||||||
hierarchy_display.push(get_descendants(&all_children, &all_names, &root_entity, &all_transforms, &all_global_transforms, 0, &to_check));
|
hierarchy_display.push(get_descendants(
|
||||||
|
&all_children,
|
||||||
|
&all_names,
|
||||||
|
&root_entity,
|
||||||
|
&all_transforms,
|
||||||
|
&all_global_transforms,
|
||||||
|
0,
|
||||||
|
&to_check,
|
||||||
|
));
|
||||||
// let mut children = all_children.get(root_entity);
|
// let mut children = all_children.get(root_entity);
|
||||||
/*for child in children.iter() {
|
/*for child in children.iter() {
|
||||||
// hierarchy_display
|
// hierarchy_display
|
||||||
let name = all_names.get(*child); //.unwrap_or(&Name::new("no name"));
|
let name = all_names.get(*child); //.unwrap_or(&Name::new("no name"));
|
||||||
hierarchy_display.push(format!(" {:?}", name))
|
hierarchy_display.push(format!(" {:?}", name))
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
let mut display = display.single_mut();
|
let mut display = display.single_mut();
|
||||||
display.sections[0].value = hierarchy_display.join("\n");
|
display.sections[0].value = hierarchy_display.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////:just some testing for gltf extras
|
////////:just some testing for gltf extras
|
||||||
fn check_for_gltf_extras(
|
fn check_for_gltf_extras(
|
||||||
gltf_extras_per_entity: Query<(
|
gltf_extras_per_entity: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
Option<&Name>,
|
Option<&Name>,
|
||||||
Option<&GltfSceneExtras>,
|
Option<&GltfSceneExtras>,
|
||||||
Option<&GltfExtras>,
|
Option<&GltfExtras>,
|
||||||
Option<&GltfMeshExtras>,
|
Option<&GltfMeshExtras>,
|
||||||
Option<&GltfMaterialExtras>,
|
Option<&GltfMaterialExtras>,
|
||||||
)>,
|
)>,
|
||||||
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
||||||
) {
|
) {
|
||||||
let mut gltf_extra_infos_lines: Vec<String> = vec![];
|
let mut gltf_extra_infos_lines: Vec<String> = vec![];
|
||||||
|
|
||||||
for (id, name, scene_extras, extras, mesh_extras, material_extras) in
|
for (id, name, scene_extras, extras, mesh_extras, material_extras) in
|
||||||
gltf_extras_per_entity.iter()
|
gltf_extras_per_entity.iter()
|
||||||
{
|
{
|
||||||
if scene_extras.is_some()
|
if scene_extras.is_some()
|
||||||
//|| extras.is_some()
|
//|| extras.is_some()
|
||||||
|| mesh_extras.is_some()
|
|| mesh_extras.is_some()
|
||||||
|| material_extras.is_some()
|
|| material_extras.is_some()
|
||||||
{
|
{
|
||||||
let formatted_extras = format!(
|
let formatted_extras = format!(
|
||||||
"Extras per entity {} ('Name: {}'):
|
"Extras per entity {} ('Name: {}'):
|
||||||
- scene extras: {:?}
|
- scene extras: {:?}
|
||||||
- mesh extras: {:?}
|
- mesh extras: {:?}
|
||||||
- material extras: {:?}
|
- material extras: {:?}
|
||||||
",
|
",
|
||||||
id,
|
id,
|
||||||
name.unwrap_or(&Name::default()),
|
name.unwrap_or(&Name::default()),
|
||||||
scene_extras,
|
scene_extras,
|
||||||
//extras,
|
//extras,
|
||||||
mesh_extras,
|
mesh_extras,
|
||||||
material_extras
|
material_extras
|
||||||
);
|
);
|
||||||
gltf_extra_infos_lines.push(formatted_extras);
|
gltf_extra_infos_lines.push(formatted_extras);
|
||||||
|
}
|
||||||
|
let mut display = display.single_mut();
|
||||||
|
display.sections[0].value = gltf_extra_infos_lines.join("\n");
|
||||||
}
|
}
|
||||||
let mut display = display.single_mut();
|
|
||||||
display.sections[0].value = gltf_extra_infos_lines.join("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_component(
|
fn check_for_component(
|
||||||
foo: Query<(Entity, Option<&Name>, &RedirectPropHitImpulse)>,
|
foo: Query<(Entity, Option<&Name>, &RedirectPropHitImpulse)>,
|
||||||
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
||||||
|
) {
|
||||||
){
|
|
||||||
let mut info_lines: Vec<String> = vec![];
|
let mut info_lines: Vec<String> = vec![];
|
||||||
for (entiity, name , enum_complex) in foo.iter(){
|
for (entiity, name, enum_complex) in foo.iter() {
|
||||||
let data = format!(" We have a matching component: {:?} (on {:?})", enum_complex, name);
|
let data = format!(
|
||||||
|
" We have a matching component: {:?} (on {:?})",
|
||||||
|
enum_complex, name
|
||||||
|
);
|
||||||
info_lines.push(data);
|
info_lines.push(data);
|
||||||
println!("yoho component");
|
println!("yoho component");
|
||||||
|
|
||||||
}
|
}
|
||||||
let mut display = display.single_mut();
|
let mut display = display.single_mut();
|
||||||
display.sections[0].value = info_lines.join("\n");
|
display.sections[0].value = info_lines.join("\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct HiearchyDebugPlugin;
|
pub struct HiearchyDebugPlugin;
|
||||||
impl Plugin for HiearchyDebugPlugin {
|
impl Plugin for HiearchyDebugPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
@ -164,7 +185,6 @@ impl Plugin for HiearchyDebugPlugin {
|
|||||||
//.add_systems(Update, check_for_component)
|
//.add_systems(Update, check_for_component)
|
||||||
//.add_systems(Update, draw_hierarchy_debug)
|
//.add_systems(Update, draw_hierarchy_debug)
|
||||||
//.add_systems(Update, check_for_gltf_extras)
|
//.add_systems(Update, check_for_gltf_extras)
|
||||||
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ fn main() {
|
|||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins.set(AssetPlugin::default()),
|
DefaultPlugins.set(AssetPlugin::default()),
|
||||||
|
|
||||||
HiearchyDebugPlugin,
|
HiearchyDebugPlugin,
|
||||||
// our custom plugins
|
// our custom plugins
|
||||||
// CommonPlugin,
|
// CommonPlugin,
|
||||||
|
@ -52,8 +52,6 @@ pub struct InGameLoading;
|
|||||||
pub struct StatePlugin;
|
pub struct StatePlugin;
|
||||||
impl Plugin for StatePlugin {
|
impl Plugin for StatePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.init_state::<AppState>().init_state::<GameState>();
|
||||||
.init_state::<AppState>()
|
|
||||||
.init_state::<GameState>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ pub struct ComponentBToFilterOut;
|
|||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct ComponentWithFieldsOfIdenticalType{
|
pub struct ComponentWithFieldsOfIdenticalType {
|
||||||
pub first: f32,
|
pub first: f32,
|
||||||
pub second: f32,
|
pub second: f32,
|
||||||
pub third: Vec<f32>,
|
pub third: Vec<f32>,
|
||||||
@ -224,9 +224,8 @@ pub struct ComponentWithFieldsOfIdenticalType{
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct ComponentWithFieldsOfIdenticalType2(f32, f32, f32);
|
pub struct ComponentWithFieldsOfIdenticalType2(f32, f32, f32);
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Reflect, Component)]
|
#[derive(Debug, Clone, Copy, PartialEq, Reflect, Component)]
|
||||||
#[reflect(Component, )]
|
#[reflect(Component)]
|
||||||
pub enum RedirectPropHitImpulse {
|
pub enum RedirectPropHitImpulse {
|
||||||
Local(Vec3),
|
Local(Vec3),
|
||||||
}
|
}
|
||||||
@ -279,14 +278,11 @@ impl Plugin for ComponentsTestPlugin {
|
|||||||
.register_type::<HashmapTestStringColorFlat>()
|
.register_type::<HashmapTestStringColorFlat>()
|
||||||
.register_type::<HashmapTestStringEnum>()
|
.register_type::<HashmapTestStringEnum>()
|
||||||
.register_type::<HashmapTestStringStruct>()
|
.register_type::<HashmapTestStringStruct>()
|
||||||
|
|
||||||
.register_type::<ComponentAToFilterOut>()
|
.register_type::<ComponentAToFilterOut>()
|
||||||
.register_type::<ComponentBToFilterOut>()
|
.register_type::<ComponentBToFilterOut>()
|
||||||
.register_type::<ComponentWithFieldsOfIdenticalType>()
|
.register_type::<ComponentWithFieldsOfIdenticalType>()
|
||||||
.register_type::<ComponentWithFieldsOfIdenticalType2>()
|
.register_type::<ComponentWithFieldsOfIdenticalType2>()
|
||||||
|
|
||||||
.register_type::<RedirectPropHitImpulse>()
|
.register_type::<RedirectPropHitImpulse>()
|
||||||
|
|
||||||
.add_plugins(MaterialPlugin::<
|
.add_plugins(MaterialPlugin::<
|
||||||
ExtendedMaterial<StandardMaterial, MyExtension>,
|
ExtendedMaterial<StandardMaterial, MyExtension>,
|
||||||
>::default());
|
>::default());
|
||||||
|
@ -133,7 +133,7 @@ This issue has been resolved in v0.9.
|
|||||||
You can enable this option to automatically replace all the **collection instances** inside your main scene with blueprints
|
You can enable this option to automatically replace all the **collection instances** inside your main scene with blueprints
|
||||||
- whenever you change your main scene (or your library scene , if that option is enabled), all your collection instances
|
- whenever you change your main scene (or your library scene , if that option is enabled), all your collection instances
|
||||||
* will be replaced with empties (this will not be visible to you)
|
* will be replaced with empties (this will not be visible to you)
|
||||||
* those empties will have additional custom properties / components : ```BlueprintInfo``` & ```SpawnHere```
|
* those empties will have additional custom properties / components : ```BlueprintInfo``` & ```SpawnBlueprint```
|
||||||
* your main scene/ level will be exported to a much more trimmed down gltf file (see next point)
|
* your main scene/ level will be exported to a much more trimmed down gltf file (see next point)
|
||||||
* all the original collections (that you used to create the instances) will be exported as **seperate gltf files** into the "library" folder
|
* all the original collections (that you used to create the instances) will be exported as **seperate gltf files** into the "library" folder
|
||||||
|
|
||||||
|
@ -215,18 +215,20 @@ Blender side:
|
|||||||
|
|
||||||
Bevy Side:
|
Bevy Side:
|
||||||
- [x] deprecate BlueprintName & BlueprintPath & use BlueprintInfo instead
|
- [x] deprecate BlueprintName & BlueprintPath & use BlueprintInfo instead
|
||||||
- [ ] make blueprint instances invisible until spawning is done to avoid "spawn flash"?
|
- [x] make blueprint instances invisible until spawning is done to avoid "spawn flash"?
|
||||||
- [ ] restructure blueprint spawning
|
- [x] make this controlable via an additional "HideUntilReady" component
|
||||||
|
- [x] register "HideUntilReady" so users can set this on their blueprints in Blender directly
|
||||||
|
- [x] restructure blueprint spawning
|
||||||
- [x] "blueprint ready" only be triggered after all its sub blueprints are ready
|
- [x] "blueprint ready" only be triggered after all its sub blueprints are ready
|
||||||
- [x] "blueprintInstance ready"/finished
|
- [x] "blueprintInstance ready"/finished
|
||||||
BlueprintAssetsLoaded
|
BlueprintAssetsLoaded
|
||||||
BlueprintSceneSpawned
|
BlueprintSceneSpawned
|
||||||
BlueprintChildrenReady
|
BlueprintChildrenReady
|
||||||
BlueprintReadyForPostProcess
|
BlueprintReadyForPostProcess
|
||||||
- [ ] fix issues with deeply nested blueprints
|
- [x] fix issues with deeply nested blueprints
|
||||||
- perhaps reverse logic by using iter_ascendants
|
- perhaps reverse logic by using iter_ascendants
|
||||||
- [x] fix materials handling
|
- [x] fix materials handling
|
||||||
- [ ] fix animations handling
|
- [x] fix animations handling
|
||||||
|
|
||||||
- [ ] simplify testing example:
|
- [ ] simplify testing example:
|
||||||
- [x] remove use of rapier physics (or even the whole common boilerplate ?)
|
- [x] remove use of rapier physics (or even the whole common boilerplate ?)
|
||||||
@ -235,7 +237,7 @@ Bevy Side:
|
|||||||
- [ ] other examples without interactions or physics
|
- [ ] other examples without interactions or physics
|
||||||
- [ ] add hot reloading
|
- [ ] add hot reloading
|
||||||
- [x] basics
|
- [x] basics
|
||||||
- [ ] make it enabled/disabled based on general flag
|
- [x] make it enabled/disabled based on general flag
|
||||||
- [ ] cleanup internals
|
- [ ] cleanup internals
|
||||||
- [ ] review & change general component insertion & spawning ordering & logic
|
- [ ] review & change general component insertion & spawning ordering & logic
|
||||||
- GltfComponentsSet::Injection => GltfBlueprintsSet::Spawn => GltfBlueprintsSet::AfterSpawn
|
- GltfComponentsSet::Injection => GltfBlueprintsSet::Spawn => GltfBlueprintsSet::AfterSpawn
|
||||||
|
@ -98,7 +98,7 @@ def duplicate_object(object, parent, combine_mode, destination_collection, bluep
|
|||||||
empty_obj = make_empty(original_name, object.location, object.rotation_euler, object.scale, destination_collection)
|
empty_obj = make_empty(original_name, object.location, object.rotation_euler, object.scale, destination_collection)
|
||||||
|
|
||||||
"""we inject the collection/blueprint name & path, as a component called 'BlueprintInfo', but we only do this in the empty, not the original object"""
|
"""we inject the collection/blueprint name & path, as a component called 'BlueprintInfo', but we only do this in the empty, not the original object"""
|
||||||
empty_obj['SpawnHere'] = '()'
|
empty_obj['SpawnBlueprint'] = '()'
|
||||||
empty_obj['BlueprintInfo'] = f'(name: "{blueprint_name}", path: "{blueprint_path}")'
|
empty_obj['BlueprintInfo'] = f'(name: "{blueprint_name}", path: "{blueprint_path}")'
|
||||||
|
|
||||||
# we copy custom properties over from our original object to our empty
|
# we copy custom properties over from our original object to our empty
|
||||||
|
@ -89,7 +89,7 @@ expected_custom_property_values = {'bevy_animation::AnimationPlayer': '(animatio
|
|||||||
'bevy_gltf_blueprints::animation::SceneAnimations': '(named_animations: "")',
|
'bevy_gltf_blueprints::animation::SceneAnimations': '(named_animations: "")',
|
||||||
'bevy_gltf_blueprints::materials::MaterialInfo': '(name: " ", source: " ")',
|
'bevy_gltf_blueprints::materials::MaterialInfo': '(name: " ", source: " ")',
|
||||||
'bevy_gltf_blueprints::spawn_from_blueprints::BlueprintsList': '({})',
|
'bevy_gltf_blueprints::spawn_from_blueprints::BlueprintsList': '({})',
|
||||||
'bevy_gltf_blueprints::spawn_from_blueprints::SpawnHere': '()',
|
'bevy_gltf_blueprints::spawn_from_blueprints::SpawnBlueprint': '()',
|
||||||
'bevy_gltf_components::GltfProcessed': '()',
|
'bevy_gltf_components::GltfProcessed': '()',
|
||||||
'bevy_gltf_components::blender_settings::lighting::BlenderBackgroundShader': '(color: Rgba(red:1.0, green:1.0, '
|
'bevy_gltf_components::blender_settings::lighting::BlenderBackgroundShader': '(color: Rgba(red:1.0, green:1.0, '
|
||||||
'blue:0.0, alpha:1.0), strength: 0.0)',
|
'blue:0.0, alpha:1.0), strength: 0.0)',
|
||||||
@ -347,7 +347,7 @@ expected_custom_property_values_randomized = {'bevy_animation::AnimationPlayer':
|
|||||||
'bevy_gltf_blueprints::animation::SceneAnimations': '(named_animations: "")',
|
'bevy_gltf_blueprints::animation::SceneAnimations': '(named_animations: "")',
|
||||||
'bevy_gltf_blueprints::materials::MaterialInfo': '(name: "sbnpsago", source: "piuzfbqp")',
|
'bevy_gltf_blueprints::materials::MaterialInfo': '(name: "sbnpsago", source: "piuzfbqp")',
|
||||||
'bevy_gltf_blueprints::spawn_from_blueprints::BlueprintsList': '({})',
|
'bevy_gltf_blueprints::spawn_from_blueprints::BlueprintsList': '({})',
|
||||||
'bevy_gltf_blueprints::spawn_from_blueprints::SpawnHere': '()',
|
'bevy_gltf_blueprints::spawn_from_blueprints::SpawnBlueprint': '()',
|
||||||
'bevy_gltf_components::GltfProcessed': '()',
|
'bevy_gltf_components::GltfProcessed': '()',
|
||||||
'bevy_gltf_components::blender_settings::lighting::BlenderBackgroundShader': '(color: Rgba(red:0.5714026093482971, '
|
'bevy_gltf_components::blender_settings::lighting::BlenderBackgroundShader': '(color: Rgba(red:0.5714026093482971, '
|
||||||
'green:0.42888906598091125, '
|
'green:0.42888906598091125, '
|
||||||
|
Loading…
Reference in New Issue
Block a user