mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-26 13:32:32 +00:00
Compare commits
4 Commits
e86920168a
...
8b4bb473dc
Author | SHA1 | Date | |
---|---|---|---|
|
8b4bb473dc | ||
|
00bf600ccf | ||
|
1686aca655 | ||
|
2abdb7f64e |
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_gltf_blueprints"
|
name = "bevy_gltf_blueprints"
|
||||||
version = "0.10.0"
|
version = "0.11.0"
|
||||||
authors = ["Mark 'kaosat-dev' Moissette"]
|
authors = ["Mark 'kaosat-dev' Moissette"]
|
||||||
description = "Adds the ability to define Blueprints/Prefabs for Bevy inside gltf files and spawn them in Bevy."
|
description = "Adds the ability to define Blueprints/Prefabs for Bevy inside gltf files and spawn them in Bevy."
|
||||||
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
@ -14,8 +14,8 @@ license = "MIT OR Apache-2.0"
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy_gltf_components = { version = "0.5", path = "../bevy_gltf_components" }
|
bevy_gltf_components = { version = "0.6", path = "../bevy_gltf_components" }
|
||||||
bevy = { version = "0.13", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf", "bevy_animation", "animation"] }
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf", "bevy_animation", "animation"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { version = "0.13", default-features = false, features = ["dynamic_linking"] }
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["dynamic_linking"] }
|
@ -73,6 +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<(
|
||||||
@ -82,13 +83,15 @@ pub fn trigger_instance_animation_markers_events(
|
|||||||
&SceneAnimations,
|
&SceneAnimations,
|
||||||
&AnimationInfos,
|
&AnimationInfos,
|
||||||
)>,
|
)>,
|
||||||
animation_players: Query<&AnimationPlayer>,
|
animation_players: Query<(&AnimationPlayer)>,
|
||||||
animation_clips: Res<Assets<AnimationClip>>,
|
animation_clips: Res<Assets<AnimationClip>>,
|
||||||
|
animation_graphs: Res<Assets<AnimationGraph>>,
|
||||||
mut animation_marker_events: EventWriter<AnimationMarkerReached>,
|
mut animation_marker_events: EventWriter<AnimationMarkerReached>,
|
||||||
) {
|
) {
|
||||||
for (entity, markers, link, animations, animation_infos) in animation_infos.iter() {
|
for (entity, markers, link, animations, animation_infos) in animation_infos.iter() {
|
||||||
let animation_player = animation_players.get(link.0).unwrap();
|
let animation_player = animation_players.get(link.0).unwrap();
|
||||||
let animation_clip = animation_clips.get(animation_player.animation_clip());
|
let animation_clip = animation_clips.get(animation_player.animation_clip());
|
||||||
|
// animation_player.play(animation)
|
||||||
|
|
||||||
if animation_clip.is_some() {
|
if animation_clip.is_some() {
|
||||||
// println!("Entity {:?} markers {:?}", entity, markers);
|
// println!("Entity {:?} markers {:?}", entity, markers);
|
||||||
@ -215,3 +218,4 @@ pub fn trigger_blueprint_animation_markers_events(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
@ -1,4 +1,4 @@
|
|||||||
use bevy::ecs::system::Command;
|
use bevy::ecs::world::Command;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
|
||||||
|
@ -176,12 +176,13 @@ impl Plugin for BlueprintsPlugin {
|
|||||||
.chain()
|
.chain()
|
||||||
.in_set(GltfBlueprintsSet::AfterSpawn),
|
.in_set(GltfBlueprintsSet::AfterSpawn),
|
||||||
)
|
)
|
||||||
.add_systems(
|
/* .add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
trigger_instance_animation_markers_events,
|
trigger_instance_animation_markers_events,
|
||||||
trigger_blueprint_animation_markers_events,
|
trigger_blueprint_animation_markers_events,
|
||||||
),
|
),
|
||||||
);
|
)*/
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,10 +160,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) {
|
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)
|
.get(&material_info.name as &str)
|
||||||
.expect("this material should have been loaded");
|
.expect("this material should have been loaded");
|
||||||
blueprints_config
|
blueprints_config
|
||||||
.material_library_cache
|
.material_library_cache
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use bevy::{gltf::Gltf, prelude::*, utils::HashMap};
|
use bevy::{gltf::Gltf, prelude::*, utils::hashbrown::HashMap};
|
||||||
|
|
||||||
use crate::{AllAssets, AssetsToLoad, AssetLoadTracker, BluePrintsConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
use crate::{AllAssets, AssetsToLoad, AssetLoadTracker, BluePrintsConfig, BlueprintAnimations, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded};
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ pub struct SpawnHere;
|
|||||||
pub struct Spawned;
|
pub struct Spawned;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component)]
|
#[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
|
||||||
@ -194,8 +194,13 @@ pub(crate) fn check_for_loaded2(
|
|||||||
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 failed = asset_server.load_state(asset_id) == bevy::asset::LoadState::Failed;
|
let mut failed = false;// asset_server.load_state(asset_id) == bevy::asset::LoadState::Failed(_error);
|
||||||
|
match asset_server.load_state(asset_id) {
|
||||||
|
bevy::asset::LoadState::Failed(_) => {
|
||||||
|
failed = true
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
tracker.loaded = loaded || failed;
|
tracker.loaded = loaded || failed;
|
||||||
if loaded || failed {
|
if loaded || failed {
|
||||||
loaded_amount += 1;
|
loaded_amount += 1;
|
||||||
@ -295,6 +300,12 @@ pub(crate) fn spawn_from_blueprints2(
|
|||||||
original_children.push(*child);
|
original_children.push(*child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut named_animations:HashMap<String, Handle<AnimationClip>> = HashMap::new() ;
|
||||||
|
for (key, value) in gltf.named_animations.iter() {
|
||||||
|
named_animations.insert(key.to_string(), value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
commands.entity(entity).insert((
|
commands.entity(entity).insert((
|
||||||
SceneBundle {
|
SceneBundle {
|
||||||
scene: scene.clone(),
|
scene: scene.clone(),
|
||||||
@ -306,7 +317,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: gltf.named_animations.clone(),
|
named_animations: named_animations//gltf.named_animations.clone(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ pub(crate) fn spawned_blueprint_post_process(
|
|||||||
for (original, children, original_children, animations, no_inblueprint, name) in
|
for (original, children, original_children, animations, no_inblueprint, name) in
|
||||||
unprocessed_entities.iter()
|
unprocessed_entities.iter()
|
||||||
{
|
{
|
||||||
debug!("post processing blueprint for entity {:?}", name);
|
info!("post processing blueprint for entity {:?}", name);
|
||||||
|
|
||||||
if children.len() == 0 {
|
if children.len() == 0 {
|
||||||
warn!("timing issue ! no children found, please restart your bevy app (bug being investigated)");
|
warn!("timing issue ! no children found, please restart your bevy app (bug being investigated)");
|
||||||
@ -94,9 +94,10 @@ pub(crate) fn spawned_blueprint_post_process(
|
|||||||
|
|
||||||
commands.entity(original).remove::<SpawnHere>();
|
commands.entity(original).remove::<SpawnHere>();
|
||||||
commands.entity(original).remove::<Spawned>();
|
commands.entity(original).remove::<Spawned>();
|
||||||
commands.entity(original).remove::<Handle<Scene>>();
|
// 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::<AssetsToLoad>(); // 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::<AssetsToLoad>(); // 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::<BlueprintAssetsLoaded>();
|
//commands.entity(original).remove::<BlueprintAssetsLoaded>();
|
||||||
commands.entity(root_entity).despawn_recursive();
|
commands.entity(root_entity).despawn_recursive();
|
||||||
|
info!("DONE WITH POST PROCESS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bevy_gltf_components"
|
name = "bevy_gltf_components"
|
||||||
version = "0.5.1"
|
version = "0.6.0"
|
||||||
authors = ["Mark 'kaosat-dev' Moissette"]
|
authors = ["Mark 'kaosat-dev' Moissette"]
|
||||||
description = "Allows you to define Bevy components direclty inside gltf files and instanciate the components on the Bevy side."
|
description = "Allows you to define Bevy components direclty inside gltf files and instanciate the components on the Bevy side."
|
||||||
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
@ -14,9 +14,9 @@ license = "MIT OR Apache-2.0"
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.13", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] }
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] }
|
||||||
serde = "1.0.188"
|
serde = "1.0.188"
|
||||||
ron = "0.8.1"
|
ron = "0.8.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { version = "0.13", default-features = false, features = ["dynamic_linking"] }
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["dynamic_linking"] }
|
@ -6,7 +6,7 @@ use bevy::{
|
|||||||
reflect::{AppTypeRegistry, ReflectComponent},
|
reflect::{AppTypeRegistry, ReflectComponent},
|
||||||
world::World,
|
world::World,
|
||||||
},
|
},
|
||||||
gltf::GltfExtras,
|
gltf::{GltfExtras, GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras},
|
||||||
hierarchy::Parent,
|
hierarchy::Parent,
|
||||||
log::debug,
|
log::debug,
|
||||||
reflect::{Reflect, TypeRegistration},
|
reflect::{Reflect, TypeRegistration},
|
||||||
@ -15,25 +15,8 @@ use bevy::{
|
|||||||
|
|
||||||
use crate::{ronstring_to_reflect_component, GltfProcessed};
|
use crate::{ronstring_to_reflect_component, GltfProcessed};
|
||||||
|
|
||||||
/// main function: injects components into each entity in gltf files that have `gltf_extras`, using reflection
|
// , mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>
|
||||||
pub fn add_components_from_gltf_extras(world: &mut World) {
|
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)>){
|
||||||
let mut extras =
|
|
||||||
world.query_filtered::<(Entity, &Name, &GltfExtras, &Parent), (Added<GltfExtras>, Without<GltfProcessed>)>();
|
|
||||||
let mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>> =
|
|
||||||
HashMap::new();
|
|
||||||
|
|
||||||
// let gltf_components_config = world.resource::<GltfComponentsConfig>();
|
|
||||||
|
|
||||||
for (entity, name, extra, parent) in extras.iter(world) {
|
|
||||||
debug!(
|
|
||||||
"Name: {}, entity {:?}, parent: {:?}, extras {:?}",
|
|
||||||
name, entity, parent, extra
|
|
||||||
);
|
|
||||||
|
|
||||||
let type_registry: &AppTypeRegistry = world.resource();
|
|
||||||
let type_registry = type_registry.read();
|
|
||||||
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
|
||||||
|
|
||||||
// we assign the components specified /xxx_components objects to their parent node
|
// we assign the components specified /xxx_components objects to their parent node
|
||||||
let mut target_entity = entity;
|
let mut target_entity = 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
|
// 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
|
||||||
@ -57,12 +40,86 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
|
|||||||
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));
|
||||||
}
|
}
|
||||||
entity_components.insert(target_entity, updated_components);
|
return (target_entity, updated_components)
|
||||||
|
//entity_components.insert(target_entity, updated_components);
|
||||||
} else {
|
} else {
|
||||||
entity_components.insert(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
|
||||||
|
pub fn add_components_from_gltf_extras(world: &mut World) {
|
||||||
|
let mut extras =
|
||||||
|
world.query_filtered::<(Entity, &Name, &GltfExtras, &Parent), (Added<GltfExtras>, Without<GltfProcessed>)>();
|
||||||
|
|
||||||
|
let mut scene_extras = world.query_filtered::<(Entity, &Name, &GltfSceneExtras, &Parent), (Added<GltfSceneExtras>, Without<GltfProcessed>)>();
|
||||||
|
let mut mesh_extras = world.query_filtered::<(Entity, &Name, &GltfMeshExtras, &Parent), (Added<GltfMeshExtras>, Without<GltfProcessed>)>();
|
||||||
|
let mut material_extras = world.query_filtered::<(Entity, &Name, &GltfMaterialExtras, &Parent), (Added<GltfMaterialExtras>, Without<GltfProcessed>)>();
|
||||||
|
|
||||||
|
let mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>> =
|
||||||
|
HashMap::new();
|
||||||
|
|
||||||
|
// let gltf_components_config = world.resource::<GltfComponentsConfig>();
|
||||||
|
|
||||||
|
for (entity, name, extra, parent) in extras.iter(world) {
|
||||||
|
debug!(
|
||||||
|
"Name: {}, entity {:?}, parent: {:?}, extras {:?}",
|
||||||
|
name, entity, parent, extra
|
||||||
|
);
|
||||||
|
|
||||||
|
let type_registry: &AppTypeRegistry = world.resource();
|
||||||
|
let type_registry = type_registry.read();
|
||||||
|
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);
|
||||||
|
entity_components.insert(target_entity, updated_components);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (entity, name, extra, parent) in scene_extras.iter(world) {
|
||||||
|
debug!(
|
||||||
|
"Name: {}, entity {:?}, parent: {:?}, scene_extras {:?}",
|
||||||
|
name, entity, parent, extra
|
||||||
|
);
|
||||||
|
|
||||||
|
let type_registry: &AppTypeRegistry = world.resource();
|
||||||
|
let type_registry = type_registry.read();
|
||||||
|
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);
|
||||||
|
entity_components.insert(target_entity, updated_components);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, name, extra, parent) in mesh_extras.iter(world) {
|
||||||
|
debug!(
|
||||||
|
"Name: {}, entity {:?}, parent: {:?}, mesh_extras {:?}",
|
||||||
|
name, entity, parent, extra
|
||||||
|
);
|
||||||
|
|
||||||
|
let type_registry: &AppTypeRegistry = world.resource();
|
||||||
|
let type_registry = type_registry.read();
|
||||||
|
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);
|
||||||
|
entity_components.insert(target_entity, updated_components);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, name, extra, parent) in material_extras.iter(world) {
|
||||||
|
debug!(
|
||||||
|
"Name: {}, entity {:?}, parent: {:?}, material_extras {:?}",
|
||||||
|
name, entity, parent, extra
|
||||||
|
);
|
||||||
|
|
||||||
|
let type_registry: &AppTypeRegistry = world.resource();
|
||||||
|
let type_registry = type_registry.read();
|
||||||
|
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);
|
||||||
|
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::UntypedReflectDeserializer;
|
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;
|
||||||
@ -68,7 +68,7 @@ fn components_string_to_components(
|
|||||||
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");
|
||||||
let reflect_deserializer = UntypedReflectDeserializer::new(type_registry);
|
let reflect_deserializer = ReflectDeserializer::new(type_registry);
|
||||||
let component = reflect_deserializer
|
let component = reflect_deserializer
|
||||||
.deserialize(&mut deserializer)
|
.deserialize(&mut deserializer)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
@ -113,7 +113,7 @@ fn bevy_components_string_to_components(
|
|||||||
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");
|
||||||
let reflect_deserializer = UntypedReflectDeserializer::new(type_registry);
|
let reflect_deserializer = ReflectDeserializer::new(type_registry);
|
||||||
let component = reflect_deserializer
|
let component = reflect_deserializer
|
||||||
.deserialize(&mut deserializer)
|
.deserialize(&mut deserializer)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -14,8 +14,8 @@ license = "MIT OR Apache-2.0"
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.13", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] }
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] }
|
||||||
bevy_gltf_blueprints = { version = "0.10", path = "../bevy_gltf_blueprints" }
|
bevy_gltf_blueprints = { version = "0.11", path = "../bevy_gltf_blueprints" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { version = "0.13", default-features = false, features = ["dynamic_linking"] }
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["dynamic_linking"] }
|
||||||
|
@ -147,7 +147,7 @@ pub(crate) fn save_game(world: &mut World) {
|
|||||||
// dyn_scene.resources.append(&mut dyn_scene_root.resources);
|
// dyn_scene.resources.append(&mut dyn_scene_root.resources);
|
||||||
|
|
||||||
let serialized_scene = dyn_scene
|
let serialized_scene = dyn_scene
|
||||||
.serialize_ron(world.resource::<AppTypeRegistry>())
|
.serialize(&world.resource::<AppTypeRegistry>().read())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let save_path = Path::new("assets")
|
let save_path = Path::new("assets")
|
||||||
|
@ -11,11 +11,11 @@ edition = "2021"
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.13", default-features = false, features = ["bevy_scene"] }
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_scene"] }
|
||||||
bevy_reflect = { version = "0.13", default-features = false }
|
bevy_reflect = { version = "0.14.0-rc.3", default-features = false }
|
||||||
bevy_app = { version = "0.13", default-features = false, features = ["bevy_reflect"] }
|
bevy_app = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_reflect"] }
|
||||||
bevy_ecs = { version = "0.13", default-features = false, features = ["bevy_reflect"] }
|
bevy_ecs = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_reflect"] }
|
||||||
serde_json = "1.0.108"
|
serde_json = "1.0.108"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { version = "0.13", default-features = false, features = ["dynamic_linking"] }
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["dynamic_linking"] }
|
22
crates/blenvy/Cargo.toml
Normal file
22
crates/blenvy/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "blenvy"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["Mark 'kaosat-dev' Moissette"]
|
||||||
|
description = "Allows you to define Bevy components direclty inside gltf files and instanciate the components on the Bevy side."
|
||||||
|
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
|
repository = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
|
keywords = ["gamedev", "bevy", "assets", "gltf", "components"]
|
||||||
|
categories = ["game-development"]
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] }
|
||||||
|
serde = "1.0.188"
|
||||||
|
ron = "0.8.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
bevy = { version = "0.14.0-rc.3", default-features = false, features = ["dynamic_linking"] }
|
8
crates/blenvy/src/blender_settings.rs
Normal file
8
crates/blenvy/src/blender_settings.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
mod lighting;
|
||||||
|
pub use lighting::*;
|
||||||
|
|
||||||
|
pub(crate) fn plugin(app: &mut App) {
|
||||||
|
app.add_plugins(lighting::plugin);
|
||||||
|
}
|
97
crates/blenvy/src/blender_settings/lighting.rs
Normal file
97
crates/blenvy/src/blender_settings/lighting.rs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
use bevy::pbr::DirectionalLightShadowMap;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::GltfComponentsSet;
|
||||||
|
|
||||||
|
pub(crate) fn plugin(app: &mut App) {
|
||||||
|
app.register_type::<BlenderBackgroundShader>()
|
||||||
|
.register_type::<BlenderShadowSettings>()
|
||||||
|
.register_type::<BlenderLightShadows>()
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(process_lights, process_shadowmap, process_background_shader)
|
||||||
|
.after(GltfComponentsSet::Injection),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
/// The properties of a light's shadow , to enable controlling per light shadows from Blender
|
||||||
|
pub struct BlenderLightShadows {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub buffer_bias: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The background color as described by Blender's [background shader](https://docs.blender.org/manual/en/latest/render/shader_nodes/shader/background.html).
|
||||||
|
#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct BlenderBackgroundShader {
|
||||||
|
pub color: Color,
|
||||||
|
pub strength: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The settings used by EEVEE's [shadow rendering](https://docs.blender.org/manual/en/latest/render/eevee/render_settings/shadows.html).
|
||||||
|
#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct BlenderShadowSettings {
|
||||||
|
pub cascade_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_lights(
|
||||||
|
mut directional_lights: Query<
|
||||||
|
(&mut DirectionalLight, Option<&BlenderLightShadows>),
|
||||||
|
Added<DirectionalLight>,
|
||||||
|
>,
|
||||||
|
mut spot_lights: Query<(&mut SpotLight, Option<&BlenderLightShadows>), Added<SpotLight>>,
|
||||||
|
mut point_lights: Query<(&mut PointLight, Option<&BlenderLightShadows>), Added<PointLight>>,
|
||||||
|
) {
|
||||||
|
for (mut light, blender_light_shadows) in directional_lights.iter_mut() {
|
||||||
|
if let Some(blender_light_shadows) = blender_light_shadows {
|
||||||
|
light.shadows_enabled = blender_light_shadows.enabled;
|
||||||
|
} else {
|
||||||
|
light.shadows_enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (mut light, blender_light_shadows) in spot_lights.iter_mut() {
|
||||||
|
if let Some(blender_light_shadows) = blender_light_shadows {
|
||||||
|
light.shadows_enabled = blender_light_shadows.enabled;
|
||||||
|
} else {
|
||||||
|
light.shadows_enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mut light, blender_light_shadows) in point_lights.iter_mut() {
|
||||||
|
if let Some(blender_light_shadows) = blender_light_shadows {
|
||||||
|
light.shadows_enabled = blender_light_shadows.enabled;
|
||||||
|
} else {
|
||||||
|
light.shadows_enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_shadowmap(
|
||||||
|
shadowmaps: Query<&BlenderShadowSettings, Added<BlenderShadowSettings>>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
for shadowmap in shadowmaps.iter() {
|
||||||
|
commands.insert_resource(DirectionalLightShadowMap {
|
||||||
|
size: shadowmap.cascade_size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_background_shader(
|
||||||
|
background_shaders: Query<&BlenderBackgroundShader, Added<BlenderBackgroundShader>>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
for background_shader in background_shaders.iter() {
|
||||||
|
commands.insert_resource(AmbientLight {
|
||||||
|
color: background_shader.color,
|
||||||
|
// Just a guess, see <https://github.com/bevyengine/bevy/issues/12280>
|
||||||
|
brightness: background_shader.strength * 400.0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
78
crates/blenvy/src/lib.rs
Normal file
78
crates/blenvy/src/lib.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
pub mod utils;
|
||||||
|
pub use utils::*;
|
||||||
|
|
||||||
|
pub mod ronstring_to_reflect_component;
|
||||||
|
pub use ronstring_to_reflect_component::*;
|
||||||
|
|
||||||
|
pub mod process_gltfs;
|
||||||
|
pub use process_gltfs::*;
|
||||||
|
|
||||||
|
pub mod blender_settings;
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
ecs::{component::Component, reflect::ReflectComponent, system::Resource},
|
||||||
|
prelude::{App, IntoSystemConfigs, Plugin, SystemSet, Update},
|
||||||
|
reflect::Reflect,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A Bevy plugin for extracting components from gltf files and automatically adding them to the relevant entities
|
||||||
|
/// It will automatically run every time you load a gltf file
|
||||||
|
/// Add this plugin to your Bevy app to get access to this feature
|
||||||
|
/// ```
|
||||||
|
/// # use bevy::prelude::*;
|
||||||
|
/// # use bevy::gltf::*;
|
||||||
|
/// # use bevy_gltf_components::ComponentsFromGltfPlugin;
|
||||||
|
///
|
||||||
|
/// //too barebones of an example to be meaningfull, please see https://github.com/kaosat-dev/Blender_bevy_components_workflow/examples/basic for a real example
|
||||||
|
/// fn main() {
|
||||||
|
/// App::new()
|
||||||
|
/// .add_plugins(DefaultPlugins)
|
||||||
|
/// .add_plugin(ComponentsFromGltfPlugin)
|
||||||
|
/// .add_system(spawn_level)
|
||||||
|
/// .run();
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn spawn_level(
|
||||||
|
/// asset_server: Res<AssetServer>,
|
||||||
|
/// mut commands: bevy::prelude::Commands,
|
||||||
|
/// keycode: Res<Input<KeyCode>>,
|
||||||
|
|
||||||
|
/// ){
|
||||||
|
/// if keycode.just_pressed(KeyCode::Return) {
|
||||||
|
/// commands.spawn(SceneBundle {
|
||||||
|
/// scene: asset_server.load("basic/models/level1.glb"),
|
||||||
|
/// transform: Transform::from_xyz(2.0, 0.0, -5.0),
|
||||||
|
/// ..Default::default()
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
///}
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
/// this is a flag component to tag a processed gltf, to avoid processing things multiple times
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct GltfProcessed;
|
||||||
|
|
||||||
|
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
||||||
|
/// systemset to order your systems after the component injection when needed
|
||||||
|
pub enum GltfComponentsSet {
|
||||||
|
Injection,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Resource)]
|
||||||
|
pub struct GltfComponentsConfig {}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ComponentsFromGltfPlugin {}
|
||||||
|
|
||||||
|
impl Plugin for ComponentsFromGltfPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_plugins(blender_settings::plugin)
|
||||||
|
.register_type::<GltfProcessed>()
|
||||||
|
.insert_resource(GltfComponentsConfig {})
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(add_components_from_gltf_extras).in_set(GltfComponentsSet::Injection),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
130
crates/blenvy/src/process_gltfs.rs
Normal file
130
crates/blenvy/src/process_gltfs.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
use bevy::{
|
||||||
|
core::Name,
|
||||||
|
ecs::{
|
||||||
|
entity::Entity,
|
||||||
|
query::{Added, Without},
|
||||||
|
reflect::{AppTypeRegistry, ReflectComponent},
|
||||||
|
world::World,
|
||||||
|
},
|
||||||
|
gltf::{GltfExtras, GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras},
|
||||||
|
hierarchy::Parent,
|
||||||
|
log::debug,
|
||||||
|
reflect::{Reflect, TypeRegistration},
|
||||||
|
utils::HashMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{ronstring_to_reflect_component, GltfProcessed};
|
||||||
|
|
||||||
|
fn bla_balb(entity: Entity, name: &Name, parent: &Parent, reflect_components: Vec<(Box<dyn Reflect>, TypeRegistration)>, mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>){
|
||||||
|
// we assign the components specified /xxx_components objects to their parent node
|
||||||
|
let mut target_entity = 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
|
||||||
|
// 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) {
|
||||||
|
let mut updated_components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new();
|
||||||
|
let current_components = &entity_components[&target_entity];
|
||||||
|
// first inject the current components
|
||||||
|
for (component, type_registration) in current_components {
|
||||||
|
updated_components.push((component.clone_value(), type_registration.clone()));
|
||||||
|
}
|
||||||
|
// then inject the new components: this also enables overwrite components set in the collection
|
||||||
|
for (component, type_registration) in reflect_components {
|
||||||
|
updated_components.push((component.clone_value(), type_registration));
|
||||||
|
}
|
||||||
|
entity_components.insert(target_entity, updated_components);
|
||||||
|
} else {
|
||||||
|
entity_components.insert(target_entity, reflect_components);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// main function: injects components into each entity in gltf files that have `gltf_extras`, using reflection
|
||||||
|
pub fn add_components_from_gltf_extras(world: &mut World) {
|
||||||
|
let mut extras =
|
||||||
|
world.query_filtered::<(Entity, &Name, &GltfExtras, &Parent), (Added<GltfExtras>, Without<GltfProcessed>)>();
|
||||||
|
|
||||||
|
let mut scene_extras = world.query_filtered::<(Entity, &Name, &GltfSceneExtras, &Parent), (Added<GltfSceneExtras>, Without<GltfProcessed>)>();
|
||||||
|
let mut mesh_extras = world.query_filtered::<(Entity, &Name, &GltfMeshExtras, &Parent), (Added<GltfMeshExtras>, Without<GltfProcessed>)>();
|
||||||
|
let mut material_extras = world.query_filtered::<(Entity, &Name, &GltfMaterialExtras, &Parent), (Added<GltfMaterialExtras>, Without<GltfProcessed>)>();
|
||||||
|
|
||||||
|
let mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>> =
|
||||||
|
HashMap::new();
|
||||||
|
|
||||||
|
// let gltf_components_config = world.resource::<GltfComponentsConfig>();
|
||||||
|
|
||||||
|
for (entity, name, extra, parent) in extras.iter(world) {
|
||||||
|
debug!(
|
||||||
|
"Name: {}, entity {:?}, parent: {:?}, extras {:?}",
|
||||||
|
name, entity, parent, extra
|
||||||
|
);
|
||||||
|
|
||||||
|
let type_registry: &AppTypeRegistry = world.resource();
|
||||||
|
let type_registry = type_registry.read();
|
||||||
|
let reflect_components = ronstring_to_reflect_component(&extra.value, &type_registry);
|
||||||
|
|
||||||
|
bla_balb(entity, name, parent, reflect_components, entity_components);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// we assign the components specified /xxx_components objects to their parent node
|
||||||
|
let mut target_entity = 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
|
||||||
|
// 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) {
|
||||||
|
let mut updated_components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new();
|
||||||
|
let current_components = &entity_components[&target_entity];
|
||||||
|
// first inject the current components
|
||||||
|
for (component, type_registration) in current_components {
|
||||||
|
updated_components.push((component.clone_value(), type_registration.clone()));
|
||||||
|
}
|
||||||
|
// then inject the new components: this also enables overwrite components set in the collection
|
||||||
|
for (component, type_registration) in reflect_components {
|
||||||
|
updated_components.push((component.clone_value(), type_registration));
|
||||||
|
}
|
||||||
|
entity_components.insert(target_entity, updated_components);
|
||||||
|
} else {
|
||||||
|
entity_components.insert(target_entity, reflect_components);
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
for (entity, components) in entity_components {
|
||||||
|
let type_registry: &AppTypeRegistry = world.resource();
|
||||||
|
let type_registry = type_registry.clone();
|
||||||
|
let type_registry = type_registry.read();
|
||||||
|
|
||||||
|
if !components.is_empty() {
|
||||||
|
debug!("--entity {:?}, components {}", entity, components.len());
|
||||||
|
}
|
||||||
|
for (component, type_registration) in components {
|
||||||
|
debug!(
|
||||||
|
"------adding {} {:?}",
|
||||||
|
component.get_represented_type_info().unwrap().type_path(),
|
||||||
|
component
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut entity_mut = world.entity_mut(entity);
|
||||||
|
type_registration
|
||||||
|
.data::<ReflectComponent>()
|
||||||
|
.expect("Unable to reflect component")
|
||||||
|
.insert(&mut entity_mut, &*component, &type_registry);
|
||||||
|
|
||||||
|
entity_mut.insert(GltfProcessed); // this is how can we insert any additional components
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
134
crates/blenvy/src/ronstring_to_reflect_component.rs
Normal file
134
crates/blenvy/src/ronstring_to_reflect_component.rs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
use bevy::log::{debug, warn};
|
||||||
|
use bevy::reflect::serde::ReflectDeserializer;
|
||||||
|
use bevy::reflect::{Reflect, TypeRegistration, TypeRegistry};
|
||||||
|
use bevy::utils::HashMap;
|
||||||
|
use ron::Value;
|
||||||
|
use serde::de::DeserializeSeed;
|
||||||
|
|
||||||
|
use super::capitalize_first_letter;
|
||||||
|
|
||||||
|
pub fn ronstring_to_reflect_component(
|
||||||
|
ron_string: &str,
|
||||||
|
type_registry: &TypeRegistry,
|
||||||
|
) -> Vec<(Box<dyn Reflect>, TypeRegistration)> {
|
||||||
|
let lookup: HashMap<String, Value> = ron::from_str(ron_string).unwrap();
|
||||||
|
let mut components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new();
|
||||||
|
// println!("ron_string {:?}", ron_string);
|
||||||
|
for (name, value) in lookup.into_iter() {
|
||||||
|
let parsed_value: String = match value.clone() {
|
||||||
|
Value::String(str) => {
|
||||||
|
str
|
||||||
|
}
|
||||||
|
_ => ron::to_string(&value).unwrap().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if name.as_str() == "bevy_components" {
|
||||||
|
bevy_components_string_to_components(parsed_value, type_registry, &mut components);
|
||||||
|
} else {
|
||||||
|
components_string_to_components(
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
parsed_value,
|
||||||
|
type_registry,
|
||||||
|
&mut components,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
components
|
||||||
|
}
|
||||||
|
|
||||||
|
fn components_string_to_components(
|
||||||
|
name: String,
|
||||||
|
value: Value,
|
||||||
|
parsed_value: String,
|
||||||
|
type_registry: &TypeRegistry,
|
||||||
|
components: &mut Vec<(Box<dyn Reflect>, TypeRegistration)>,
|
||||||
|
) {
|
||||||
|
let type_string = name.replace("component: ", "").trim().to_string();
|
||||||
|
let capitalized_type_name = capitalize_first_letter(type_string.as_str());
|
||||||
|
|
||||||
|
if let Some(type_registration) =
|
||||||
|
type_registry.get_with_short_type_path(capitalized_type_name.as_str())
|
||||||
|
{
|
||||||
|
debug!("TYPE INFO {:?}", type_registration.type_info());
|
||||||
|
|
||||||
|
let ron_string = format!(
|
||||||
|
"{{ \"{}\":{} }}",
|
||||||
|
type_registration.type_info().type_path(),
|
||||||
|
parsed_value
|
||||||
|
);
|
||||||
|
|
||||||
|
// usefull to determine what an entity looks like Serialized
|
||||||
|
/*let test_struct = CameraRenderGraph::new("name");
|
||||||
|
let serializer = ReflectSerializer::new(&test_struct, &type_registry);
|
||||||
|
let serialized =
|
||||||
|
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
|
||||||
|
println!("serialized Component {}", serialized);*/
|
||||||
|
|
||||||
|
debug!("component data ron string {}", ron_string);
|
||||||
|
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str())
|
||||||
|
.expect("deserialzer should have been generated from string");
|
||||||
|
let reflect_deserializer = ReflectDeserializer::new(type_registry);
|
||||||
|
let component = reflect_deserializer
|
||||||
|
.deserialize(&mut deserializer)
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
panic!(
|
||||||
|
"failed to deserialize component {} with value: {:?}",
|
||||||
|
name, value
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
debug!("component {:?}", component);
|
||||||
|
debug!("real type {:?}", component.get_represented_type_info());
|
||||||
|
components.push((component, type_registration.clone()));
|
||||||
|
debug!("found type registration for {}", capitalized_type_name);
|
||||||
|
} else {
|
||||||
|
warn!("no type registration for {}", capitalized_type_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bevy_components_string_to_components(
|
||||||
|
parsed_value: String,
|
||||||
|
type_registry: &TypeRegistry,
|
||||||
|
components: &mut Vec<(Box<dyn Reflect>, TypeRegistration)>,
|
||||||
|
) {
|
||||||
|
let lookup: HashMap<String, Value> = ron::from_str(&parsed_value).unwrap();
|
||||||
|
for (key, value) in lookup.into_iter() {
|
||||||
|
let parsed_value: String = match value.clone() {
|
||||||
|
Value::String(str) => {
|
||||||
|
str
|
||||||
|
}
|
||||||
|
_ => ron::to_string(&value).unwrap().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(type_registration) = type_registry.get_with_type_path(key.as_str()) {
|
||||||
|
debug!("TYPE INFO {:?}", type_registration.type_info());
|
||||||
|
|
||||||
|
let ron_string = format!(
|
||||||
|
"{{ \"{}\":{} }}",
|
||||||
|
type_registration.type_info().type_path(),
|
||||||
|
parsed_value
|
||||||
|
);
|
||||||
|
|
||||||
|
debug!("component data ron string {}", ron_string);
|
||||||
|
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str())
|
||||||
|
.expect("deserialzer should have been generated from string");
|
||||||
|
let reflect_deserializer = ReflectDeserializer::new(type_registry);
|
||||||
|
let component = reflect_deserializer
|
||||||
|
.deserialize(&mut deserializer)
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
panic!(
|
||||||
|
"failed to deserialize component {} with value: {:?}",
|
||||||
|
key, value
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
debug!("component {:?}", component);
|
||||||
|
debug!("real type {:?}", component.get_represented_type_info());
|
||||||
|
components.push((component, type_registration.clone()));
|
||||||
|
debug!("found type registration for {}", key);
|
||||||
|
} else {
|
||||||
|
warn!("no type registration for {}", key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
crates/blenvy/src/utils.rs
Normal file
3
crates/blenvy/src/utils.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub fn capitalize_first_letter(s: &str) -> String {
|
||||||
|
s[0..1].to_uppercase() + &s[1..]
|
||||||
|
}
|
@ -5,13 +5,14 @@ edition = "2021"
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.13", features = ["dynamic_linking"] }
|
bevy = { version = "0.14.0-rc.3", features = ["dynamic_linking"] }
|
||||||
bevy_gltf_blueprints = { path = "../../crates/bevy_gltf_blueprints" }
|
bevy_gltf_blueprints = { path = "../../crates/bevy_gltf_blueprints" }
|
||||||
bevy_registry_export = { path = "../../crates/bevy_registry_export" }
|
bevy_registry_export = { path = "../../crates/bevy_registry_export" }
|
||||||
bevy_gltf_worlflow_examples_common_rapier = { path = "../../examples/common_rapier" }
|
# bevy_gltf_worlflow_examples_common_rapier = { path = "../../examples/common_rapier" }
|
||||||
|
#bevy_gltf_worlflow_examples_common = { path = "../../examples/common" }
|
||||||
|
|
||||||
bevy_rapier3d = { version = "0.25.0", features = ["serde-serialize", "debug-render-3d", "enhanced-determinism"] }
|
#evy_rapier3d = { version = "0.25.0", features = ["serde-serialize", "debug-render-3d", "enhanced-determinism"] }
|
||||||
bevy_asset_loader = { version = "0.20", features = ["standard_dynamic_assets"] }
|
#bevy_asset_loader = { version = "0.20", features = ["standard_dynamic_assets"] }
|
||||||
bevy_editor_pls = { version = "0.8" }
|
#bevy_editor_pls = { version = "0.8" }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
json-writer ="0.3"
|
json-writer ="0.3"
|
@ -34,6 +34,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)>,
|
||||||
@ -225,7 +226,7 @@ pub fn play_animations(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
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,8 +1,8 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, BlueprintPath, GameWorldTag};
|
use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, BlueprintPath, GameWorldTag};
|
||||||
use bevy_gltf_worlflow_examples_common_rapier::{GameState, InAppRunning};
|
use crate::{GameState, InAppRunning};
|
||||||
|
|
||||||
use bevy_rapier3d::prelude::Velocity;
|
//use bevy_rapier3d::prelude::Velocity;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
pub fn setup_game(
|
pub fn setup_game(
|
||||||
@ -69,10 +69,10 @@ pub fn spawn_test(
|
|||||||
// BlueprintName("Health_Pickup".to_string()),
|
// BlueprintName("Health_Pickup".to_string()),
|
||||||
// SpawnHere,
|
// SpawnHere,
|
||||||
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),
|
||||||
angvel: Vec3::new(0.0, 0.0, 0.0),
|
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||||
},
|
},*/
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
commands.entity(world).add_child(new_entity);
|
commands.entity(world).add_child(new_entity);
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
pub mod animation;
|
|
||||||
pub mod in_game;
|
pub mod in_game;
|
||||||
pub use animation::*;
|
|
||||||
pub use in_game::*;
|
pub use in_game::*;
|
||||||
|
|
||||||
|
pub mod animation;
|
||||||
|
pub use animation::*;
|
||||||
|
|
||||||
use std::{collections::HashMap, fs, time::Duration};
|
use std::{collections::HashMap, fs, time::Duration};
|
||||||
|
|
||||||
use bevy_gltf_blueprints::{
|
use bevy_gltf_blueprints::{
|
||||||
@ -13,12 +14,14 @@ 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 bevy_gltf_worlflow_examples_common_rapier::{AppState, GameState};
|
use crate::{AppState, GameState};
|
||||||
|
|
||||||
use json_writer::to_json_string;
|
use json_writer::to_json_string;
|
||||||
|
|
||||||
fn start_game(mut next_app_state: ResMut<NextState<AppState>>) {
|
fn start_game(mut next_app_state: ResMut<NextState<AppState>>) {
|
||||||
next_app_state.set(AppState::AppLoading);
|
println!("START GAME");
|
||||||
|
//next_app_state.set(AppState::AppLoading);
|
||||||
|
next_app_state.set(AppState::AppRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the export from Blender worked correctly, we should have animations (simplified here by using AnimationPlayerLink)
|
// if the export from Blender worked correctly, we should have animations (simplified here by using AnimationPlayerLink)
|
||||||
@ -121,7 +124,7 @@ fn generate_screenshot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exit_game(mut app_exit_events: ResMut<Events<bevy::app::AppExit>>) {
|
fn exit_game(mut app_exit_events: ResMut<Events<bevy::app::AppExit>>) {
|
||||||
app_exit_events.send(bevy::app::AppExit);
|
app_exit_events.send(bevy::app::AppExit::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GamePlugin;
|
pub struct GamePlugin;
|
||||||
@ -134,16 +137,18 @@ impl Plugin for GamePlugin {
|
|||||||
|
|
||||||
.add_systems(Update, (spawn_test).run_if(in_state(GameState::InGame)))
|
.add_systems(Update, (spawn_test).run_if(in_state(GameState::InGame)))
|
||||||
.add_systems(Update, validate_export)
|
.add_systems(Update, validate_export)
|
||||||
|
//.add_systems(OnEnter(AppState::CoreLoading), start_game)
|
||||||
|
|
||||||
.add_systems(OnEnter(AppState::MenuRunning), start_game)
|
.add_systems(OnEnter(AppState::MenuRunning), start_game)
|
||||||
.add_systems(OnEnter(AppState::AppRunning), setup_game)
|
.add_systems(OnEnter(AppState::AppRunning), setup_game)
|
||||||
|
|
||||||
.add_systems(OnEnter(AppState::MenuRunning), setup_main_scene_animations)
|
.add_systems(OnEnter(AppState::MenuRunning), setup_main_scene_animations)
|
||||||
.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(
|
||||||
|
146
testing/bevy_example/src/hierarchy_debug.rs
Normal file
146
testing/bevy_example/src/hierarchy_debug.rs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
use bevy::{gltf::{GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras}, prelude::*};
|
||||||
|
use bevy_gltf_blueprints::{AllAssets, BlueprintInstanceReady};
|
||||||
|
|
||||||
|
use crate::BasicTest;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct HiearchyDebugTag;
|
||||||
|
|
||||||
|
pub fn setup_hierarchy_debug(mut commands: Commands, asset_server: Res<AssetServer>){
|
||||||
|
// a place to display the extras on screen
|
||||||
|
commands.spawn((
|
||||||
|
TextBundle::from_section(
|
||||||
|
"",
|
||||||
|
TextStyle {
|
||||||
|
color: LinearRgba { red: 1.0, green:0.0, blue: 0.0, alpha: 1.0}.into(),
|
||||||
|
font_size: 10.,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.with_style(Style {
|
||||||
|
position_type: PositionType::Absolute,
|
||||||
|
top: Val::Px(12.0),
|
||||||
|
left: Val::Px(12.0),
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
HiearchyDebugTag,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_descendants(
|
||||||
|
all_children: &Query<&Children>,
|
||||||
|
all_names:&Query<&Name>, root: &Entity,
|
||||||
|
nesting: usize,
|
||||||
|
to_check: &Query<&BasicTest>//&Query<(&BlueprintInstanceReady, &AllAssets)>,
|
||||||
|
)
|
||||||
|
-> String
|
||||||
|
{
|
||||||
|
|
||||||
|
let mut hierarchy_display: Vec<String> = vec![];
|
||||||
|
let root_name = all_names.get(*root);
|
||||||
|
let name;
|
||||||
|
if root_name.is_ok() {
|
||||||
|
name = root_name.unwrap().to_string();
|
||||||
|
}else {
|
||||||
|
name = "no_name".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
let components_to_check = to_check.get(*root);
|
||||||
|
|
||||||
|
hierarchy_display.push( format!("{}{} ({:?})", " ".repeat(nesting), name, components_to_check) ); //
|
||||||
|
|
||||||
|
|
||||||
|
if let Ok(children) = all_children.get(*root) {
|
||||||
|
|
||||||
|
for child in children.iter() {
|
||||||
|
|
||||||
|
let child_descendants_display = get_descendants(&all_children, &all_names, &child, nesting + 4, &to_check);
|
||||||
|
hierarchy_display.push(child_descendants_display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hierarchy_display.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_hierarchy_debug(
|
||||||
|
root: Query<(Entity, Option<&Name>, &Children), (Without<Parent>)>,
|
||||||
|
all_children: Query<&Children>,
|
||||||
|
all_names:Query<&Name>,
|
||||||
|
|
||||||
|
to_check: Query<&BasicTest>,//Query<(&BlueprintInstanceReady, &AllAssets)>,
|
||||||
|
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
||||||
|
){
|
||||||
|
let mut hierarchy_display: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for (root_entity, name, children) in root.iter() {
|
||||||
|
// hierarchy_display.push( format!("Hierarchy root{:?}", name) );
|
||||||
|
|
||||||
|
hierarchy_display.push(get_descendants(&all_children, &all_names, &root_entity, 0, &to_check));
|
||||||
|
// let mut children = all_children.get(root_entity);
|
||||||
|
/*for child in children.iter() {
|
||||||
|
// hierarchy_display
|
||||||
|
let name = all_names.get(*child); //.unwrap_or(&Name::new("no name"));
|
||||||
|
hierarchy_display.push(format!(" {:?}", name))
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
let mut display = display.single_mut();
|
||||||
|
display.sections[0].value = hierarchy_display.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////:just some testing for gltf extras
|
||||||
|
fn check_for_gltf_extras(
|
||||||
|
gltf_extras_per_entity: Query<(
|
||||||
|
Entity,
|
||||||
|
Option<&Name>,
|
||||||
|
Option<&GltfSceneExtras>,
|
||||||
|
Option<&GltfExtras>,
|
||||||
|
Option<&GltfMeshExtras>,
|
||||||
|
Option<&GltfMaterialExtras>,
|
||||||
|
)>,
|
||||||
|
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
||||||
|
) {
|
||||||
|
let mut gltf_extra_infos_lines: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for (id, name, scene_extras, extras, mesh_extras, material_extras) in
|
||||||
|
gltf_extras_per_entity.iter()
|
||||||
|
{
|
||||||
|
if scene_extras.is_some()
|
||||||
|
//|| extras.is_some()
|
||||||
|
|| mesh_extras.is_some()
|
||||||
|
|| material_extras.is_some()
|
||||||
|
{
|
||||||
|
let formatted_extras = format!(
|
||||||
|
"Extras per entity {} ('Name: {}'):
|
||||||
|
- scene extras: {:?}
|
||||||
|
- mesh extras: {:?}
|
||||||
|
- material extras: {:?}
|
||||||
|
",
|
||||||
|
id,
|
||||||
|
name.unwrap_or(&Name::default()),
|
||||||
|
scene_extras,
|
||||||
|
//extras,
|
||||||
|
mesh_extras,
|
||||||
|
material_extras
|
||||||
|
);
|
||||||
|
gltf_extra_infos_lines.push(formatted_extras);
|
||||||
|
}
|
||||||
|
let mut display = display.single_mut();
|
||||||
|
display.sections[0].value = gltf_extra_infos_lines.join("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HiearchyDebugPlugin;
|
||||||
|
impl Plugin for HiearchyDebugPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app
|
||||||
|
.add_systems(Startup, setup_hierarchy_debug)
|
||||||
|
.add_systems(Update, draw_hierarchy_debug)
|
||||||
|
//.add_systems(Update, check_for_gltf_extras)
|
||||||
|
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_gltf_worlflow_examples_common_rapier::CommonPlugin;
|
// use bevy_gltf_worlflow_examples_common::CommonPlugin;
|
||||||
|
mod state;
|
||||||
|
use state::*;
|
||||||
|
|
||||||
mod core;
|
mod core;
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
@ -11,12 +13,18 @@ mod dupe_components;
|
|||||||
mod test_components;
|
mod test_components;
|
||||||
use test_components::*;
|
use test_components::*;
|
||||||
|
|
||||||
|
mod hierarchy_debug;
|
||||||
|
use hierarchy_debug::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins.set(AssetPlugin::default()),
|
DefaultPlugins.set(AssetPlugin::default()),
|
||||||
|
|
||||||
|
HiearchyDebugPlugin,
|
||||||
// our custom plugins
|
// our custom plugins
|
||||||
CommonPlugin,
|
// CommonPlugin,
|
||||||
|
StatePlugin,
|
||||||
CorePlugin, // reusable plugins
|
CorePlugin, // reusable plugins
|
||||||
GamePlugin, // specific to our game
|
GamePlugin, // specific to our game
|
||||||
ComponentsTestPlugin, // Showcases different type of components /structs
|
ComponentsTestPlugin, // Showcases different type of components /structs
|
||||||
|
59
testing/bevy_example/src/state.rs
Normal file
59
testing/bevy_example/src/state.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
||||||
|
pub enum AppState {
|
||||||
|
CoreLoading,
|
||||||
|
#[default]
|
||||||
|
MenuRunning,
|
||||||
|
AppLoading,
|
||||||
|
AppRunning,
|
||||||
|
AppEnding,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
||||||
|
pub enum GameState {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
|
||||||
|
InMenu,
|
||||||
|
InGame,
|
||||||
|
|
||||||
|
InGameOver,
|
||||||
|
|
||||||
|
InSaving,
|
||||||
|
InLoading,
|
||||||
|
}
|
||||||
|
|
||||||
|
// tag components for all entities within a certain state (for despawning them if needed) , FIXME: seems kinda hack-ish
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct InCoreLoading;
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct InMenuRunning;
|
||||||
|
#[derive(Component)]
|
||||||
|
|
||||||
|
pub struct InAppRunning;
|
||||||
|
|
||||||
|
// components for tagging in game vs in game menu stuff
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct InMainMenu;
|
||||||
|
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct InMenu;
|
||||||
|
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct InGame;
|
||||||
|
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct InGameSaving;
|
||||||
|
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct InGameLoading;
|
||||||
|
|
||||||
|
pub struct StatePlugin;
|
||||||
|
impl Plugin for StatePlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app
|
||||||
|
.init_state::<AppState>()
|
||||||
|
.init_state::<GameState>();
|
||||||
|
}
|
||||||
|
}
|
@ -117,6 +117,10 @@ pub struct VecOfVec3s2(Vec<TupleVec3>);
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct VecOfColors(Vec<Color>);
|
pub struct VecOfColors(Vec<Color>);
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct VecOfUints(Vec<u32>);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct AAAAddedCOMPONENT;
|
pub struct AAAAddedCOMPONENT;
|
||||||
@ -196,6 +200,18 @@ pub struct ComponentAToFilterOut;
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct ComponentBToFilterOut;
|
pub struct ComponentBToFilterOut;
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct ComponentWithFieldsOfIdenticalType{
|
||||||
|
pub first: f32,
|
||||||
|
pub second: f32,
|
||||||
|
pub third: Vec<f32>,
|
||||||
|
pub fourth: Vec<f32>,
|
||||||
|
}
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct ComponentWithFieldsOfIdenticalType2(f32, f32, f32);
|
||||||
|
|
||||||
pub struct ComponentsTestPlugin;
|
pub struct ComponentsTestPlugin;
|
||||||
impl Plugin for ComponentsTestPlugin {
|
impl Plugin for ComponentsTestPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
@ -227,6 +243,9 @@ impl Plugin for ComponentsTestPlugin {
|
|||||||
.register_type::<Range<f32>>()
|
.register_type::<Range<f32>>()
|
||||||
.register_type::<VecOfF32s>()
|
.register_type::<VecOfF32s>()
|
||||||
.register_type::<Vec<f32>>()
|
.register_type::<Vec<f32>>()
|
||||||
|
.register_type::<u32>()
|
||||||
|
.register_type::<Vec<u32>>()
|
||||||
|
.register_type::<VecOfUints>()
|
||||||
// .register_type::<AAAAddedCOMPONENT>()
|
// .register_type::<AAAAddedCOMPONENT>()
|
||||||
.register_type::<AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut>()
|
.register_type::<AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut>()
|
||||||
.register_type::<HashMap<String, String>>()
|
.register_type::<HashMap<String, String>>()
|
||||||
@ -242,6 +261,9 @@ impl Plugin for ComponentsTestPlugin {
|
|||||||
.register_type::<HashmapTestStringColorFlat>()
|
.register_type::<HashmapTestStringColorFlat>()
|
||||||
.register_type::<ComponentAToFilterOut>()
|
.register_type::<ComponentAToFilterOut>()
|
||||||
.register_type::<ComponentBToFilterOut>()
|
.register_type::<ComponentBToFilterOut>()
|
||||||
|
.register_type::<ComponentWithFieldsOfIdenticalType>()
|
||||||
|
.register_type::<ComponentWithFieldsOfIdenticalType2>()
|
||||||
|
|
||||||
.add_plugins(MaterialPlugin::<
|
.add_plugins(MaterialPlugin::<
|
||||||
ExtendedMaterial<StandardMaterial, MyExtension>,
|
ExtendedMaterial<StandardMaterial, MyExtension>,
|
||||||
>::default());
|
>::default());
|
||||||
|
@ -95,7 +95,7 @@ Components:
|
|||||||
-> VERY likely due to the int-offset computation for hashes of components
|
-> VERY likely due to the int-offset computation for hashes of components
|
||||||
- now switched to tiger_hash
|
- now switched to tiger_hash
|
||||||
- [x] add warning about hash colision (not much we can/ could do if it is the case ?)
|
- [x] add warning about hash colision (not much we can/ could do if it is the case ?)
|
||||||
- [ ] double check weird collisions AND/OR reuse existing if applicable
|
- [x] double check weird collisions AND/OR reuse existing if applicable
|
||||||
|
|
||||||
- [x] annoying default path for registry, should be relative to the assets path
|
- [x] annoying default path for registry, should be relative to the assets path
|
||||||
|
|
||||||
@ -156,15 +156,20 @@ General issues:
|
|||||||
- [ ] rename project to Blenvy
|
- [ ] rename project to Blenvy
|
||||||
- [ ] replace all references to the old 2 add-ons with those to Blenvy
|
- [ ] replace all references to the old 2 add-ons with those to Blenvy
|
||||||
- [ ] rename repo to "Blenvy"
|
- [ ] rename repo to "Blenvy"
|
||||||
|
- [x] switch to bevy 0.14 rc2
|
||||||
|
- [ ] find a solution for the new color handling
|
||||||
|
- [ ] add back lighting_components
|
||||||
|
- [ ] check if scene components are being deleted through our scene re-orgs in the spawn post process
|
||||||
|
|
||||||
|
|
||||||
- [ ] simplify testing example:
|
- [ ] simplify testing example:
|
||||||
- [ ] remove use of rapier physics (or even the whole common boilerplate ?)
|
- [x] remove use of rapier physics (or even the whole common boilerplate ?)
|
||||||
- [ ] remove/replace bevy editor pls with some native ui to display hierarchies
|
- [ ] remove/replace bevy editor pls with some native ui to display hierarchies
|
||||||
- [ ] switch to bevy rc2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] simplify examples:
|
||||||
|
- [ ] a full fledged demo (including physics & co)
|
||||||
|
- [ ] other examples without interactions or physics
|
||||||
|
|
||||||
|
|
||||||
- [x] overall cleanup
|
- [x] overall cleanup
|
||||||
|
@ -20,23 +20,13 @@ def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_out
|
|||||||
temp_root_collection = temp_scene.collection
|
temp_root_collection = temp_scene.collection
|
||||||
|
|
||||||
print("additional_dataAAAAAAAAAAAAAAAH", additional_data)
|
print("additional_dataAAAAAAAAAAAAAAAH", additional_data)
|
||||||
|
properties_black_list = ['user_assets', 'components_meta']
|
||||||
if additional_data is not None: # FIXME not a fan of having this here
|
if additional_data is not None: # FIXME not a fan of having this here
|
||||||
for entry in dict(additional_data):
|
for entry in dict(additional_data):
|
||||||
print("entry in additional data", entry)
|
# we copy everything over except those on the black list
|
||||||
if entry == "local_assets":
|
if entry not in properties_black_list:
|
||||||
temp_scene["local_assets"] = additional_data[entry] # this is for bevy 0.14
|
print("entry in additional data", entry, "value", additional_data[entry], "in", additional_data.name)
|
||||||
temp_root_collection["local_assets"] = additional_data[entry] # for previous bevy versions, remove when migration done
|
temp_scene[entry] = additional_data[entry]
|
||||||
bla = "[(name: \"test_asset\", path: \"audio/fake.mp3\")]"
|
|
||||||
local_assets = additional_data.get(entry, [])
|
|
||||||
local_assets = [entry for entry in local_assets]
|
|
||||||
add_scene_property(temp_scene, 'assets_components', {"LocalAssets": f"LocalAssets({local_assets})".replace("'", '')})
|
|
||||||
|
|
||||||
if entry == entry == "AllAssets":
|
|
||||||
temp_scene["AllAssets"] = additional_data[entry]
|
|
||||||
temp_root_collection["AllAssets"] = additional_data[entry] # for previous bevy versions, remove when migration done
|
|
||||||
all_assets = additional_data.get(entry, [])
|
|
||||||
all_assets = [entry for entry in all_assets]
|
|
||||||
add_scene_property(temp_scene, 'assets_components', {"AllAssets": f"AllAssets({all_assets})".replace("'", '')})
|
|
||||||
|
|
||||||
# save active scene
|
# save active scene
|
||||||
active_scene = bpy.context.window.scene
|
active_scene = bpy.context.window.scene
|
||||||
@ -121,11 +111,11 @@ def clear_hollow_scene(temp_scene, original_root_collection):
|
|||||||
def restore_original_names(collection):
|
def restore_original_names(collection):
|
||||||
if collection.name.endswith("____bak"):
|
if collection.name.endswith("____bak"):
|
||||||
collection.name = collection.name.replace("____bak", "")
|
collection.name = collection.name.replace("____bak", "")
|
||||||
for object in collection.objects:
|
for object in collection.all_objects:
|
||||||
if object.instance_type == 'COLLECTION':
|
"""if object.instance_type == 'COLLECTION':
|
||||||
if object.name.endswith("____bak"):
|
if object.name.endswith("____bak"):
|
||||||
object.name = object.name.replace("____bak", "")
|
object.name = object.name.replace("____bak", "")
|
||||||
else:
|
else: """
|
||||||
if object.name.endswith("____bak"):
|
if object.name.endswith("____bak"):
|
||||||
object.name = object.name.replace("____bak", "")
|
object.name = object.name.replace("____bak", "")
|
||||||
for child_collection in collection.children:
|
for child_collection in collection.children:
|
||||||
|
@ -5,32 +5,33 @@ from blenvy.core.object_makers import make_empty
|
|||||||
# TODO: replace this with placing scene level custom properties once support for that has been added to bevy_gltf
|
# TODO: replace this with placing scene level custom properties once support for that has been added to bevy_gltf
|
||||||
def upsert_scene_components(main_scenes):
|
def upsert_scene_components(main_scenes):
|
||||||
for scene in main_scenes:
|
for scene in main_scenes:
|
||||||
lighting_components_name = f"lighting_components_{scene.name}"
|
"""lighting_components_name = f"lighting_components_{scene.name}"
|
||||||
lighting_components = bpy.data.objects.get(lighting_components_name, None)
|
lighting_components = bpy.data.objects.get(lighting_components_name, None)
|
||||||
if not lighting_components:
|
if not lighting_components:
|
||||||
root_collection = scene.collection
|
root_collection = scene.collection
|
||||||
lighting_components = make_empty('lighting_components_'+scene.name, [0,0,0], [0,0,0], [0,0,0], root_collection)
|
lighting_components = make_empty('lighting_components_'+scene.name, [0,0,0], [0,0,0], [0,0,0], root_collection)"""
|
||||||
|
|
||||||
if scene.world is not None:
|
"""if scene.world is not None:
|
||||||
lighting_components['BlenderBackgroundShader'] = ambient_color_to_component(scene.world)
|
lighting_components['BlenderBackgroundShader'] = ambient_color_to_component(scene.world)""" # FIXME add back
|
||||||
lighting_components['BlenderShadowSettings'] = scene_shadows_to_component(scene)
|
scene['BlenderShadowSettings'] = scene_shadows_to_component(scene)
|
||||||
|
|
||||||
if scene.eevee.use_bloom:
|
if scene.eevee.use_bloom:
|
||||||
lighting_components['BloomSettings'] = scene_bloom_to_component(scene)
|
scene['BloomSettings'] = scene_bloom_to_component(scene)
|
||||||
elif 'BloomSettings' in lighting_components:
|
elif 'BloomSettings' in scene:
|
||||||
del lighting_components['BloomSettings']
|
del scene['BloomSettings']
|
||||||
|
|
||||||
if scene.eevee.use_gtao:
|
if scene.eevee.use_gtao:
|
||||||
lighting_components['SSAOSettings'] = scene_ao_to_component(scene)
|
scene['SSAOSettings'] = scene_ao_to_component(scene)
|
||||||
elif 'SSAOSettings' in lighting_components:
|
elif 'SSAOSettings' in scene:
|
||||||
del lighting_components['SSAOSettings']
|
del scene['SSAOSettings']
|
||||||
|
|
||||||
def remove_scene_components(main_scenes):
|
def remove_scene_components(main_scenes):
|
||||||
for scene in main_scenes:
|
pass
|
||||||
|
"""for scene in main_scenes:
|
||||||
lighting_components_name = f"lighting_components_{scene.name}"
|
lighting_components_name = f"lighting_components_{scene.name}"
|
||||||
lighting_components = bpy.data.objects.get(lighting_components_name, None)
|
lighting_components = bpy.data.objects.get(lighting_components_name, None)
|
||||||
if lighting_components:
|
if lighting_components:
|
||||||
bpy.data.objects.remove(lighting_components, do_unlink=True)
|
bpy.data.objects.remove(lighting_components, do_unlink=True)"""
|
||||||
|
|
||||||
|
|
||||||
def ambient_color_to_component(world):
|
def ambient_color_to_component(world):
|
||||||
@ -44,7 +45,7 @@ def ambient_color_to_component(world):
|
|||||||
|
|
||||||
|
|
||||||
if color is not None and strength is not None:
|
if color is not None and strength is not None:
|
||||||
colorRgba = f"Rgba(red: {color[0]}, green: {color[1]}, blue: {color[2]}, alpha: {color[3]})"
|
colorRgba = f"LinearRgba(red: {color[0]}, green: {color[1]}, blue: {color[2]}, alpha: {color[3]})"
|
||||||
component = f"( color: {colorRgba}, strength: {strength})"
|
component = f"( color: {colorRgba}, strength: {strength})"
|
||||||
return component
|
return component
|
||||||
return None
|
return None
|
||||||
|
@ -220,7 +220,7 @@ def upsert_component_in_item(item, long_name, registry):
|
|||||||
if property_group_name in registry.component_propertyGroups:
|
if property_group_name in registry.component_propertyGroups:
|
||||||
# we have found a matching property_group, so try to inject it
|
# we have found a matching property_group, so try to inject it
|
||||||
# now inject property group
|
# now inject property group
|
||||||
setattr(ComponentMetadata, property_group_name, registry.component_propertyGroups[property_group_name]) # FIXME: not ideal as all ComponentMetadata get the propGroup, but have not found a way to assign it per instance
|
setattr(ComponentMetadata, property_group_name, registry.component_propertyGroups[property_group_name]) # FIXME: not ideal as ALL instances of ComponentMetadata get the propGroup, but have not found a way to assign it per instance
|
||||||
propertyGroup = getattr(component_meta, property_group_name, None)
|
propertyGroup = getattr(component_meta, property_group_name, None)
|
||||||
|
|
||||||
# now deal with property groups details
|
# now deal with property groups details
|
||||||
|
@ -30,13 +30,14 @@ def process_component(registry, definition, update, extras=None, nesting_long_na
|
|||||||
with_list = False
|
with_list = False
|
||||||
with_map = False
|
with_map = False
|
||||||
|
|
||||||
padding = " " * (len(nesting_long_names) + 1)
|
#padding = " " * (len(nesting_long_names) + 1)
|
||||||
#print(f"{padding}process component", long_name, "nesting_long_names",nesting_long_names, "foo", has_properties, has_prefixItems, is_enum, is_list, is_map)
|
#print(f"{padding}process component", long_name, "nesting_long_names",nesting_long_names, "foo", has_properties, has_prefixItems, is_enum, is_list, is_map)
|
||||||
|
|
||||||
if has_properties:
|
if has_properties:
|
||||||
__annotations__ = __annotations__ | process_structs.process_structs(registry, definition, properties, update, nesting_long_names)
|
__annotations__ = __annotations__ | process_structs.process_structs(registry, definition, properties, update, nesting_long_names)
|
||||||
with_properties = True
|
with_properties = True
|
||||||
tupple_or_struct = "struct"
|
tupple_or_struct = "struct"
|
||||||
|
#print(f"{padding}struct")
|
||||||
|
|
||||||
if has_prefixItems:
|
if has_prefixItems:
|
||||||
__annotations__ = __annotations__ | process_tupples.process_tupples(registry, definition, prefixItems, update, nesting_long_names)
|
__annotations__ = __annotations__ | process_tupples.process_tupples(registry, definition, prefixItems, update, nesting_long_names)
|
||||||
@ -61,7 +62,6 @@ def process_component(registry, definition, update, extras=None, nesting_long_na
|
|||||||
for a in __annotations__:
|
for a in __annotations__:
|
||||||
field_names.append(a)
|
field_names.append(a)
|
||||||
|
|
||||||
|
|
||||||
extras = extras if extras is not None else {
|
extras = extras if extras is not None else {
|
||||||
"long_name": long_name
|
"long_name": long_name
|
||||||
}
|
}
|
||||||
@ -78,25 +78,16 @@ def process_component(registry, definition, update, extras=None, nesting_long_na
|
|||||||
**dict(with_properties = with_properties, with_items= with_items, with_enum= with_enum, with_list= with_list, with_map = with_map, short_name= short_name, long_name=long_name),
|
**dict(with_properties = with_properties, with_items= with_items, with_enum= with_enum, with_list= with_list, with_map = with_map, short_name= short_name, long_name=long_name),
|
||||||
'root_component': root_component
|
'root_component': root_component
|
||||||
}
|
}
|
||||||
#FIXME: YIKES, but have not found another way:
|
|
||||||
""" Withouth this ; the following does not work
|
# we need to pass the full hierarchy to disambiguate between components
|
||||||
|
# Withouth this ; the following does not work
|
||||||
|
"""
|
||||||
-BasicTest
|
-BasicTest
|
||||||
- NestingTestLevel2
|
- NestingTestLevel2
|
||||||
-BasicTest => the registration & update callback of this one overwrites the first "basicTest"
|
-BasicTest => the registration & update callback of this one overwrites the first "basicTest"
|
||||||
have not found a cleaner workaround so far
|
|
||||||
"""
|
"""
|
||||||
property_group_name = registry.generate_propGroup_name(nesting_long_names)
|
|
||||||
(property_group_pointer, property_group_class) = property_group_from_infos(property_group_name, property_group_params)
|
|
||||||
# add our component propertyGroup to the registry
|
# add our component propertyGroup to the registry
|
||||||
registry.register_component_propertyGroup(property_group_name, property_group_pointer)
|
(property_group_pointer, property_group_class) = registry.register_component_propertyGroup(nesting_long_names, property_group_params)
|
||||||
|
|
||||||
return (property_group_pointer, property_group_class)
|
return (property_group_pointer, property_group_class)
|
||||||
|
|
||||||
def property_group_from_infos(property_group_name, property_group_parameters):
|
|
||||||
# print("creating property group", property_group_name)
|
|
||||||
property_group_class = type(property_group_name, (PropertyGroup,), property_group_parameters)
|
|
||||||
|
|
||||||
bpy.utils.register_class(property_group_class)
|
|
||||||
property_group_pointer = PointerProperty(type=property_group_class)
|
|
||||||
|
|
||||||
return (property_group_pointer, property_group_class)
|
|
@ -33,7 +33,7 @@ def process_structs(registry, definition, properties, update, nesting_long_names
|
|||||||
__annotations__[property_name] = blender_property
|
__annotations__[property_name] = blender_property
|
||||||
else:
|
else:
|
||||||
original_long_name = original["long_name"]
|
original_long_name = original["long_name"]
|
||||||
(sub_component_group, _) = process_component.process_component(registry, original, update, {"nested": True, "long_name": original_long_name}, nesting_long_names)
|
(sub_component_group, _) = process_component.process_component(registry, original, update, {"nested": True, "long_name": original_long_name}, nesting_long_names+[property_name])
|
||||||
__annotations__[property_name] = sub_component_group
|
__annotations__[property_name] = sub_component_group
|
||||||
# if there are sub fields, add an attribute "sub_fields" possibly a pointer property ? or add a standard field to the type , that is stored under "attributes" and not __annotations (better)
|
# if there are sub fields, add an attribute "sub_fields" possibly a pointer property ? or add a standard field to the type , that is stored under "attributes" and not __annotations (better)
|
||||||
else:
|
else:
|
||||||
|
@ -34,12 +34,10 @@ def generate_propertyGroups_for_components():
|
|||||||
|
|
||||||
type_infos = registry.type_infos
|
type_infos = registry.type_infos
|
||||||
|
|
||||||
for component_name in type_infos:
|
for root_type_name in type_infos:
|
||||||
definition = type_infos[component_name]
|
definition = type_infos[root_type_name]
|
||||||
is_component = definition['isComponent'] if "isComponent" in definition else False
|
#print("root property", component_name,f"({is_component})")
|
||||||
root_property_name = component_name# if is_component else None
|
process_component(registry, definition, update_calback_helper(definition, update_component, root_type_name), extras=None, nesting_long_names=[])
|
||||||
print("root property", component_name,f"({is_component})")
|
|
||||||
process_component(registry, definition, update_calback_helper(definition, update_component, root_property_name), extras=None, nesting_long_names=[])
|
|
||||||
|
|
||||||
# if we had to add any wrapper types on the fly, process them now
|
# if we had to add any wrapper types on the fly, process them now
|
||||||
registry.process_custom_types()
|
registry.process_custom_types()
|
@ -7,6 +7,8 @@ from bpy_types import (PropertyGroup)
|
|||||||
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
from bpy.props import (StringProperty, BoolProperty, FloatProperty, FloatVectorProperty, IntProperty, IntVectorProperty, EnumProperty, PointerProperty, CollectionProperty)
|
||||||
from ..components.metadata import ComponentMetadata
|
from ..components.metadata import ComponentMetadata
|
||||||
from .hashing.tiger import hash as tiger_hash
|
from .hashing.tiger import hash as tiger_hash
|
||||||
|
|
||||||
|
|
||||||
# helper class to store missing bevy types information
|
# helper class to store missing bevy types information
|
||||||
class MissingBevyType(bpy.types.PropertyGroup):
|
class MissingBevyType(bpy.types.PropertyGroup):
|
||||||
long_name: bpy.props.StringProperty(
|
long_name: bpy.props.StringProperty(
|
||||||
@ -14,6 +16,15 @@ class MissingBevyType(bpy.types.PropertyGroup):
|
|||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
def property_group_from_infos(property_group_name, property_group_parameters):
|
||||||
|
# print("creating property group", property_group_name)
|
||||||
|
property_group_class = type(property_group_name, (PropertyGroup,), property_group_parameters)
|
||||||
|
|
||||||
|
bpy.utils.register_class(property_group_class)
|
||||||
|
property_group_pointer = PointerProperty(type=property_group_class)
|
||||||
|
|
||||||
|
return (property_group_pointer, property_group_class)
|
||||||
|
|
||||||
# this is where we store the information for all available components
|
# this is where we store the information for all available components
|
||||||
class ComponentsRegistry(PropertyGroup):
|
class ComponentsRegistry(PropertyGroup):
|
||||||
registry: bpy.props. StringProperty(
|
registry: bpy.props. StringProperty(
|
||||||
@ -140,6 +151,8 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
type_infos = {}
|
type_infos = {}
|
||||||
type_infos_missing = []
|
type_infos_missing = []
|
||||||
component_propertyGroups = {}
|
component_propertyGroups = {}
|
||||||
|
component_property_group_classes = []
|
||||||
|
|
||||||
custom_types_to_add = {}
|
custom_types_to_add = {}
|
||||||
invalid_components = []
|
invalid_components = []
|
||||||
|
|
||||||
@ -152,8 +165,18 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
for propgroup_name in cls.component_propertyGroups.keys():
|
for propgroup_name in cls.component_propertyGroups.keys():
|
||||||
try:
|
try:
|
||||||
delattr(ComponentMetadata, propgroup_name)
|
delattr(ComponentMetadata, propgroup_name)
|
||||||
|
#print("sucess REMOVAL from Metadata")
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
pass
|
pass
|
||||||
|
#print("failed to unregister")
|
||||||
|
|
||||||
|
for propgroup_class in cls.component_property_group_classes:
|
||||||
|
try:
|
||||||
|
bpy.utils.unregister_class(propgroup_class)
|
||||||
|
#print("sucess UNREGISTER")
|
||||||
|
except Exception as error:
|
||||||
|
pass
|
||||||
|
#print("NEW failed to unregister")
|
||||||
|
|
||||||
del bpy.types.WindowManager.components_registry
|
del bpy.types.WindowManager.components_registry
|
||||||
|
|
||||||
@ -167,7 +190,10 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
self.missing_types_list.clear()
|
self.missing_types_list.clear()
|
||||||
self.type_infos.clear()
|
self.type_infos.clear()
|
||||||
self.type_infos_missing.clear()
|
self.type_infos_missing.clear()
|
||||||
|
|
||||||
self.component_propertyGroups.clear()
|
self.component_propertyGroups.clear()
|
||||||
|
self.component_property_group_classes.clear()
|
||||||
|
|
||||||
self.custom_types_to_add.clear()
|
self.custom_types_to_add.clear()
|
||||||
self.invalid_components.clear()
|
self.invalid_components.clear()
|
||||||
# now prepare paths to load data
|
# now prepare paths to load data
|
||||||
@ -188,10 +214,6 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
def has_type_infos(self):
|
def has_type_infos(self):
|
||||||
return len(self.type_infos.keys()) != 0
|
return len(self.type_infos.keys()) != 0
|
||||||
|
|
||||||
# we keep a list of component propertyGroup around
|
|
||||||
def register_component_propertyGroup(self, name, propertyGroup):
|
|
||||||
self.component_propertyGroups[name] = propertyGroup
|
|
||||||
|
|
||||||
# to be able to give the user more feedback on any missin/unregistered types in their schema file
|
# to be able to give the user more feedback on any missin/unregistered types in their schema file
|
||||||
def add_missing_typeInfo(self, long_name):
|
def add_missing_typeInfo(self, long_name):
|
||||||
if not long_name in self.type_infos_missing:
|
if not long_name in self.type_infos_missing:
|
||||||
@ -217,18 +239,25 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
|
|
||||||
long_names_to_propgroup_names = {}
|
long_names_to_propgroup_names = {}
|
||||||
|
|
||||||
|
# we keep a list of component propertyGroup around
|
||||||
|
def register_component_propertyGroup(self, nesting, property_group_params):
|
||||||
|
property_group_name = self.generate_propGroup_name(nesting)
|
||||||
|
(property_group_pointer, property_group_class) = property_group_from_infos(property_group_name, property_group_params)
|
||||||
|
self.component_propertyGroups[property_group_name] = property_group_pointer
|
||||||
|
self.component_property_group_classes.append(property_group_class)
|
||||||
|
|
||||||
|
return (property_group_pointer, property_group_class)
|
||||||
|
|
||||||
# generate propGroup name from nesting level: each longName + nesting is unique
|
# generate propGroup name from nesting level: each longName + nesting is unique
|
||||||
def generate_propGroup_name(self, nesting):
|
def generate_propGroup_name(self, nesting):
|
||||||
#print("gen propGroup name for", shortName, nesting)
|
|
||||||
key = str(nesting)
|
key = str(nesting)
|
||||||
|
|
||||||
propGroupHash = tiger_hash(key)
|
propGroupHash = tiger_hash(key)
|
||||||
propGroupName = propGroupHash + "_ui"
|
propGroupName = propGroupHash + "_ui"
|
||||||
|
|
||||||
# check for collision
|
# check for collision
|
||||||
padding = " " * (len(nesting) + 1)
|
#padding = " " * (len(nesting) + 1)
|
||||||
|
#print(f"{padding}--computing hash for", nesting)
|
||||||
print(f"{padding}--computing hash for", nesting)
|
|
||||||
if propGroupName in self.long_names_to_propgroup_names.values():
|
if propGroupName in self.long_names_to_propgroup_names.values():
|
||||||
print(" WARNING !! you have a collision between the hash of multiple component names: collision for", nesting)
|
print(" WARNING !! you have a collision between the hash of multiple component names: collision for", nesting)
|
||||||
|
|
||||||
@ -239,7 +268,6 @@ class ComponentsRegistry(PropertyGroup):
|
|||||||
def get_propertyGroupName_from_longName(self, longName):
|
def get_propertyGroupName_from_longName(self, longName):
|
||||||
return self.long_names_to_propgroup_names.get(str([longName]), None)
|
return self.long_names_to_propgroup_names.get(str([longName]), None)
|
||||||
|
|
||||||
|
|
||||||
###########
|
###########
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user