Compare commits

...

7 Commits

Author SHA1 Message Date
kaosat.dev
310ee194a9 chore(): cargo fmt 2024-05-07 00:40:47 +02:00
kaosat.dev
c27bfb839e chore(bevy_components): cleanups 2024-05-07 00:39:15 +02:00
kaosat.dev
03c3d397a7 feat(bevy_components): lot more cleanups & fixes
* fixed issues with initial insertion of map key/value pairs
 * overhauled & upgraded tests
 * changed internals of rename components
 * cleanups everwhere !
 * tweaks & minor improvements all around
2024-05-07 00:22:33 +02:00
kaosat.dev
7e6805f221 chore(testing): added example of filtered out components 2024-05-06 14:35:57 +02:00
kaosat.dev
664e04b05c chore(testing): updated registry 2024-05-06 14:35:19 +02:00
kaosat.dev
3154b8e8c7 feat(bevy_registry_export):
* added key & value type information for maps/hashmaps
 * added filtering out of components/resources
2024-05-06 14:34:23 +02:00
kaosat.dev
e7e680b92c tests(bevy_components): migrating tests to new apis 2024-05-05 22:43:49 +02:00
25 changed files with 946 additions and 803 deletions

View File

@ -15,8 +15,6 @@ pub fn ronstring_to_reflect_component(
let mut components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new(); let mut components: Vec<(Box<dyn Reflect>, TypeRegistration)> = Vec::new();
// 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; let parsed_value: String;
match value.clone() { match value.clone() {
Value::String(str) => { Value::String(str) => {
@ -28,7 +26,13 @@ pub fn ronstring_to_reflect_component(
if name.as_str() == "bevy_components" { if name.as_str() == "bevy_components" {
bevy_components_string_to_components(parsed_value, type_registry, &mut components) bevy_components_string_to_components(parsed_value, type_registry, &mut components)
} else { } else {
components_string_to_components(name, value, parsed_value, type_registry, &mut components) components_string_to_components(
name,
value,
parsed_value,
type_registry,
&mut components,
)
} }
} }
components components
@ -39,8 +43,8 @@ fn components_string_to_components(
value: Value, value: Value,
parsed_value: String, parsed_value: String,
type_registry: &TypeRegistry, type_registry: &TypeRegistry,
components: &mut Vec<(Box<dyn Reflect>, TypeRegistration)> components: &mut Vec<(Box<dyn Reflect>, TypeRegistration)>,
){ ) {
let type_string = name.replace("component: ", "").trim().to_string(); let type_string = name.replace("component: ", "").trim().to_string();
let capitalized_type_name = capitalize_first_letter(type_string.as_str()); let capitalized_type_name = capitalize_first_letter(type_string.as_str());
@ -87,8 +91,8 @@ fn components_string_to_components(
fn bevy_components_string_to_components( fn bevy_components_string_to_components(
parsed_value: String, parsed_value: String,
type_registry: &TypeRegistry, type_registry: &TypeRegistry,
components: &mut Vec<(Box<dyn Reflect>, TypeRegistration)> components: &mut Vec<(Box<dyn Reflect>, TypeRegistration)>,
){ ) {
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; let parsed_value: String;
@ -99,9 +103,7 @@ fn bevy_components_string_to_components(
_ => parsed_value = ron::to_string(&value).unwrap().to_string(), _ => parsed_value = ron::to_string(&value).unwrap().to_string(),
} }
if let Some(type_registration) = if let Some(type_registration) = type_registry.get_with_type_path(key.as_str()) {
type_registry.get_with_type_path(key.as_str())
{
debug!("TYPE INFO {:?}", type_registration.type_info()); debug!("TYPE INFO {:?}", type_registration.type_info());
let ron_string = format!( let ron_string = format!(

View File

@ -20,9 +20,20 @@ pub fn export_types(world: &mut World) {
println!("registry_save_path {}", registry_save_path.display()); println!("registry_save_path {}", registry_save_path.display());
let writer = File::create(registry_save_path).expect("should have created schema file"); let writer = File::create(registry_save_path).expect("should have created schema file");
let components_to_filter_out = &config.component_filter.clone();
let resources_to_filter_out = &config.resource_filter.clone();
let types = world.resource_mut::<AppTypeRegistry>(); let types = world.resource_mut::<AppTypeRegistry>();
let types = types.read(); let types = types.read();
let schemas = types.iter().map(export_type).collect::<Map<_, _>>(); let schemas = types
.iter()
.filter(|type_info| {
let type_id = type_info.type_id();
return components_to_filter_out.is_allowed_by_id(type_id)
&& resources_to_filter_out.is_allowed_by_id(type_id);
})
.map(export_type)
.collect::<Map<_, _>>();
serde_json::to_writer_pretty( serde_json::to_writer_pretty(
writer, writer,
@ -41,7 +52,6 @@ pub fn export_type(reg: &TypeRegistration) -> (String, Value) {
let t = reg.type_info(); let t = reg.type_info();
let binding = t.type_path_table(); let binding = t.type_path_table();
let short_name = binding.short_path(); let short_name = binding.short_path();
println!("T YOOO {:?}", t);
let mut schema = match t { let mut schema = match t {
TypeInfo::Struct(info) => { TypeInfo::Struct(info) => {
let properties = info let properties = info
@ -164,7 +174,8 @@ pub fn export_type(reg: &TypeRegistration) -> (String, Value) {
"long_name": t.type_path(), "long_name": t.type_path(),
"type": "object", "type": "object",
"typeInfo": "Map", "typeInfo": "Map",
"additionalProperties": json!({"type": typ(info.value_type_path_table().path())}), "valueType": json!({"type": typ(info.value_type_path_table().path())}),
"keyType": json!({"type": typ(info.key_type_path_table().path())}),
}), }),
TypeInfo::Tuple(info) => json!({ TypeInfo::Tuple(info) => json!({
"long_name": t.type_path(), "long_name": t.type_path(),

View File

@ -16,9 +16,9 @@ use bevy::{
pub struct ExportComponentsConfig { pub struct ExportComponentsConfig {
pub(crate) save_path: PathBuf, pub(crate) save_path: PathBuf,
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) component_filter: SceneFilter, // unused for now pub(crate) component_filter: SceneFilter,
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) resource_filter: SceneFilter, // unused for now pub(crate) resource_filter: SceneFilter,
} }
pub struct ExportRegistryPlugin { pub struct ExportRegistryPlugin {
@ -30,8 +30,8 @@ pub struct ExportRegistryPlugin {
impl Default for ExportRegistryPlugin { impl Default for ExportRegistryPlugin {
fn default() -> Self { fn default() -> Self {
Self { Self {
component_filter: SceneFilter::default(), // unused for now component_filter: SceneFilter::default(),
resource_filter: SceneFilter::default(), // unused for now resource_filter: SceneFilter::default(),
save_path: PathBuf::from("registry.json"), // relative to assets folder save_path: PathBuf::from("registry.json"), // relative to assets folder
} }
} }

View File

@ -11138,108 +11138,148 @@
"typeInfo": "Value" "typeInfo": "Value"
}, },
"bevy_utils::hashbrown::HashMap<alloc::string::String, alloc::string::String, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": { "bevy_utils::hashbrown::HashMap<alloc::string::String, alloc::string::String, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"additionalProperties": { "isComponent": false,
"isResource": false,
"keyType": {
"type": { "type": {
"$ref": "#/$defs/alloc::string::String" "$ref": "#/$defs/alloc::string::String"
} }
}, },
"isComponent": false,
"isResource": false,
"long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, alloc::string::String, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>", "long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, alloc::string::String, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<String, String, DefaultHashBuilder>", "short_name": "HashMap<String, String, DefaultHashBuilder>",
"type": "object", "type": "object",
"typeInfo": "Map" "typeInfo": "Map",
"valueType": {
"type": {
"$ref": "#/$defs/alloc::string::String"
}
}
}, },
"bevy_utils::hashbrown::HashMap<alloc::string::String, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": { "bevy_utils::hashbrown::HashMap<alloc::string::String, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"additionalProperties": {
"type": {
"$ref": "#/$defs/alloc::vec::Vec<alloc::string::String>"
}
},
"isComponent": false, "isComponent": false,
"isResource": false, "isResource": false,
"long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>", "keyType": {
"short_name": "HashMap<String, Vec<String>, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map"
},
"bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_render::color::Color, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"additionalProperties": {
"type": {
"$ref": "#/$defs/bevy_render::color::Color"
}
},
"isComponent": false,
"isResource": false,
"long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_render::color::Color, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<String, Color, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map"
},
"bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"additionalProperties": {
"type": {
"$ref": "#/$defs/bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>"
}
},
"isComponent": false,
"isResource": false,
"long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<String, HashMap<u32, Vec<String>, DefaultHashBuilder>, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map"
},
"bevy_utils::hashbrown::HashMap<alloc::string::String, f32, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"additionalProperties": {
"type": {
"$ref": "#/$defs/f32"
}
},
"isComponent": false,
"isResource": false,
"long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, f32, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<String, f32, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map"
},
"bevy_utils::hashbrown::HashMap<u32, alloc::string::String, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"additionalProperties": {
"type": { "type": {
"$ref": "#/$defs/alloc::string::String" "$ref": "#/$defs/alloc::string::String"
} }
}, },
"isComponent": false, "long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"isResource": false, "short_name": "HashMap<String, Vec<String>, DefaultHashBuilder>",
"long_name": "bevy_utils::hashbrown::HashMap<u32, alloc::string::String, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<u32, String, DefaultHashBuilder>",
"type": "object", "type": "object",
"typeInfo": "Map" "typeInfo": "Map",
}, "valueType": {
"bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"additionalProperties": {
"type": { "type": {
"$ref": "#/$defs/alloc::vec::Vec<alloc::string::String>" "$ref": "#/$defs/alloc::vec::Vec<alloc::string::String>"
} }
}
}, },
"bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_render::color::Color, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"isComponent": false, "isComponent": false,
"isResource": false, "isResource": false,
"long_name": "bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>", "keyType": {
"short_name": "HashMap<u32, Vec<String>, DefaultHashBuilder>", "type": {
"type": "object", "$ref": "#/$defs/alloc::string::String"
"typeInfo": "Map" }
}, },
"bevy_utils::hashbrown::HashMap<u32, bevy_render::color::Color, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": { "long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_render::color::Color, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"additionalProperties": { "short_name": "HashMap<String, Color, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map",
"valueType": {
"type": { "type": {
"$ref": "#/$defs/bevy_render::color::Color" "$ref": "#/$defs/bevy_render::color::Color"
} }
}
}, },
"bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"isComponent": false, "isComponent": false,
"isResource": false, "isResource": false,
"keyType": {
"type": {
"$ref": "#/$defs/alloc::string::String"
}
},
"long_name": "bevy_utils::hashbrown::HashMap<alloc::string::String, bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<String, HashMap<u32, Vec<String>, DefaultHashBuilder>, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map",
"valueType": {
"type": {
"$ref": "#/$defs/bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>"
}
}
},
"bevy_utils::hashbrown::HashMap<alloc::string::String, f32, 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, f32, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<String, f32, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map",
"valueType": {
"type": {
"$ref": "#/$defs/f32"
}
}
},
"bevy_utils::hashbrown::HashMap<u32, alloc::string::String, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"isComponent": false,
"isResource": false,
"keyType": {
"type": {
"$ref": "#/$defs/u32"
}
},
"long_name": "bevy_utils::hashbrown::HashMap<u32, alloc::string::String, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<u32, String, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map",
"valueType": {
"type": {
"$ref": "#/$defs/alloc::string::String"
}
}
},
"bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"isComponent": false,
"isResource": false,
"keyType": {
"type": {
"$ref": "#/$defs/u32"
}
},
"long_name": "bevy_utils::hashbrown::HashMap<u32, alloc::vec::Vec<alloc::string::String>, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<u32, Vec<String>, DefaultHashBuilder>",
"type": "object",
"typeInfo": "Map",
"valueType": {
"type": {
"$ref": "#/$defs/alloc::vec::Vec<alloc::string::String>"
}
}
},
"bevy_utils::hashbrown::HashMap<u32, bevy_render::color::Color, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>": {
"isComponent": false,
"isResource": false,
"keyType": {
"type": {
"$ref": "#/$defs/u32"
}
},
"long_name": "bevy_utils::hashbrown::HashMap<u32, bevy_render::color::Color, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>", "long_name": "bevy_utils::hashbrown::HashMap<u32, bevy_render::color::Color, bevy_utils::hashbrown::hash_map::DefaultHashBuilder>",
"short_name": "HashMap<u32, Color, DefaultHashBuilder>", "short_name": "HashMap<u32, Color, DefaultHashBuilder>",
"type": "object", "type": "object",
"typeInfo": "Map" "typeInfo": "Map",
"valueType": {
"type": {
"$ref": "#/$defs/bevy_render::color::Color"
}
}
}, },
"bevy_utils::smallvec::SmallVec<[bevy_ecs::entity::Entity; 8]>": { "bevy_utils::smallvec::SmallVec<[bevy_ecs::entity::Entity; 8]>": {
"isComponent": false, "isComponent": false,

View File

@ -1,12 +1,23 @@
use bevy::prelude::*; use std::any::TypeId;
use bevy::{prelude::*, utils::HashSet};
use bevy_gltf_blueprints::*; use bevy_gltf_blueprints::*;
use bevy_registry_export::*; use bevy_registry_export::*;
use crate::{ComponentAToFilterOut, ComponentBToFilterOut};
pub struct CorePlugin; pub struct CorePlugin;
impl Plugin for CorePlugin { impl Plugin for CorePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_plugins(( app.add_plugins((
ExportRegistryPlugin::default(), ExportRegistryPlugin{
component_filter: SceneFilter::Denylist(HashSet::from([ // this is using Bevy's build in SceneFilter, you can compose what components you want to allow/deny
TypeId::of::<ComponentAToFilterOut>(),
TypeId::of::<ComponentBToFilterOut>(),
// and any other commponent you want to include/exclude
])),
..Default::default()},
BlueprintsPlugin { BlueprintsPlugin {
library_folder: "blueprints".into(), library_folder: "blueprints".into(),
format: GltfFormat::GLB, format: GltfFormat::GLB,

View File

@ -152,7 +152,6 @@ impl MaterialExtension for MyExtension {
} }
} }
use bevy::utils::HashMap; use bevy::utils::HashMap;
#[derive(Component, Reflect, Default, Debug)] #[derive(Component, Reflect, Default, Debug)]
@ -189,6 +188,14 @@ pub struct HashmapTestStringColor {
#[reflect(Component)] #[reflect(Component)]
pub struct HashmapTestStringColorFlat(HashMap<String, Color>); pub struct HashmapTestStringColorFlat(HashMap<String, Color>);
#[derive(Component, Reflect, Default, Debug)]
#[reflect(Component)]
pub struct ComponentAToFilterOut;
#[derive(Component, Reflect, Default, Debug)]
#[reflect(Component)]
pub struct ComponentBToFilterOut;
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) {
@ -228,14 +235,13 @@ impl Plugin for ComponentsTestPlugin {
.register_type::<HashmapTestStringFloat>() .register_type::<HashmapTestStringFloat>()
.register_type::<HashMap<u32, String>>() .register_type::<HashMap<u32, String>>()
.register_type::<HashmapTestIntString>() .register_type::<HashmapTestIntString>()
.register_type::<HashMap<u32, Color>>() .register_type::<HashMap<u32, Color>>()
.register_type::<HashmapTestIntColor>() .register_type::<HashmapTestIntColor>()
.register_type::<HashMap<String, Color>>() .register_type::<HashMap<String, Color>>()
.register_type::<HashmapTestStringColor>() .register_type::<HashmapTestStringColor>()
.register_type::<HashmapTestStringColorFlat>() .register_type::<HashmapTestStringColorFlat>()
.register_type::<ComponentAToFilterOut>()
.register_type::<ComponentBToFilterOut>()
.add_plugins(MaterialPlugin::< .add_plugins(MaterialPlugin::<
ExtendedMaterial<StandardMaterial, MyExtension>, ExtendedMaterial<StandardMaterial, MyExtension>,
>::default()); >::default());

View File

@ -212,14 +212,18 @@ UI:
========================================= =========================================
Restructuring of storage of components Restructuring of storage of components
- [x] marking of invalid root propgroups/components should be based on long name - [x] marking of invalid root propgroups/components should be based on long name
- [ ] overhaul & check each prop group type's use of short names => long names - [x] overhaul & check each prop group type's use of short names => long names
- [ ] lists - [x] lists
- [ ] property_name = short_name in process enum: will likely require to use another indirection helper to keep the propery names short - [x] property_name = short_name in process enum: will likely require to use another indirection helper to keep the propery names short
- [x] in conversions from propgroups - [x] in conversions from propgroups
component_name = definition["short_name"] component_name = definition["short_name"]
- [ ] fix is_component_valid that is used in gltf_auto_export - [ ] fix is_component_valid that is used in gltf_auto_export
- [x] update all tests
- Hashmap Support - Hashmap Support
- [ ] fix parsing of keys's type either on Bevy side (prefered, unlikely to be possible) or on the Blender side - [x] fix parsing of keys's type either on Bevy side (prefered) or on the Blender side
- [x] fix weird issue with missing "0" property when adding new entry in empty hashmap => happens only if the values for the "setter" have never been set
- [ ] handle missing types in registry for keys & values - [ ] handle missing types in registry for keys & values
- Add correct upgrade handling from individual component to bevy_components

View File

@ -2,6 +2,8 @@ import json
from bpy_types import Operator, UIList from bpy_types import Operator, UIList
from bpy.props import (StringProperty, EnumProperty, PointerProperty, FloatVectorProperty, IntProperty) from bpy.props import (StringProperty, EnumProperty, PointerProperty, FloatVectorProperty, IntProperty)
from ..propGroups.conversions_from_prop_group import property_group_value_to_custom_property_value
class GENERIC_MAP_OT_actions(Operator): class GENERIC_MAP_OT_actions(Operator):
"""Move items up and down, add and remove""" """Move items up and down, add and remove"""
bl_idname = "generic_map.map_action" bl_idname = "generic_map.map_action"
@ -47,7 +49,6 @@ class GENERIC_MAP_OT_actions(Operator):
key_setter = getattr(propertyGroup, "keys_setter") key_setter = getattr(propertyGroup, "keys_setter")
value_setter = getattr(propertyGroup, "values_setter") value_setter = getattr(propertyGroup, "values_setter")
if self.action == 'DOWN' and index < len(keys_list) - 1: if self.action == 'DOWN' and index < len(keys_list) - 1:
#item_next = scn.rule_list[index + 1].name #item_next = scn.rule_list[index + 1].name
keys_list.move(index, index + 1) keys_list.move(index, index + 1)
@ -67,23 +68,23 @@ class GENERIC_MAP_OT_actions(Operator):
if self.action == 'ADD': if self.action == 'ADD':
print("keys_list", keys_list) print("keys_list", keys_list)
# first we gather all key/value pairs
hashmap = {} hashmap = {}
for index, key in enumerate(keys_list): for index, key in enumerate(keys_list):
key_entry = {} key_entry = {}
for field_name in key.field_names: for field_name in key.field_names:
print("field name", field_name, key) key_entry[field_name] = getattr(key, field_name, None)
key_entry[field_name] = key[field_name]
value_entry = {} value_entry = {}
for field_name in values_list[index].field_names: for field_name in values_list[index].field_names:
value_entry[field_name] = values_list[index][field_name] value_entry[field_name] = values_list[index][field_name]
hashmap[json.dumps(key_entry)] = index
hashmap[json.dumps(key_entry)] = index #{"value": json.dumps(value_entry), "index": index}
print("hashmap", hashmap ) print("hashmap", hashmap )
# we need to find the index of a specific value # then we need to find the index of a specific value if it exists
key_entry = {} key_entry = {}
for field_name in key_setter.field_names: for field_name in key_setter.field_names:
key_entry[field_name] = key_setter[field_name] key_entry[field_name] = getattr(key_setter, field_name, None)
key_to_add = json.dumps(key_entry) key_to_add = json.dumps(key_entry)
existing_index = hashmap.get(key_to_add, None) existing_index = hashmap.get(key_to_add, None)
print("existing_index", existing_index) print("existing_index", existing_index)
@ -93,12 +94,18 @@ class GENERIC_MAP_OT_actions(Operator):
key = keys_list.add() key = keys_list.add()
# copy the values over # copy the values over
for field_name in key_setter.field_names: for field_name in key_setter.field_names:
key[field_name] = key_setter[field_name] val = getattr(key_setter, field_name, None)
if val is not None:
key[field_name] = val
# TODO: add error handling
value = values_list.add() value = values_list.add()
# copy the values over # copy the values over
for field_name in value_setter.field_names: for field_name in value_setter.field_names:
value[field_name] = value_setter[field_name] val = getattr(value_setter, field_name, None)
if val is not None:
value[field_name] = val
# TODO: add error handling
propertyGroup.list_index = index + 1 # we use this to force the change detection propertyGroup.list_index = index + 1 # we use this to force the change detection
propertyGroup.values_index = index + 1 # we use this to force the change detection propertyGroup.values_index = index + 1 # we use this to force the change detection

View File

@ -110,6 +110,7 @@ def do_object_custom_properties_have_missing_metadata(object):
import json import json
def upsert_bevy_component(object, long_name, value): def upsert_bevy_component(object, long_name, value):
if not 'bevy_components' in object: if not 'bevy_components' in object:
object['bevy_components'] = '{}' object['bevy_components'] = '{}'
@ -121,16 +122,11 @@ def upsert_bevy_component(object, long_name, value):
def remove_bevy_component(object, long_name): def remove_bevy_component(object, long_name):
if 'bevy_components' in object: if 'bevy_components' in object:
bevy_components = json.loads(object['bevy_components']) bevy_components = json.loads(object['bevy_components'])
if long_name in bevy_components:
del bevy_components[long_name] del bevy_components[long_name]
object['bevy_components'] = json.dumps(bevy_components) object['bevy_components'] = json.dumps(bevy_components)
if long_name in object:
def rename_bevy_component(object, original_long_name, new_long_name): del object[long_name]
if 'bevy_components' in object:
bevy_components = json.loads(object['bevy_components'])
original_component = bevy_components.get(original_long_name, None)
bevy_components[new_long_name] = original_component
del bevy_components[original_long_name]
object['bevy_components'] = json.dumps(bevy_components)
def get_bevy_components(object): def get_bevy_components(object):
if 'bevy_components' in object: if 'bevy_components' in object:
@ -175,17 +171,12 @@ def add_component_to_object(object, component_definition, value=None):
property_group_value_from_custom_property_value(propertyGroup, definition, registry, value) property_group_value_from_custom_property_value(propertyGroup, definition, registry, value)
del object["__disable__update"] del object["__disable__update"]
# object[short_name] = value
print("ADDING VAALUEEE", value)
upsert_bevy_component(object, long_name, value) upsert_bevy_component(object, long_name, value)
#ping_depsgraph_update(object)
def upsert_component_in_object(object, long_name, registry): def upsert_component_in_object(object, long_name, registry):
# print("upsert_component_in_object", object, "component name", component_name) # print("upsert_component_in_object", object, "component name", component_name)
# TODO: upsert this part too ? # TODO: upsert this part too ?
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
print("target_components_metadata", target_components_metadata)
component_definition = registry.type_infos.get(long_name, None) component_definition = registry.type_infos.get(long_name, None)
if component_definition != None: if component_definition != None:
short_name = component_definition["short_name"] short_name = component_definition["short_name"]
@ -196,7 +187,7 @@ def upsert_component_in_object(object, long_name, registry):
component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
if not component_meta: if not component_meta:
component_meta = target_components_metadata.add() component_meta = target_components_metadata.add()
component_meta.name = short_name component_meta.short_name = short_name
component_meta.long_name = long_name component_meta.long_name = long_name
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
else: # this one has metadata but we check that the relevant property group is present else: # this one has metadata but we check that the relevant property group is present
@ -299,7 +290,7 @@ def apply_customProperty_values_to_object_propertyGroups(object):
source_componentMeta = next(filter(lambda component: component["long_name"] == component_name, components_metadata), None) source_componentMeta = next(filter(lambda component: component["long_name"] == component_name, components_metadata), None)
# matching component means we already have this type of component # matching component means we already have this type of component
propertyGroup = getattr(source_componentMeta, property_group_name, None) propertyGroup = getattr(source_componentMeta, property_group_name, None)
customProperty_value = object[component_name] customProperty_value = get_bevy_component_value_by_long_name(object, component_name)
#value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None) #value = property_group_value_to_custom_property_value(propertyGroup, component_definition, registry, None)
object["__disable__update"] = True # disable update callback while we set the values of the propertyGroup "tree" (as a propertyGroup can contain other propertyGroups) object["__disable__update"] = True # disable update callback while we set the values of the propertyGroup "tree" (as a propertyGroup can contain other propertyGroups)
@ -310,8 +301,10 @@ def apply_customProperty_values_to_object_propertyGroups(object):
# removes the given component from the object: removes both the custom property and the matching metadata from the object # removes the given component from the object: removes both the custom property and the matching metadata from the object
def remove_component_from_object(object, component_name): def remove_component_from_object(object, component_name):
# remove the component value
remove_bevy_component(object, component_name) remove_bevy_component(object, component_name)
# now remove the component's metadata
components_metadata = getattr(object, "components_meta", None) components_metadata = getattr(object, "components_meta", None)
if components_metadata == None: if components_metadata == None:
return False return False
@ -331,6 +324,19 @@ def add_component_from_custom_property(object):
add_metadata_to_components_without_metadata(object) add_metadata_to_components_without_metadata(object)
apply_customProperty_values_to_object_propertyGroups(object) apply_customProperty_values_to_object_propertyGroups(object)
def rename_component(object, original_long_name, new_long_name):
registry = bpy.context.window_manager.components_registry
type_infos = registry.type_infos
component_definition = type_infos[new_long_name]
component_ron_value = get_bevy_component_value_by_long_name(object=object, long_name=original_long_name)
if component_ron_value is None and original_long_name in object:
component_ron_value = object[original_long_name]
remove_component_from_object(object, original_long_name)
add_component_to_object(object, component_definition, component_ron_value)
def toggle_component(object, component_name): def toggle_component(object, component_name):
components_in_object = object.components_meta.components components_in_object = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None) component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None)

View File

@ -4,7 +4,7 @@ import bpy
from bpy_types import Operator from bpy_types import Operator
from bpy.props import (StringProperty) from bpy.props import (StringProperty)
from .metadata import add_component_from_custom_property, add_component_to_object, apply_propertyGroup_values_to_object_customProperties_for_component, copy_propertyGroup_values_to_another_object, get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_object, remove_component_from_object, rename_bevy_component, toggle_component from .metadata import add_component_from_custom_property, add_component_to_object, apply_propertyGroup_values_to_object_customProperties_for_component, copy_propertyGroup_values_to_another_object, get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_object, remove_component_from_object, rename_component, toggle_component
class AddComponentOperator(Operator): class AddComponentOperator(Operator):
"""Add Bevy component to object""" """Add Bevy component to object"""
@ -214,31 +214,10 @@ class OT_rename_component(Operator):
if original_name != '' and new_name != '' and original_name != new_name and len(target_objects) > 0: if original_name != '' and new_name != '' and original_name != new_name and len(target_objects) > 0:
for index, object_name in enumerate(target_objects): for index, object_name in enumerate(target_objects):
object = bpy.data.objects[object_name] object = bpy.data.objects[object_name]
if object and original_name in get_bevy_components(object): if object and original_name in get_bevy_components(object) or original_name in object:
# copy data to new component, remove the old one
try:
rename_bevy_component(object=object, original_long_name=original_name, new_long_name=new_name)
remove_component_from_object(object, original_name)
except Exception as error:
if '__disable__update' in object:
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure
# get metadata
components_metadata = getattr(object, "components_meta", None)
if components_metadata:
components_metadata = components_metadata.components
component_meta = next(filter(lambda component: component["long_name"] == new_name, components_metadata), None)
if component_meta:
component_meta.invalid = True
component_meta.invalid_details = "unknow issue when renaming/transforming component, please remove it & add it back again"
errors.append( "failed to copy old component value to new component: object: '" + object.name + "', error: " + str(error))
try: try:
# attempt conversion # attempt conversion
long_name = new_name rename_component(object=object, original_long_name=original_name, new_long_name=new_name)
component_definition = type_infos[long_name]
add_component_to_object(object, component_definition, get_bevy_component_value_by_long_name(new_name))
except Exception as error: except Exception as error:
if '__disable__update' in object: if '__disable__update' in object:
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure

View File

@ -20,7 +20,7 @@ def draw_propertyGroup( propertyGroup, layout, nesting =[], rootName=None):
display_name = field_names[0] if propertyGroup.tupple_or_struct == "struct" else "" display_name = field_names[0] if propertyGroup.tupple_or_struct == "struct" else ""
subrow.prop(propertyGroup, field_names[0], text=display_name) subrow.prop(propertyGroup, field_names[0], text=display_name)
subrow.separator() subrow.separator()
selection = getattr(propertyGroup, field_names[0]) selection = getattr(propertyGroup, "selection")
for fname in field_names[1:]: for fname in field_names[1:]:
if fname == "variant_" + selection: if fname == "variant_" + selection:

View File

@ -28,12 +28,11 @@ conversion_tables = {
#converts the value of a property group(no matter its complexity) into a single custom property value #converts the value of a property group(no matter its complexity) into a single custom property value
# this is more or less a glorified "to_ron()" method (not quite but close to) # this is more or less a glorified "to_ron()" method (not quite but close to)
def property_group_value_to_custom_property_value(property_group, definition, registry, parent=None, value=None): def property_group_value_to_custom_property_value(property_group, definition, registry, parent=None, value=None):
print('definition', definition)
long_name = definition["long_name"] long_name = definition["long_name"]
type_info = definition["typeInfo"] if "typeInfo" in definition else None type_info = definition["typeInfo"] if "typeInfo" in definition else None
type_def = definition["type"] if "type" in definition else None type_def = definition["type"] if "type" in definition else None
is_value_type = long_name in conversion_tables is_value_type = long_name in conversion_tables
# print("computing custom property: component name:", long_name, "type_info", type_info, "type_def", type_def) # print("computing custom property: component name:", long_name, "type_info", type_info, "type_def", type_def, "value", value)
if is_value_type: if is_value_type:
value = conversion_tables[long_name](value) value = conversion_tables[long_name](value)
@ -89,11 +88,7 @@ def property_group_value_to_custom_property_value(property_group, definition, re
value = tuple(e for e in list(values.values())) value = tuple(e for e in list(values.values()))
elif type_info == "Enum": elif type_info == "Enum":
short_name = definition["short_name"] selected = getattr(property_group, "selection")
print("ENUM", definition, property_group.field_names, long_name)
# TODO: perhaps use a mapping of (long) component name to a short ID , like we do in get_propertyGroupName_from_longName
selected = getattr(property_group, short_name)
if type_def == "object": if type_def == "object":
selection_index = property_group.field_names.index("variant_"+selected) selection_index = property_group.field_names.index("variant_"+selected)
variant_name = property_group.field_names[selection_index] variant_name = property_group.field_names[selection_index]
@ -174,7 +169,6 @@ def property_group_value_to_custom_property_value(property_group, definition, re
value = value.replace("'", "") value = value.replace("'", "")
if parent == None: if parent == None:
print("transforming value", value, definition)
value = str(value).replace("'", "") value = str(value).replace("'", "")
value = value.replace(",)",")") value = value.replace(",)",")")
value = value.replace("{", "(").replace("}", ")") # FIXME: deal with hashmaps value = value.replace("{", "(").replace("}", ")") # FIXME: deal with hashmaps

View File

@ -268,7 +268,7 @@ def property_group_value_from_custom_property_value(property_group, definition,
selection_index = property_group.field_names.index(chosen_variant_name) selection_index = property_group.field_names.index(chosen_variant_name)
variant_definition = definition["oneOf"][selection_index-1] variant_definition = definition["oneOf"][selection_index-1]
# first we set WHAT variant is selected # first we set WHAT variant is selected
setattr(property_group, field_names[0], chosen_variant_raw) setattr(property_group, "selection", chosen_variant_raw)
# and then we set the value of the variant # and then we set the value of the variant
if "prefixItems" in variant_definition: if "prefixItems" in variant_definition:

View File

@ -7,7 +7,7 @@ def process_enum(registry, definition, update, nesting, nesting_long_names):
long_name = definition["long_name"] long_name = definition["long_name"]
type_def = definition["type"] if "type" in definition else None type_def = definition["type"] if "type" in definition else None
values = definition["oneOf"] variants = definition["oneOf"]
nesting = nesting + [short_name] nesting = nesting + [short_name]
nesting_long_names = nesting_long_names = [long_name] nesting_long_names = nesting_long_names = [long_name]
@ -15,59 +15,53 @@ def process_enum(registry, definition, update, nesting, nesting_long_names):
__annotations__ = {} __annotations__ = {}
original_type_name = "enum" original_type_name = "enum"
#print("processing enum", short_name, definition) # print("processing enum", short_name, long_name, definition)
if type_def == "object": if type_def == "object":
labels = [] labels = []
additional_annotations = {} additional_annotations = {}
for item in values: for variant in variants:
item_name = item["long_name"] variant_name = variant["long_name"]
item_short_name = item["short_name"] if "short_name" in item else item_name variant_prefixed_name = "variant_" + variant_name
variant_name = "variant_" + item_short_name labels.append(variant_name)
labels.append(item_name)
if "prefixItems" in item: if "prefixItems" in variant:
#print("tupple variant in enum", short_name, item) #print("tupple variant in enum", variant)
registry.add_custom_type(item_short_name, item) registry.add_custom_type(variant_name, variant)
(sub_component_group, _) = process_component.process_component(registry, item, update, {"nested": True}, nesting, nesting_long_names) (sub_component_group, _) = process_component.process_component(registry, variant, update, {"nested": True}, nesting, nesting_long_names)
additional_annotations[variant_name] = sub_component_group additional_annotations[variant_prefixed_name] = sub_component_group
elif "properties" in item: elif "properties" in variant:
#print("struct variant in enum", short_name, item) #print("struct variant in enum", variant)
registry.add_custom_type(item_short_name, item) registry.add_custom_type(variant_name, variant)
(sub_component_group, _) = process_component.process_component(registry, item, update, {"nested": True}, nesting, nesting_long_names) (sub_component_group, _) = process_component.process_component(registry, variant, update, {"nested": True}, nesting, nesting_long_names)
additional_annotations[variant_name] = sub_component_group additional_annotations[variant_prefixed_name] = sub_component_group
else: # for the cases where it's neither a tupple nor a structs: FIXME: not 100% sure of this else: # for the cases where it's neither a tupple nor a structs: FIXME: not 100% sure of this
#print("other variant in enum", short_name) #print("other variant in enum")
annotations = {"variant_"+item_name: StringProperty(default="----<ignore_field>----")} annotations = {"variant_"+variant_name: StringProperty(default="----<ignore_field>----")}
additional_annotations = additional_annotations | annotations additional_annotations = additional_annotations | annotations
items = tuple((e, e, e) for e in labels) items = tuple((e, e, e) for e in labels)
property_name = short_name
blender_property_def = blender_property_mapping[original_type_name] blender_property_def = blender_property_mapping[original_type_name]
blender_property = blender_property_def["type"]( blender_property = blender_property_def["type"](
**blender_property_def["presets"],# we inject presets first **blender_property_def["presets"],# we inject presets first
name = property_name, items=items, # this is needed by Blender's EnumProperty , which we are using here
items=items,
update= update update= update
) )
__annotations__[property_name] = blender_property __annotations__["selection"] = blender_property
for a in additional_annotations: for a in additional_annotations:
__annotations__[a] = additional_annotations[a] __annotations__[a] = additional_annotations[a]
# enum_value => what field to display # enum_value => what field to display
# a second field + property for the "content" of the enum # a second field + property for the "content" of the enum
else: else:
items = tuple((e, e, "") for e in values) items = tuple((e, e, "") for e in variants)
property_name = short_name
blender_property_def = blender_property_mapping[original_type_name] blender_property_def = blender_property_mapping[original_type_name]
blender_property = blender_property_def["type"]( blender_property = blender_property_def["type"](
**blender_property_def["presets"],# we inject presets first **blender_property_def["presets"],# we inject presets first
name = property_name,
items=items, items=items,
update= update update= update
) )
__annotations__[property_name] = blender_property __annotations__["selection"] = blender_property
return __annotations__ return __annotations__

View File

@ -12,8 +12,8 @@ def process_map(registry, definition, update, nesting=[], nesting_long_names=[])
nesting = nesting + [short_name] nesting = nesting + [short_name]
nesting_long_names = nesting_long_names + [long_name] nesting_long_names = nesting_long_names + [long_name]
value_ref_name = definition["additionalProperties"]["type"]["$ref"].replace("#/$defs/", "") value_ref_name = definition["valueType"]["type"]["$ref"].replace("#/$defs/", "")
key_ref_name = long_name.split(',')[0].split('<')[1]# FIXME: hack !!! key_ref_name = definition["keyType"]["type"]["$ref"].replace("#/$defs/", "")
#print("definition", definition) #print("definition", definition)
__annotations__ = {} __annotations__ = {}
@ -21,11 +21,11 @@ def process_map(registry, definition, update, nesting=[], nesting_long_names=[])
key_definition = type_infos[key_ref_name] key_definition = type_infos[key_ref_name]
original_long_name = key_definition["long_name"] original_long_name = key_definition["long_name"]
is_key_value_type = original_long_name in value_types_defaults is_key_value_type = original_long_name in value_types_defaults
definition_link = f"#/$defs/{key_ref_name}" definition_link = definition["keyType"]["type"]["$ref"]
#if the content of the list is a unit type, we need to generate a fake wrapper, otherwise we cannot use layout.prop(group, "propertyName") as there is no propertyName ! #if the content of the list is a unit type, we need to generate a fake wrapper, otherwise we cannot use layout.prop(group, "propertyName") as there is no propertyName !
if is_key_value_type: if is_key_value_type:
keys_property_group_class = generate_wrapper_propertyGroup(f"{long_name}_values", original_long_name, definition_link, registry, update) keys_property_group_class = generate_wrapper_propertyGroup(f"{long_name}_keys", original_long_name, definition_link, registry, update)
else: else:
(_, list_content_group_class) = process_component.process_component(registry, key_definition, update, {"nested": True, "long_name": original_long_name}, nesting, nesting_long_names) (_, list_content_group_class) = process_component.process_component(registry, key_definition, update, {"nested": True, "long_name": original_long_name}, nesting, nesting_long_names)
keys_property_group_class = list_content_group_class keys_property_group_class = list_content_group_class
@ -42,11 +42,11 @@ def process_map(registry, definition, update, nesting=[], nesting_long_names=[])
value_definition = type_infos[value_ref_name] value_definition = type_infos[value_ref_name]
original_long_name = value_definition["long_name"] original_long_name = value_definition["long_name"]
is_value_value_type = original_long_name in value_types_defaults is_value_value_type = original_long_name in value_types_defaults
definition_link = definition["additionalProperties"]["type"]["$ref"]#f"#/$defs/{value_ref_name}" definition_link = definition["valueType"]["type"]["$ref"]
#if the content of the list is a unit type, we need to generate a fake wrapper, otherwise we cannot use layout.prop(group, "propertyName") as there is no propertyName ! #if the content of the list is a unit type, we need to generate a fake wrapper, otherwise we cannot use layout.prop(group, "propertyName") as there is no propertyName !
if is_value_value_type: if is_value_value_type:
values_property_group_class = generate_wrapper_propertyGroup(f"{long_name}_keys", original_long_name, definition_link, registry, update) values_property_group_class = generate_wrapper_propertyGroup(f"{long_name}_values", original_long_name, definition_link, registry, update)
else: else:
(_, list_content_group_class) = process_component.process_component(registry, value_definition, update, {"nested": True, "long_name": original_long_name}, nesting, nesting_long_names) (_, list_content_group_class) = process_component.process_component(registry, value_definition, update, {"nested": True, "long_name": original_long_name}, nesting, nesting_long_names)
values_property_group_class = list_content_group_class values_property_group_class = list_content_group_class

View File

@ -16,7 +16,6 @@ def update_component(self, context, definition, component_name):
print("update in component", component_name, self, "current_object", current_object.name) print("update in component", component_name, self, "current_object", current_object.name)
components_in_object = current_object.components_meta.components components_in_object = current_object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None) component_meta = next(filter(lambda component: component["long_name"] == component_name, components_in_object), None)
print("component_meta", component_meta)
if component_meta != None: if component_meta != None:
property_group_name = registry.get_propertyGroupName_from_longName(component_name) property_group_name = registry.get_propertyGroupName_from_longName(component_name)

View File

@ -118,10 +118,10 @@ class COMPONENTS_OT_REFRESH_PROPGROUPS_FROM_CUSTOM_PROPERTIES_CURRENT(Operator):
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
except:pass # ony run in ui except:pass # ony run in ui
except Exception as error: except Exception as error_message:
del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure del object["__disable__update"] # make sure custom properties are updateable afterwards, even in the case of failure
error = True error = True
self.report({'ERROR'}, "Failed to update propertyGroup values from custom property: Error:" + str(error)) self.report({'ERROR'}, "Failed to update propertyGroup values from custom property: Error:" + str(error_message))
if not error: if not error:
self.report({'INFO'}, "Sucessfully generated UI values for custom properties for selected object") self.report({'INFO'}, "Sucessfully generated UI values for custom properties for selected object")
context.window_manager.components_from_custom_properties_progress = -1.0 context.window_manager.components_from_custom_properties_progress = -1.0

View File

@ -131,7 +131,6 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
components_metadata = object.components_meta.components components_metadata = object.components_meta.components
comp_names = [] comp_names = []
for index, component_meta in enumerate(components_metadata): for index, component_meta in enumerate(components_metadata):
short_name = component_meta.name
long_name = component_meta.long_name long_name = component_meta.long_name
if component_meta.invalid: if component_meta.invalid:
self.draw_invalid_or_unregistered(layout, "Invalid", long_name, object) self.draw_invalid_or_unregistered(layout, "Invalid", long_name, object)
@ -146,7 +145,7 @@ class BEVY_COMPONENTS_PT_AdvancedToolsPanel(bpy.types.Panel):
comp_names.append(long_name) comp_names.append(long_name)
for custom_property in object.keys(): for custom_property in object.keys():
if custom_property != 'components_meta' and custom_property not in comp_names: if custom_property != 'components_meta' and custom_property != 'bevy_components' and custom_property not in comp_names:
self.draw_invalid_or_unregistered(layout, "Unregistered", custom_property, object) self.draw_invalid_or_unregistered(layout, "Unregistered", custom_property, object)
if not object.name in objects_with_invalid_components: if not object.name in objects_with_invalid_components:

View File

@ -162,7 +162,7 @@ def component_values_shuffler(seed=1, property_group=None, definition=None, regi
selected = random.choice(available_variants) selected = random.choice(available_variants)
# set selected variant # set selected variant
setattr(property_group , component_name, selected) setattr(property_group , "selection", selected)
if type_def == "object": if type_def == "object":
selection_index = property_group.field_names.index("variant_"+selected) selection_index = property_group.field_names.index("variant_"+selected)

View File

@ -1,444 +1,555 @@
expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut': '()', expected_custom_property_values = {'bevy_animation::AnimationPlayer': '(animation: "", paused: true)',
'Aabb': '(center: Vec3A(x:0.0, y:0.0, z:0.0), half_extents: Vec3A(x:0.0, y:0.0, z:0.0))', 'bevy_asset::handle::Handle<()>': 'Strong("")',
'AdditionalMassProperties': 'Mass(0.0)', 'bevy_asset::handle::Handle<bevy_animation::AnimationClip>': 'Strong("")',
'AnimationPlayer': '(animation: "", paused: true)', 'bevy_asset::handle::Handle<bevy_asset::assets::LoadedUntypedAsset>': 'Strong("")',
'Animations': '(named_animations: "")', 'bevy_asset::handle::Handle<bevy_asset::folder::LoadedFolder>': 'Strong("")',
'AutoAABBCollider': 'Cuboid', 'bevy_asset::handle::Handle<bevy_asset_loader::standard_dynamic_asset::StandardDynamicAssetCollection>': 'Strong("")',
'BackgroundColor': '(Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))', 'bevy_asset::handle::Handle<bevy_audio::audio_source::AudioSource>': 'Strong("")',
'BasicTest': '(a: 0.0, b: 0, c: " ")', 'bevy_asset::handle::Handle<bevy_audio::pitch::Pitch>': 'Strong("")',
'BlenderBackgroundShader': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), strength: 0.0)', 'bevy_asset::handle::Handle<bevy_gizmos::LineGizmo>': 'Strong("")',
'BlenderLightShadows': '(buffer_bias: 0.0, enabled: true)', 'bevy_asset::handle::Handle<bevy_gltf::Gltf>': 'Strong("")',
'BlenderShadowSettings': '(cascade_size: 0)', 'bevy_asset::handle::Handle<bevy_gltf::GltfMesh>': 'Strong("")',
'BloomSettings': '(composite_mode: EnergyConserving, high_pass_frequency: 0.0, intensity: 0.0, low_frequency_boost: ' 'bevy_asset::handle::Handle<bevy_gltf::GltfNode>': 'Strong("")',
'0.0, low_frequency_boost_curvature: 0.0, prefilter_settings: (threshold: 0.0, threshold_softness: ' 'bevy_asset::handle::Handle<bevy_gltf::GltfPrimitive>': 'Strong("")',
'0.0))', 'bevy_asset::handle::Handle<bevy_pbr::extended_material::ExtendedMaterial<bevy_pbr::pbr_material::StandardMaterial, bevy_example::test_components::MyExtension>>': 'Strong("")',
'BlueprintName': '(" ")', 'bevy_asset::handle::Handle<bevy_pbr::pbr_material::StandardMaterial>': 'Strong("")',
'BlueprintsList': '("")', 'bevy_asset::handle::Handle<bevy_pbr::wireframe::WireframeMaterial>': 'Strong("")',
'BorderColor': '(Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))', 'bevy_asset::handle::Handle<bevy_render::mesh::mesh::Mesh>': 'Strong("")',
'Button': '()', 'bevy_asset::handle::Handle<bevy_render::mesh::mesh::skinning::SkinnedMeshInverseBindposes>': 'Strong("")',
'CalculatedClip': '(clip: (max: Vec2(x:0.0, y:0.0), min: Vec2(x:0.0, y:0.0)))', 'bevy_asset::handle::Handle<bevy_render::render_resource::shader::Shader>': 'Strong("")',
'Camera': '(clear_color: Default, hdr: true, is_active: true, msaa_writeback: true, order: 0, viewport: None)', 'bevy_asset::handle::Handle<bevy_render::texture::image::Image>': 'Strong("")',
'Camera2d': '()', 'bevy_asset::handle::Handle<bevy_scene::dynamic_scene::DynamicScene>': 'Strong("")',
'Camera3d': '(depth_load_op: Clear(0.0), depth_texture_usages: (0), screen_space_specular_transmission_quality: Low, ' 'bevy_asset::handle::Handle<bevy_scene::scene::Scene>': 'Strong("")',
'screen_space_specular_transmission_steps: 0)', 'bevy_asset::handle::Handle<bevy_sprite::mesh2d::color_material::ColorMaterial>': 'Strong("")',
'CameraMainTextureUsages': 'None', 'bevy_asset::handle::Handle<bevy_sprite::texture_atlas::TextureAtlasLayout>': 'Strong("")',
'CameraRenderGraph': 'None', 'bevy_asset::handle::Handle<bevy_text::font::Font>': 'Strong("")',
'CameraTrackable': '()', 'bevy_audio::audio::PlaybackSettings': '(mode: Once, paused: true, spatial: true, spatial_scale: "", speed: 0.0, '
'CameraTracking': '(offset: Vec3(x:0.0, y:0.0, z:0.0))', 'volume: (0.0))',
'CameraTrackingOffset': '(Vec3(x:0.0, y:0.0, z:0.0))', 'bevy_audio::audio::SpatialListener': '(left_ear_offset: Vec3(x:0.0, y:0.0, z:0.0), right_ear_offset: Vec3(x:0.0, '
'CascadeShadowConfig': '(bounds: [], minimum_distance: 0.0, overlap_proportion: 0.0)',
'Cascades': '(cascades: "")',
'CascadesFrusta': '()',
'CascadesVisibleEntities': '()',
'Ccd': '(enabled: true)',
'Children': '([])',
'ClusterConfig': 'None',
'Collider': 'Ball(0.0)',
'CollidingEntities': '("")',
'CollisionGroups': '(filters: (0), memberships: (0))',
'ColorGrading': '(exposure: 0.0, gamma: 0.0, post_saturation: 0.0, pre_saturation: 0.0)',
'ContactForceEventThreshold': '(0.0)',
'ContentSize': '()',
'ContrastAdaptiveSharpeningSettings': '(denoise: true, enabled: true, sharpening_strength: 0.0)',
'CubemapFrusta': '()',
'CubemapVisibleEntities': '()',
'Damping': '(angular_damping: 0.0, linear_damping: 0.0)',
'DebandDither': 'Disabled',
'DirectionalLight': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), illuminance: 0.0, shadow_depth_bias: 0.0, '
'shadow_normal_bias: 0.0, shadows_enabled: true)',
'Dominance': '(groups: 0)',
'EnumComplex': 'Float(0.0)',
'EnumTest': 'Metal',
'Exposure': 'None',
'ExternalForce': '(force: Vec3(x:0.0, y:0.0, z:0.0), torque: Vec3(x:0.0, y:0.0, z:0.0))',
'ExternalImpulse': '(impulse: Vec3(x:0.0, y:0.0, z:0.0), torque_impulse: Vec3(x:0.0, y:0.0, z:0.0))',
'FocusPolicy': 'Block',
'FogSettings': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), directional_light_color: Rgba(red:1.0, '
'green:1.0, blue:0.0, alpha:1.0), directional_light_exponent: 0.0, falloff: Linear(end: 0.0, start: '
'0.0))',
'Friction': '(coefficient: 0.0, combine_rule: "")',
'Frustum': '()',
'Fxaa': '(edge_threshold: "", edge_threshold_min: "", enabled: true)',
'GlobalTransform': '((matrix3: (x_axis: Vec3A(x:0.0, y:0.0, z:0.0), y_axis: Vec3A(x:0.0, y:0.0, z:0.0), z_axis: '
'Vec3A(x:0.0, y:0.0, z:0.0)), translation: Vec3A(x:0.0, y:0.0, z:0.0)))',
'GltfExtras': '(value: " ")',
'GltfProcessed': '()',
'GravityScale': '(0.0)',
'Group': '(0)',
'Handle<()>': 'Strong("")',
'Handle<AnimationClip>': 'Strong("")',
'Handle<AudioSource>': 'Strong("")',
'Handle<ColorMaterial>': 'Strong("")',
'Handle<DynamicScene>': 'Strong("")',
'Handle<ExtendedMaterial<StandardMaterial, MyExtension>>': 'Strong("")',
'Handle<Font>': 'Strong("")',
'Handle<Gltf>': 'Strong("")',
'Handle<GltfMesh>': 'Strong("")',
'Handle<GltfNode>': 'Strong("")',
'Handle<GltfPrimitive>': 'Strong("")',
'Handle<Image>': 'Strong("")',
'Handle<LineGizmo>': 'Strong("")',
'Handle<LoadedFolder>': 'Strong("")',
'Handle<LoadedUntypedAsset>': 'Strong("")',
'Handle<Mesh>': 'Strong("")',
'Handle<Pitch>': 'Strong("")',
'Handle<Scene>': 'Strong("")',
'Handle<Shader>': 'Strong("")',
'Handle<SkinnedMeshInverseBindposes>': 'Strong("")',
'Handle<StandardDynamicAssetCollection>': 'Strong("")',
'Handle<StandardMaterial>': 'Strong("")',
'Handle<TextureAtlasLayout>': 'Strong("")',
'Handle<WireframeMaterial>': 'Strong("")',
'ImageScaleMode': 'Sliced((border: "", center_scale_mode: "", max_corner_scale: 0.0, sides_scale_mode: ""))',
'InheritedVisibility': '(true)',
'Interaction': 'Pressed',
'Label': '()',
'LightProbe': '()',
'LockedAxes': '(0)',
'MaterialInfo': '(name: " ", source: " ")',
'Mesh2dHandle': '(Strong(""))',
'MeshMorphWeights': '(weights: [])',
'MorphWeights': '(first_mesh: "", weights: [])',
'Name': '(hash: 0, name: " ")',
'NestedTupleStuff': '(0.0, 0, (basic: (a: 0.0, b: 0, c: " "), color: (Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0)), '
'colors_list: ([]), enable: true, enum_inner: Metal, nested: (vec: (Vec3(x:0.0, y:0.0, z:0.0))), '
'text: " ", toggle: (true)))',
'NestingTestLevel2': '(basic: (a: 0.0, b: 0, c: " "), color: (Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0)), '
'colors_list: ([]), enable: true, enum_inner: Metal, nested: (vec: (Vec3(x:0.0, y:0.0, z:0.0))), '
'text: " ", toggle: (true))',
'NestingTestLevel3': '(vec: (Vec3(x:0.0, y:0.0, z:0.0)))',
'NoFrustumCulling': '()',
'NoWireframe': '()',
'Node': '(calculated_size: Vec2(x:0.0, y:0.0), outline_offset: 0.0, outline_width: 0.0, stack_index: 0, '
'unrounded_size: Vec2(x:0.0, y:0.0))',
'NotShadowCaster': '()',
'NotShadowReceiver': '()',
'OrthographicProjection': '(area: (max: Vec2(x:0.0, y:0.0), min: Vec2(x:0.0, y:0.0)), far: 0.0, near: 0.0, scale: '
'0.0, scaling_mode: Fixed(height: 0.0, width: 0.0), viewport_origin: Vec2(x:0.0, y:0.0))',
'Outline': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), offset: Auto, width: Auto)',
'Parent': '(0)',
'PerspectiveProjection': '(aspect_ratio: 0.0, far: 0.0, fov: 0.0, near: 0.0)',
'Pickable': '()',
'PlaybackSettings': '(mode: Once, paused: true, spatial: true, spatial_scale: "", speed: 0.0, volume: (0.0))',
'Player': '()',
'PointLight': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), intensity: 0.0, radius: 0.0, range: 0.0, '
'shadow_depth_bias: 0.0, shadow_normal_bias: 0.0, shadows_enabled: true)',
'PrimaryWindow': '()',
'Projection': 'Perspective((aspect_ratio: 0.0, far: 0.0, fov: 0.0, near: 0.0))',
'RelativeCursorPosition': '(normalized: "", normalized_visible_node_rect: (max: Vec2(x:0.0, y:0.0), min: Vec2(x:0.0, '
'y:0.0)))',
'RenderLayers': '(0)',
'Restitution': '(coefficient: 0.0, combine_rule: "")',
'RigidBody': 'Dynamic',
'SSAOSettings': '()',
'ScreenSpaceAmbientOcclusionSettings': '(quality_level: "")',
'Sensor': '()',
'ShadowFilteringMethod': 'Hardware2x2',
'SkinnedMesh': '(inverse_bindposes: Strong(""), joints: [])',
'Sleeping': '(angular_threshold: 0.0, linear_threshold: 0.0, sleeping: true)',
'SolverGroups': '(filters: (0), memberships: (0))',
'SpatialListener': '(left_ear_offset: Vec3(x:0.0, y:0.0, z:0.0), right_ear_offset: Vec3(x:0.0, y:0.0, z:0.0))',
'SpawnHere': '()',
'SpotLight': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), inner_angle: 0.0, intensity: 0.0, outer_angle: '
'0.0, radius: 0.0, range: 0.0, shadow_depth_bias: 0.0, shadow_normal_bias: 0.0, shadows_enabled: true)',
'Sprite': '(anchor: Center, color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), custom_size: "", flip_x: true, '
'flip_y: true, rect: "")',
'Style': '(align_content: Default, align_items: Default, align_self: Auto, aspect_ratio: None, border: (bottom: Auto, '
'left: Auto, right: Auto, top: Auto), bottom: Auto, column_gap: Auto, direction: Inherit, display: Flex, '
'flex_basis: Auto, flex_direction: Row, flex_grow: 0.0, flex_shrink: 0.0, flex_wrap: NoWrap, '
'grid_auto_columns: "", grid_auto_flow: Row, grid_auto_rows: "", grid_column: (end: "", span: "", start: '
'""), grid_row: (end: "", span: "", start: ""), grid_template_columns: "", grid_template_rows: "", height: '
'Auto, justify_content: Default, justify_items: Default, justify_self: Auto, left: Auto, margin: (bottom: '
'Auto, left: Auto, right: Auto, top: Auto), max_height: Auto, max_width: Auto, min_height: Auto, min_width: '
'Auto, overflow: (x: Visible, y: Visible), padding: (bottom: Auto, left: Auto, right: Auto, top: Auto), '
'position_type: Relative, right: Auto, row_gap: Auto, top: Auto, width: Auto)',
'Text': '(justify: Left, linebreak_behavior: WordBoundary, sections: [])',
'Text2dBounds': '(size: Vec2(x:0.0, y:0.0))',
'TextFlags': '(needs_new_measure_func: true, needs_recompute: true)',
'TextLayoutInfo': '(glyphs: "", logical_size: Vec2(x:0.0, y:0.0))',
'Tonemapping': 'None',
'Transform': '(rotation: Quat(x:0.0, y:0.0, z:0.0, w:0.0), scale: Vec3(x:0.0, y:0.0, z:0.0), translation: Vec3(x:0.0, '
'y:0.0, z:0.0))', 'y:0.0, z:0.0))',
'TupleTest2': '(0.0, 0, " ")', 'bevy_core::name::Name': '(hash: 0, name: " ")',
'TupleTestBool': '(true)', 'bevy_core_pipeline::bloom::settings::BloomSettings': '(composite_mode: EnergyConserving, high_pass_frequency: 0.0, '
'TupleTestColor': '(Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))', 'intensity: 0.0, low_frequency_boost: 0.0, '
'TupleTestF32': '(0.0)', 'low_frequency_boost_curvature: 0.0, prefilter_settings: '
'TupleTestStr': '(" ")', '(threshold: 0.0, threshold_softness: 0.0))',
'TupleTestU64': '(0)', 'bevy_core_pipeline::contrast_adaptive_sharpening::ContrastAdaptiveSharpeningSettings': '(denoise: true, enabled: '
'TupleVec': '([])', 'true, sharpening_strength: '
'TupleVec2': '(Vec2(x:0.0, y:0.0))', '0.0)',
'TupleVec3': '(Vec3(x:0.0, y:0.0, z:0.0))', 'bevy_core_pipeline::core_2d::camera_2d::Camera2d': '()',
'TupleVecF32F32': '([])', 'bevy_core_pipeline::core_3d::camera_3d::Camera3d': '(depth_load_op: Clear(0.0), depth_texture_usages: (0), '
'UiImage': '(flip_x: true, flip_y: true, texture: Strong(""))', 'screen_space_specular_transmission_quality: Low, '
'UiImageSize': '(size: Vec2(x:0.0, y:0.0))', 'screen_space_specular_transmission_steps: 0)',
'UnitTest': '()', 'bevy_core_pipeline::fxaa::Fxaa': '(edge_threshold: "", edge_threshold_min: "", enabled: true)',
'VecOfColors': '([])', 'bevy_core_pipeline::tonemapping::DebandDither': 'Disabled',
'VecOfF32s': '([])', 'bevy_core_pipeline::tonemapping::Tonemapping': 'None',
'VecOfVec3s2': '([])', 'bevy_example::dupe_components::EnumTest': 'Metal',
'Velocity': '(angvel: Vec3(x:0.0, y:0.0, z:0.0), linvel: Vec3(x:0.0, y:0.0, z:0.0))', 'bevy_example::game::animation::Marker1': '()',
'ViewVisibility': '(true)', 'bevy_example::game::animation::Marker2': '()',
'Visibility': 'Inherited', 'bevy_example::game::animation::Marker3': '()',
'VisibleEntities': '()', 'bevy_example::game::animation::MarkerFox': '()',
'Window': '(canvas: None, composite_alpha_mode: Auto, cursor: (grab_mode: None, hit_test: true, icon: Default, ' 'bevy_example::test_components::AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut': '()',
'visible: true), decorations: true, enabled_buttons: (close: true, maximize: true, minimize: true), ' 'bevy_example::test_components::BasicTest': '(a: 0.0, b: 0, c: " ")',
'focused: true, ime_enabled: true, ime_position: Vec2(x:0.0, y:0.0), internal: (maximize_request: None, ' 'bevy_example::test_components::EnumComplex': 'Float(0.0)',
'minimize_request: None, physical_cursor_position: None), mode: Windowed, name: None, position: Automatic, ' 'bevy_example::test_components::EnumTest': 'Metal',
'present_mode: AutoVsync, prevent_default_event_handling: true, resizable: true, resize_constraints: ' 'bevy_example::test_components::HashmapTestIntColor': '(inner: {})',
'(max_height: 0.0, max_width: 0.0, min_height: 0.0, min_width: 0.0), resolution: (physical_height: 0, ' 'bevy_example::test_components::HashmapTestIntString': '(named_animations: {})',
'physical_width: 0, scale_factor: 0.0, scale_factor_override: None), title: " ", transparent: true, ' 'bevy_example::test_components::HashmapTestSimple': '(named_animations: {})',
'visible: true, window_level: AlwaysOnBottom, window_theme: "")', 'bevy_example::test_components::HashmapTestStringColor': '(inner: {})',
'Wireframe': '()', 'bevy_example::test_components::HashmapTestStringColorFlat': '({})',
'WireframeColor': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))', 'bevy_example::test_components::HashmapTestStringFloat': '(named_animations: {})',
'ZIndex': 'Local(0)'} 'bevy_example::test_components::NestedTupleStuff': '(0.0, 0, (basic: (a: 0.0, b: 0, c: " "), color: (Rgba(red:1.0, '
'green:1.0, blue:0.0, alpha:1.0)), colors_list: ([]), enable: '
'true, enum_inner: Metal, nested: (vec: (Vec3(x:0.0, y:0.0, '
'z:0.0))), text: " ", toggle: (true)))',
'bevy_example::test_components::NestingTestLevel2': '(basic: (a: 0.0, b: 0, c: " "), color: (Rgba(red:1.0, green:1.0, '
expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut': '()', 'blue:0.0, alpha:1.0)), colors_list: ([]), enable: true, '
'Aabb': '(center: Vec3A(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), half_extents: ' 'enum_inner: Metal, nested: (vec: (Vec3(x:0.0, y:0.0, z:0.0))), '
'Vec3A(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))', 'text: " ", toggle: (true))',
'AdditionalMassProperties': 'Mass(0.42888906598091125)', 'bevy_example::test_components::NestingTestLevel3': '(vec: (Vec3(x:0.0, y:0.0, z:0.0)))',
'AnimationPlayer': '(animation: "", paused: true)', 'bevy_example::test_components::TupleTest2': '(0.0, 0, " ")',
'Animations': '(named_animations: "")', 'bevy_example::test_components::TupleTestBool': '(true)',
'AutoAABBCollider': 'Capsule', 'bevy_example::test_components::TupleTestColor': '(Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))',
'BackgroundColor': '(Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_example::test_components::TupleTestF32': '(0.0)',
'alpha:0.20609822869300842))', 'bevy_example::test_components::TupleTestStr': '(" ")',
'BasicTest': '(a: 0.5714026093482971, b: 54, c: "psagopiu")', 'bevy_example::test_components::TupleTestU64': '(0)',
'BlenderBackgroundShader': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_example::test_components::TupleVec': '([])',
'alpha:0.20609822869300842), strength: 0.8133212327957153)', 'bevy_example::test_components::TupleVec2': '(Vec2(x:0.0, y:0.0))',
'BlenderLightShadows': '(buffer_bias: 0.5714026093482971, enabled: false)', 'bevy_example::test_components::TupleVec3': '(Vec3(x:0.0, y:0.0, z:0.0))',
'BlenderShadowSettings': '(cascade_size: 73)', 'bevy_example::test_components::TupleVecF32F32': '([])',
'BloomSettings': '(composite_mode: EnergyConserving, high_pass_frequency: 0.42888906598091125, intensity: ' 'bevy_example::test_components::UnitTest': '()',
'0.5780913233757019, low_frequency_boost: 0.20609822869300842, low_frequency_boost_curvature: ' 'bevy_example::test_components::VecOfColors': '([])',
'0.8133212327957153, prefilter_settings: (threshold: 0.8235888481140137, threshold_softness: ' 'bevy_example::test_components::VecOfF32s': '([])',
'0.6534725427627563))', 'bevy_example::test_components::VecOfVec3s2': '([])',
'BlueprintName': '("sbnpsago")', 'bevy_gltf::GltfExtras': '(value: " ")',
'BlueprintsList': '("")', 'bevy_gltf_blueprints::animation::AnimationInfos': '(animations: [])',
'BorderColor': '(Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_gltf_blueprints::animation::AnimationMarkers': '({})',
'alpha:0.20609822869300842))', 'bevy_gltf_blueprints::animation::BlueprintAnimations': '(named_animations: "")',
'Button': '()', 'bevy_gltf_blueprints::animation::SceneAnimations': '(named_animations: "")',
'CalculatedClip': '(clip: (max: Vec2(x:0.5714026093482971, y:0.42888906598091125), min: Vec2(x:0.5780913233757019, ' 'bevy_gltf_blueprints::materials::MaterialInfo': '(name: " ", source: " ")',
'y:0.20609822869300842)))', 'bevy_gltf_blueprints::spawn_from_blueprints::BlueprintName': '(" ")',
'Camera': '(clear_color: None, hdr: false, is_active: false, msaa_writeback: false, order: 73, viewport: None)', 'bevy_gltf_blueprints::spawn_from_blueprints::BlueprintsList': '({})',
'Camera2d': '()', 'bevy_gltf_blueprints::spawn_from_blueprints::SpawnHere': '()',
'Camera3d': '(depth_load_op: Clear(0.42888906598091125), depth_texture_usages: (73), ' 'bevy_gltf_components::GltfProcessed': '()',
'screen_space_specular_transmission_quality: Low, screen_space_specular_transmission_steps: 26)', 'bevy_gltf_components::blender_settings::lighting::BlenderBackgroundShader': '(color: Rgba(red:1.0, green:1.0, '
'CameraMainTextureUsages': 'None', 'blue:0.0, alpha:1.0), strength: 0.0)',
'CameraRenderGraph': 'None', 'bevy_gltf_components::blender_settings::lighting::BlenderLightShadows': '(buffer_bias: 0.0, enabled: true)',
'CameraTrackable': '()', 'bevy_gltf_components::blender_settings::lighting::BlenderShadowSettings': '(cascade_size: 0)',
'CameraTracking': '(offset: Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019))', 'bevy_gltf_worlflow_examples_common::core::camera::camera_replace_proxies::SSAOSettings': '()',
'CameraTrackingOffset': '(Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019))', 'bevy_gltf_worlflow_examples_common::core::camera::camera_tracking::CameraTrackable': '()',
'CascadeShadowConfig': '(bounds: [0.42888906598091125], minimum_distance: 0.5780913233757019, overlap_proportion: ' 'bevy_gltf_worlflow_examples_common::core::camera::camera_tracking::CameraTracking': '(offset: Vec3(x:0.0, y:0.0, '
'0.20609822869300842)', 'z:0.0))',
'Cascades': '(cascades: "")', 'bevy_gltf_worlflow_examples_common::core::camera::camera_tracking::CameraTrackingOffset': '(Vec3(x:0.0, y:0.0, '
'CascadesFrusta': '()', 'z:0.0))',
'CascadesVisibleEntities': '()', 'bevy_gltf_worlflow_examples_common::game::picking::Pickable': '()',
'Ccd': '(enabled: true)', 'bevy_gltf_worlflow_examples_common::game::player::Player': '()',
'Children': '([0])', 'bevy_gltf_worlflow_examples_common_rapier::physics::physics_replace_proxies::AutoAABBCollider': 'Cuboid',
'ClusterConfig': 'None', 'bevy_gltf_worlflow_examples_common_rapier::physics::physics_replace_proxies::Collider': 'Ball(0.0)',
'Collider': 'Ball(0.42888906598091125)', 'bevy_hierarchy::components::children::Children': '([])',
'CollidingEntities': '("")', 'bevy_hierarchy::components::parent::Parent': '(0)',
'CollisionGroups': '(filters: (73), memberships: (4))', 'bevy_pbr::bundle::CascadesVisibleEntities': '()',
'ColorGrading': '(exposure: 0.5714026093482971, gamma: 0.42888906598091125, post_saturation: 0.5780913233757019, ' 'bevy_pbr::bundle::CubemapVisibleEntities': '()',
'pre_saturation: 0.20609822869300842)', 'bevy_pbr::fog::FogSettings': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), directional_light_color: '
'ContactForceEventThreshold': '(0.5714026093482971)', 'Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), directional_light_exponent: 0.0, '
'ContentSize': '()', 'falloff: Linear(end: 0.0, start: 0.0))',
'ContrastAdaptiveSharpeningSettings': '(denoise: true, enabled: false, sharpening_strength: 0.42888906598091125)', 'bevy_pbr::light::CascadeShadowConfig': '(bounds: [], minimum_distance: 0.0, overlap_proportion: 0.0)',
'CubemapFrusta': '()', 'bevy_pbr::light::Cascades': '(cascades: "")',
'CubemapVisibleEntities': '()', 'bevy_pbr::light::ClusterConfig': 'None',
'Damping': '(angular_damping: 0.5714026093482971, linear_damping: 0.42888906598091125)', 'bevy_pbr::light::DirectionalLight': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), illuminance: 0.0, '
'DebandDither': 'Disabled', 'shadow_depth_bias: 0.0, shadow_normal_bias: 0.0, shadows_enabled: true)',
'DirectionalLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_pbr::light::NotShadowCaster': '()',
'alpha:0.20609822869300842), illuminance: 0.8133212327957153, shadow_depth_bias: ' 'bevy_pbr::light::NotShadowReceiver': '()',
'0.8235888481140137, shadow_normal_bias: 0.6534725427627563, shadows_enabled: false)', 'bevy_pbr::light::PointLight': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), intensity: 0.0, radius: 0.0, '
'Dominance': '(groups: 73)', 'range: 0.0, shadow_depth_bias: 0.0, shadow_normal_bias: 0.0, shadows_enabled: true)',
'EnumComplex': 'StructLike(a: 0.03258506581187248, b: 61, c: "sagopiuz")', 'bevy_pbr::light::ShadowFilteringMethod': 'Hardware2x2',
'EnumTest': 'Squishy', 'bevy_pbr::light::SpotLight': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), inner_angle: 0.0, intensity: '
'Exposure': 'None', '0.0, outer_angle: 0.0, radius: 0.0, range: 0.0, shadow_depth_bias: 0.0, '
'ExternalForce': '(force: Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), torque: ' 'shadow_normal_bias: 0.0, shadows_enabled: true)',
'Vec3(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))', 'bevy_pbr::light_probe::LightProbe': '()',
'ExternalImpulse': '(impulse: Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), ' 'bevy_pbr::ssao::ScreenSpaceAmbientOcclusionSettings': '(quality_level: "")',
'torque_impulse: Vec3(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))', 'bevy_pbr::wireframe::NoWireframe': '()',
'FocusPolicy': 'Block', 'bevy_pbr::wireframe::Wireframe': '()',
'FogSettings': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_pbr::wireframe::WireframeColor': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))',
'alpha:0.20609822869300842), directional_light_color: Rgba(red:0.8133212327957153, ' 'bevy_rapier3d::dynamics::rigid_body::AdditionalMassProperties': 'Mass(0.0)',
'green:0.8235888481140137, blue:0.6534725427627563, alpha:0.16022956371307373), ' 'bevy_rapier3d::dynamics::rigid_body::Ccd': '(enabled: true)',
'directional_light_exponent: 0.5206693410873413, falloff: ExponentialSquared(density: ' 'bevy_rapier3d::dynamics::rigid_body::Damping': '(angular_damping: 0.0, linear_damping: 0.0)',
'0.07608934491872787))', 'bevy_rapier3d::dynamics::rigid_body::Dominance': '(groups: 0)',
'Friction': '(coefficient: 0.5714026093482971, combine_rule: "")', 'bevy_rapier3d::dynamics::rigid_body::ExternalForce': '(force: Vec3(x:0.0, y:0.0, z:0.0), torque: Vec3(x:0.0, y:0.0, '
'Frustum': '()', 'z:0.0))',
'Fxaa': '(edge_threshold: "", edge_threshold_min: "", enabled: true)', 'bevy_rapier3d::dynamics::rigid_body::ExternalImpulse': '(impulse: Vec3(x:0.0, y:0.0, z:0.0), torque_impulse: '
'GlobalTransform': '((matrix3: (x_axis: Vec3A(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), ' 'Vec3(x:0.0, y:0.0, z:0.0))',
'y_axis: Vec3A(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137), z_axis: ' 'bevy_rapier3d::dynamics::rigid_body::GravityScale': '(0.0)',
'Vec3A(x:0.6534725427627563, y:0.16022956371307373, z:0.5206693410873413)), translation: ' 'bevy_rapier3d::dynamics::rigid_body::LockedAxes': '(0)',
'Vec3A(x:0.3277728259563446, y:0.24999667704105377, z:0.952816903591156)))', 'bevy_rapier3d::dynamics::rigid_body::RigidBody': 'Dynamic',
'GltfExtras': '(value: "sbnpsago")', 'bevy_rapier3d::dynamics::rigid_body::Sleeping': '(angular_threshold: 0.0, linear_threshold: 0.0, sleeping: true)',
'GltfProcessed': '()', 'bevy_rapier3d::dynamics::rigid_body::Velocity': '(angvel: Vec3(x:0.0, y:0.0, z:0.0), linvel: Vec3(x:0.0, y:0.0, '
'GravityScale': '(0.5714026093482971)', 'z:0.0))',
'Group': '(73)', 'bevy_rapier3d::geometry::collider::CollidingEntities': '("")',
'Handle<()>': 'Strong("")', 'bevy_rapier3d::geometry::collider::CollisionGroups': '(filters: (0), memberships: (0))',
'Handle<AnimationClip>': 'Strong("")', 'bevy_rapier3d::geometry::collider::ContactForceEventThreshold': '(0.0)',
'Handle<AudioSource>': 'Strong("")', 'bevy_rapier3d::geometry::collider::Friction': '(coefficient: 0.0, combine_rule: "")',
'Handle<ColorMaterial>': 'Strong("")', 'bevy_rapier3d::geometry::collider::Group': '(0)',
'Handle<DynamicScene>': 'Strong("")', 'bevy_rapier3d::geometry::collider::Restitution': '(coefficient: 0.0, combine_rule: "")',
'Handle<ExtendedMaterial<StandardMaterial, MyExtension>>': 'Strong("")', 'bevy_rapier3d::geometry::collider::Sensor': '()',
'Handle<Font>': 'Strong("")', 'bevy_rapier3d::geometry::collider::SolverGroups': '(filters: (0), memberships: (0))',
'Handle<Gltf>': 'Strong("")', 'bevy_render::camera::camera::Camera': '(clear_color: Default, hdr: true, is_active: true, msaa_writeback: true, '
'Handle<GltfMesh>': 'Strong("")', 'order: 0, viewport: None)',
'Handle<GltfNode>': 'Strong("")', 'bevy_render::camera::camera::CameraMainTextureUsages': 'None',
'Handle<GltfPrimitive>': 'Strong("")', 'bevy_render::camera::camera::CameraRenderGraph': 'None',
'Handle<Image>': 'Strong("")', 'bevy_render::camera::camera::Exposure': 'None',
'Handle<LineGizmo>': 'Strong("")', 'bevy_render::camera::projection::OrthographicProjection': '(area: (max: Vec2(x:0.0, y:0.0), min: Vec2(x:0.0, '
'Handle<LoadedFolder>': 'Strong("")', 'y:0.0)), far: 0.0, near: 0.0, scale: 0.0, scaling_mode: '
'Handle<LoadedUntypedAsset>': 'Strong("")', 'Fixed(height: 0.0, width: 0.0), viewport_origin: '
'Handle<Mesh>': 'Strong("")', 'Vec2(x:0.0, y:0.0))',
'Handle<Pitch>': 'Strong("")', 'bevy_render::camera::projection::PerspectiveProjection': '(aspect_ratio: 0.0, far: 0.0, fov: 0.0, near: 0.0)',
'Handle<Scene>': 'Strong("")', 'bevy_render::camera::projection::Projection': 'Perspective((aspect_ratio: 0.0, far: 0.0, fov: 0.0, near: 0.0))',
'Handle<Shader>': 'Strong("")', 'bevy_render::mesh::mesh::skinning::SkinnedMesh': '(inverse_bindposes: Strong(""), joints: [])',
'Handle<SkinnedMeshInverseBindposes>': 'Strong("")', 'bevy_render::mesh::morph::MeshMorphWeights': '(weights: [])',
'Handle<StandardDynamicAssetCollection>': 'Strong("")', 'bevy_render::mesh::morph::MorphWeights': '(first_mesh: "", weights: [])',
'Handle<StandardMaterial>': 'Strong("")', 'bevy_render::primitives::Aabb': '(center: Vec3A(x:0.0, y:0.0, z:0.0), half_extents: Vec3A(x:0.0, y:0.0, z:0.0))',
'Handle<TextureAtlasLayout>': 'Strong("")', 'bevy_render::primitives::CascadesFrusta': '()',
'Handle<WireframeMaterial>': 'Strong("")', 'bevy_render::primitives::CubemapFrusta': '()',
'ImageScaleMode': 'Sliced((border: "", center_scale_mode: "", max_corner_scale: 0.42888906598091125, ' 'bevy_render::primitives::Frustum': '()',
'bevy_render::view::ColorGrading': '(exposure: 0.0, gamma: 0.0, post_saturation: 0.0, pre_saturation: 0.0)',
'bevy_render::view::visibility::InheritedVisibility': '(true)',
'bevy_render::view::visibility::NoFrustumCulling': '()',
'bevy_render::view::visibility::ViewVisibility': '(true)',
'bevy_render::view::visibility::Visibility': 'Inherited',
'bevy_render::view::visibility::VisibleEntities': '()',
'bevy_render::view::visibility::render_layers::RenderLayers': '(0)',
'bevy_sprite::mesh2d::mesh::Mesh2dHandle': '(Strong(""))',
'bevy_sprite::sprite::ImageScaleMode': 'Sliced((border: "", center_scale_mode: "", max_corner_scale: 0.0, '
'sides_scale_mode: ""))', 'sides_scale_mode: ""))',
'InheritedVisibility': '(true)', 'bevy_sprite::sprite::Sprite': '(anchor: Center, color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), custom_size: '
'Interaction': 'None', '"", flip_x: true, flip_y: true, rect: "")',
'Label': '()', 'bevy_text::pipeline::TextLayoutInfo': '(glyphs: "", logical_size: Vec2(x:0.0, y:0.0))',
'LightProbe': '()', 'bevy_text::text2d::Text2dBounds': '(size: Vec2(x:0.0, y:0.0))',
'LockedAxes': '(73)', 'bevy_text::text::Text': '(justify: Left, linebreak_behavior: WordBoundary, sections: [])',
'MaterialInfo': '(name: "sbnpsago", source: "piuzfbqp")', 'bevy_transform::components::global_transform::GlobalTransform': '((matrix3: (x_axis: Vec3A(x:0.0, y:0.0, z:0.0), '
'Mesh2dHandle': '(Strong(""))', 'y_axis: Vec3A(x:0.0, y:0.0, z:0.0), z_axis: '
'MeshMorphWeights': '(weights: [0.42888906598091125])', 'Vec3A(x:0.0, y:0.0, z:0.0)), translation: '
'MorphWeights': '(first_mesh: "", weights: [0.42888906598091125])', 'Vec3A(x:0.0, y:0.0, z:0.0)))',
'Name': '(hash: 73, name: "bnpsagop")', 'bevy_transform::components::transform::Transform': '(rotation: Quat(x:0.0, y:0.0, z:0.0, w:0.0), scale: Vec3(x:0.0, '
'NestedTupleStuff': '(0.5714026093482971, 54, (basic: (a: 0.4825616776943207, b: 1, c: "gopiuzfb"), color: ' 'y:0.0, z:0.0), translation: Vec3(x:0.0, y:0.0, z:0.0))',
'(Rgba(red:0.5206693410873413, green:0.3277728259563446, blue:0.24999667704105377, ' 'bevy_ui::focus::FocusPolicy': 'Block',
'alpha:0.952816903591156)), colors_list: ([Rgba(red:0.0445563830435276, green:0.8601610660552979, ' 'bevy_ui::focus::Interaction': 'Pressed',
'blue:0.6031906008720398, alpha:0.38160598278045654), Rgba(red:0.2836182117462158, ' 'bevy_ui::focus::RelativeCursorPosition': '(normalized: "", normalized_visible_node_rect: (max: Vec2(x:0.0, y:0.0), '
'green:0.6749648451805115, blue:0.456831157207489, alpha:0.6858614683151245)]), enable: true, ' 'min: Vec2(x:0.0, y:0.0)))',
'enum_inner: Rock, nested: (vec: (Vec3(x:0.1329781413078308, y:0.7678378224372864, ' 'bevy_ui::measurement::ContentSize': '()',
'z:0.9824132323265076))), text: "otmbsahe", toggle: (false)))', 'bevy_ui::ui_node::BackgroundColor': '(Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))',
'NestingTestLevel2': '(basic: (a: 0.5714026093482971, b: 54, c: "psagopiu"), color: (Rgba(red:0.8106188178062439, ' 'bevy_ui::ui_node::BorderColor': '(Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))',
'green:0.03440357372164726, blue:0.49008557200431824, alpha:0.07608934491872787)), colors_list: ' 'bevy_ui::ui_node::CalculatedClip': '(clip: (max: Vec2(x:0.0, y:0.0), min: Vec2(x:0.0, y:0.0)))',
'([Rgba(red:0.0445563830435276, green:0.8601610660552979, blue:0.6031906008720398, ' 'bevy_ui::ui_node::Node': '(calculated_size: Vec2(x:0.0, y:0.0), outline_offset: 0.0, outline_width: 0.0, '
'alpha:0.38160598278045654), Rgba(red:0.2836182117462158, green:0.6749648451805115, ' 'stack_index: 0, unrounded_size: Vec2(x:0.0, y:0.0))',
'blue:0.456831157207489, alpha:0.6858614683151245)]), enable: true, enum_inner: Rock, nested: ' 'bevy_ui::ui_node::Outline': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), offset: Auto, width: Auto)',
'(vec: (Vec3(x:0.1329781413078308, y:0.7678378224372864, z:0.9824132323265076))), text: ' 'bevy_ui::ui_node::Style': '(align_content: Default, align_items: Default, align_self: Auto, aspect_ratio: None, '
'"otmbsahe", toggle: (false))', 'border: (bottom: Auto, left: Auto, right: Auto, top: Auto), bottom: Auto, column_gap: '
'NestingTestLevel3': '(vec: (Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019)))', 'Auto, direction: Inherit, display: Flex, flex_basis: Auto, flex_direction: Row, '
'NoFrustumCulling': '()', 'flex_grow: 0.0, flex_shrink: 0.0, flex_wrap: NoWrap, grid_auto_columns: "", '
'NoWireframe': '()', 'grid_auto_flow: Row, grid_auto_rows: "", grid_column: (end: "", span: "", start: ""), '
'Node': '(calculated_size: Vec2(x:0.5714026093482971, y:0.42888906598091125), outline_offset: 0.5780913233757019, ' 'grid_row: (end: "", span: "", start: ""), grid_template_columns: "", grid_template_rows: '
'outline_width: 0.20609822869300842, stack_index: 62, unrounded_size: Vec2(x:0.8235888481140137, ' '"", height: Auto, justify_content: Default, justify_items: Default, justify_self: Auto, '
'y:0.6534725427627563))', 'left: Auto, margin: (bottom: Auto, left: Auto, right: Auto, top: Auto), max_height: Auto, '
'NotShadowCaster': '()', 'max_width: Auto, min_height: Auto, min_width: Auto, overflow: (x: Visible, y: Visible), '
'NotShadowReceiver': '()', 'padding: (bottom: Auto, left: Auto, right: Auto, top: Auto), position_type: Relative, '
'OrthographicProjection': '(area: (max: Vec2(x:0.5714026093482971, y:0.42888906598091125), min: ' 'right: Auto, row_gap: Auto, top: Auto, width: Auto)',
'Vec2(x:0.5780913233757019, y:0.20609822869300842)), far: 0.8133212327957153, near: ' 'bevy_ui::ui_node::UiImage': '(flip_x: true, flip_y: true, texture: Strong(""))',
'0.8235888481140137, scale: 0.6534725427627563, scaling_mode: ' 'bevy_ui::ui_node::ZIndex': 'Local(0)',
'WindowSize(0.03440357372164726), viewport_origin: Vec2(x:0.49008557200431824, ' 'bevy_ui::widget::button::Button': '()',
'bevy_ui::widget::image::UiImageSize': '(size: Vec2(x:0.0, y:0.0))',
'bevy_ui::widget::label::Label': '()',
'bevy_ui::widget::text::TextFlags': '(needs_new_measure_func: true, needs_recompute: true)',
'bevy_window::window::PrimaryWindow': '()',
'bevy_window::window::Window': '(canvas: None, composite_alpha_mode: Auto, cursor: (grab_mode: None, hit_test: true, '
'icon: Default, visible: true), decorations: true, enabled_buttons: (close: true, '
'maximize: true, minimize: true), focused: true, ime_enabled: true, ime_position: '
'Vec2(x:0.0, y:0.0), internal: (maximize_request: None, minimize_request: None, '
'physical_cursor_position: None), mode: Windowed, name: None, position: Automatic, '
'present_mode: AutoVsync, prevent_default_event_handling: true, resizable: true, '
'resize_constraints: (max_height: 0.0, max_width: 0.0, min_height: 0.0, min_width: '
'0.0), resolution: (physical_height: 0, physical_width: 0, scale_factor: 0.0, '
'scale_factor_override: None), title: " ", transparent: true, visible: true, '
'window_level: AlwaysOnBottom, window_theme: "")'}
expected_custom_property_values_randomized = {'bevy_animation::AnimationPlayer': '(animation: "", paused: true)',
'bevy_asset::handle::Handle<()>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_animation::AnimationClip>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_asset::assets::LoadedUntypedAsset>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_asset::folder::LoadedFolder>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_asset_loader::standard_dynamic_asset::StandardDynamicAssetCollection>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_audio::audio_source::AudioSource>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_audio::pitch::Pitch>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_gizmos::LineGizmo>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_gltf::Gltf>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_gltf::GltfMesh>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_gltf::GltfNode>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_gltf::GltfPrimitive>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_pbr::extended_material::ExtendedMaterial<bevy_pbr::pbr_material::StandardMaterial, bevy_example::test_components::MyExtension>>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_pbr::pbr_material::StandardMaterial>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_pbr::wireframe::WireframeMaterial>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_render::mesh::mesh::Mesh>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_render::mesh::mesh::skinning::SkinnedMeshInverseBindposes>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_render::render_resource::shader::Shader>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_render::texture::image::Image>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_scene::dynamic_scene::DynamicScene>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_scene::scene::Scene>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_sprite::mesh2d::color_material::ColorMaterial>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_sprite::texture_atlas::TextureAtlasLayout>': 'Strong("")',
'bevy_asset::handle::Handle<bevy_text::font::Font>': 'Strong("")',
'bevy_audio::audio::PlaybackSettings': '(mode: Once, paused: false, spatial: false, spatial_scale: "", speed: '
'0.5780913233757019, volume: (0.20609822869300842))',
'bevy_audio::audio::SpatialListener': '(left_ear_offset: Vec3(x:0.5714026093482971, y:0.42888906598091125, '
'z:0.5780913233757019), right_ear_offset: Vec3(x:0.20609822869300842, '
'y:0.8133212327957153, z:0.8235888481140137))',
'bevy_core::name::Name': '(hash: 73, name: "bnpsagop")',
'bevy_core_pipeline::bloom::settings::BloomSettings': '(composite_mode: EnergyConserving, high_pass_frequency: '
'0.42888906598091125, intensity: 0.5780913233757019, '
'low_frequency_boost: 0.20609822869300842, '
'low_frequency_boost_curvature: 0.8133212327957153, '
'prefilter_settings: (threshold: 0.8235888481140137, '
'threshold_softness: 0.6534725427627563))',
'bevy_core_pipeline::contrast_adaptive_sharpening::ContrastAdaptiveSharpeningSettings': '(denoise: true, enabled: '
'false, sharpening_strength: '
'0.42888906598091125)',
'bevy_core_pipeline::core_2d::camera_2d::Camera2d': '()',
'bevy_core_pipeline::core_3d::camera_3d::Camera3d': '(depth_load_op: Clear(0.42888906598091125), '
'depth_texture_usages: (73), '
'screen_space_specular_transmission_quality: Low, '
'screen_space_specular_transmission_steps: 26)',
'bevy_core_pipeline::fxaa::Fxaa': '(edge_threshold: "", edge_threshold_min: "", enabled: true)',
'bevy_core_pipeline::tonemapping::DebandDither': 'Disabled',
'bevy_core_pipeline::tonemapping::Tonemapping': 'None',
'bevy_example::dupe_components::EnumTest': 'Squishy',
'bevy_example::game::animation::Marker1': '()',
'bevy_example::game::animation::Marker2': '()',
'bevy_example::game::animation::Marker3': '()',
'bevy_example::game::animation::MarkerFox': '()',
'bevy_example::test_components::AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut': '()',
'bevy_example::test_components::BasicTest': '(a: 0.5714026093482971, b: 54, c: "psagopiu")',
'bevy_example::test_components::EnumComplex': 'StructLike(a: 0.03258506581187248, b: 61, c: "sagopiuz")',
'bevy_example::test_components::EnumTest': 'Squishy',
'bevy_example::test_components::HashmapTestIntColor': '(inner: {})',
'bevy_example::test_components::HashmapTestIntString': '(named_animations: {})',
'bevy_example::test_components::HashmapTestSimple': '(named_animations: {})',
'bevy_example::test_components::HashmapTestStringColor': '(inner: {})',
'bevy_example::test_components::HashmapTestStringColorFlat': '({})',
'bevy_example::test_components::HashmapTestStringFloat': '(named_animations: {})',
'bevy_example::test_components::NestedTupleStuff': '(0.5714026093482971, 54, (basic: (a: 0.4825616776943207, b: 1, c: '
'"gopiuzfb"), color: (Rgba(red:0.5206693410873413, '
'green:0.3277728259563446, blue:0.24999667704105377, '
'alpha:0.952816903591156)), colors_list: '
'([Rgba(red:0.0445563830435276, green:0.8601610660552979, '
'blue:0.6031906008720398, alpha:0.38160598278045654), '
'Rgba(red:0.2836182117462158, green:0.6749648451805115, '
'blue:0.456831157207489, alpha:0.6858614683151245)]), enable: '
'true, enum_inner: Rock, nested: (vec: (Vec3(x:0.1329781413078308, '
'y:0.7678378224372864, z:0.9824132323265076))), text: "otmbsahe", '
'toggle: (false)))',
'bevy_example::test_components::NestingTestLevel2': '(basic: (a: 0.5714026093482971, b: 54, c: "psagopiu"), color: '
'(Rgba(red:0.8106188178062439, green:0.03440357372164726, '
'blue:0.49008557200431824, alpha:0.07608934491872787)), '
'colors_list: ([Rgba(red:0.0445563830435276, '
'green:0.8601610660552979, blue:0.6031906008720398, '
'alpha:0.38160598278045654), Rgba(red:0.2836182117462158, '
'green:0.6749648451805115, blue:0.456831157207489, '
'alpha:0.6858614683151245)]), enable: true, enum_inner: Rock, '
'nested: (vec: (Vec3(x:0.1329781413078308, y:0.7678378224372864, '
'z:0.9824132323265076))), text: "otmbsahe", toggle: (false))',
'bevy_example::test_components::NestingTestLevel3': '(vec: (Vec3(x:0.5714026093482971, y:0.42888906598091125, '
'z:0.5780913233757019)))',
'bevy_example::test_components::TupleTest2': '(0.5714026093482971, 54, "psagopiu")',
'bevy_example::test_components::TupleTestBool': '(true)',
'bevy_example::test_components::TupleTestColor': '(Rgba(red:0.5714026093482971, green:0.42888906598091125, '
'blue:0.5780913233757019, alpha:0.20609822869300842))',
'bevy_example::test_components::TupleTestF32': '(0.5714026093482971)',
'bevy_example::test_components::TupleTestStr': '("sbnpsago")',
'bevy_example::test_components::TupleTestU64': '(73)',
'bevy_example::test_components::TupleVec': '(["npsagopi"])',
'bevy_example::test_components::TupleVec2': '(Vec2(x:0.5714026093482971, y:0.42888906598091125))',
'bevy_example::test_components::TupleVec3': '(Vec3(x:0.5714026093482971, y:0.42888906598091125, '
'z:0.5780913233757019))',
'bevy_example::test_components::TupleVecF32F32': '([(0.42888906598091125, 0.5780913233757019)])',
'bevy_example::test_components::UnitTest': '()',
'bevy_example::test_components::VecOfColors': '([Rgba(red:0.42888906598091125, green:0.5780913233757019, '
'blue:0.20609822869300842, alpha:0.8133212327957153)])',
'bevy_example::test_components::VecOfF32s': '([0.42888906598091125])',
'bevy_example::test_components::VecOfVec3s2': '([(Vec3(x:0.42888906598091125, y:0.5780913233757019, '
'z:0.20609822869300842))])',
'bevy_gltf::GltfExtras': '(value: "sbnpsago")',
'bevy_gltf_blueprints::animation::AnimationInfos': '(animations: [(frame_end: 0.42888906598091125, '
'frame_end_override: 0.5780913233757019, frame_start: '
'0.20609822869300842, frame_start_override: 0.8133212327957153, '
'frames_length: 0.8235888481140137, name: "uzfbqpkc")])',
'bevy_gltf_blueprints::animation::AnimationMarkers': '({})',
'bevy_gltf_blueprints::animation::BlueprintAnimations': '(named_animations: "")',
'bevy_gltf_blueprints::animation::SceneAnimations': '(named_animations: "")',
'bevy_gltf_blueprints::materials::MaterialInfo': '(name: "sbnpsago", source: "piuzfbqp")',
'bevy_gltf_blueprints::spawn_from_blueprints::BlueprintName': '("sbnpsago")',
'bevy_gltf_blueprints::spawn_from_blueprints::BlueprintsList': '({})',
'bevy_gltf_blueprints::spawn_from_blueprints::SpawnHere': '()',
'bevy_gltf_components::GltfProcessed': '()',
'bevy_gltf_components::blender_settings::lighting::BlenderBackgroundShader': '(color: Rgba(red:0.5714026093482971, '
'green:0.42888906598091125, '
'blue:0.5780913233757019, '
'alpha:0.20609822869300842), strength: '
'0.8133212327957153)',
'bevy_gltf_components::blender_settings::lighting::BlenderLightShadows': '(buffer_bias: 0.5714026093482971, enabled: '
'false)',
'bevy_gltf_components::blender_settings::lighting::BlenderShadowSettings': '(cascade_size: 73)',
'bevy_gltf_worlflow_examples_common::core::camera::camera_replace_proxies::SSAOSettings': '()',
'bevy_gltf_worlflow_examples_common::core::camera::camera_tracking::CameraTrackable': '()',
'bevy_gltf_worlflow_examples_common::core::camera::camera_tracking::CameraTracking': '(offset: '
'Vec3(x:0.5714026093482971, '
'y:0.42888906598091125, '
'z:0.5780913233757019))',
'bevy_gltf_worlflow_examples_common::core::camera::camera_tracking::CameraTrackingOffset': '(Vec3(x:0.5714026093482971, '
'y:0.42888906598091125, '
'z:0.5780913233757019))',
'bevy_gltf_worlflow_examples_common::game::picking::Pickable': '()',
'bevy_gltf_worlflow_examples_common::game::player::Player': '()',
'bevy_gltf_worlflow_examples_common_rapier::physics::physics_replace_proxies::AutoAABBCollider': 'Capsule',
'bevy_gltf_worlflow_examples_common_rapier::physics::physics_replace_proxies::Collider': 'Ball(0.42888906598091125)',
'bevy_hierarchy::components::children::Children': '([0])',
'bevy_hierarchy::components::parent::Parent': '(0)',
'bevy_pbr::bundle::CascadesVisibleEntities': '()',
'bevy_pbr::bundle::CubemapVisibleEntities': '()',
'bevy_pbr::fog::FogSettings': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, '
'blue:0.5780913233757019, alpha:0.20609822869300842), directional_light_color: '
'Rgba(red:0.8133212327957153, green:0.8235888481140137, blue:0.6534725427627563, '
'alpha:0.16022956371307373), directional_light_exponent: 0.5206693410873413, falloff: '
'ExponentialSquared(density: 0.07608934491872787))',
'bevy_pbr::light::CascadeShadowConfig': '(bounds: [0.42888906598091125], minimum_distance: 0.5780913233757019, '
'overlap_proportion: 0.20609822869300842)',
'bevy_pbr::light::Cascades': '(cascades: "")',
'bevy_pbr::light::ClusterConfig': 'None',
'bevy_pbr::light::DirectionalLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, '
'blue:0.5780913233757019, alpha:0.20609822869300842), illuminance: '
'0.8133212327957153, shadow_depth_bias: 0.8235888481140137, shadow_normal_bias: '
'0.6534725427627563, shadows_enabled: false)',
'bevy_pbr::light::NotShadowCaster': '()',
'bevy_pbr::light::NotShadowReceiver': '()',
'bevy_pbr::light::PointLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, '
'blue:0.5780913233757019, alpha:0.20609822869300842), intensity: 0.8133212327957153, '
'radius: 0.8235888481140137, range: 0.6534725427627563, shadow_depth_bias: '
'0.16022956371307373, shadow_normal_bias: 0.5206693410873413, shadows_enabled: false)',
'bevy_pbr::light::ShadowFilteringMethod': 'Jimenez14',
'bevy_pbr::light::SpotLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, '
'blue:0.5780913233757019, alpha:0.20609822869300842), inner_angle: 0.8133212327957153, '
'intensity: 0.8235888481140137, outer_angle: 0.6534725427627563, radius: '
'0.16022956371307373, range: 0.5206693410873413, shadow_depth_bias: 0.3277728259563446, '
'shadow_normal_bias: 0.24999667704105377, shadows_enabled: true)',
'bevy_pbr::light_probe::LightProbe': '()',
'bevy_pbr::ssao::ScreenSpaceAmbientOcclusionSettings': '(quality_level: "")',
'bevy_pbr::wireframe::NoWireframe': '()',
'bevy_pbr::wireframe::Wireframe': '()',
'bevy_pbr::wireframe::WireframeColor': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, '
'blue:0.5780913233757019, alpha:0.20609822869300842))',
'bevy_rapier3d::dynamics::rigid_body::AdditionalMassProperties': 'Mass(0.42888906598091125)',
'bevy_rapier3d::dynamics::rigid_body::Ccd': '(enabled: true)',
'bevy_rapier3d::dynamics::rigid_body::Damping': '(angular_damping: 0.5714026093482971, linear_damping: '
'0.42888906598091125)',
'bevy_rapier3d::dynamics::rigid_body::Dominance': '(groups: 73)',
'bevy_rapier3d::dynamics::rigid_body::ExternalForce': '(force: Vec3(x:0.5714026093482971, y:0.42888906598091125, '
'z:0.5780913233757019), torque: Vec3(x:0.20609822869300842, '
'y:0.8133212327957153, z:0.8235888481140137))',
'bevy_rapier3d::dynamics::rigid_body::ExternalImpulse': '(impulse: Vec3(x:0.5714026093482971, y:0.42888906598091125, '
'z:0.5780913233757019), torque_impulse: '
'Vec3(x:0.20609822869300842, y:0.8133212327957153, '
'z:0.8235888481140137))',
'bevy_rapier3d::dynamics::rigid_body::GravityScale': '(0.5714026093482971)',
'bevy_rapier3d::dynamics::rigid_body::LockedAxes': '(73)',
'bevy_rapier3d::dynamics::rigid_body::RigidBody': 'Dynamic',
'bevy_rapier3d::dynamics::rigid_body::Sleeping': '(angular_threshold: 0.5714026093482971, linear_threshold: '
'0.42888906598091125, sleeping: true)',
'bevy_rapier3d::dynamics::rigid_body::Velocity': '(angvel: Vec3(x:0.5714026093482971, y:0.42888906598091125, '
'z:0.5780913233757019), linvel: Vec3(x:0.20609822869300842, '
'y:0.8133212327957153, z:0.8235888481140137))',
'bevy_rapier3d::geometry::collider::CollidingEntities': '("")',
'bevy_rapier3d::geometry::collider::CollisionGroups': '(filters: (73), memberships: (4))',
'bevy_rapier3d::geometry::collider::ContactForceEventThreshold': '(0.5714026093482971)',
'bevy_rapier3d::geometry::collider::Friction': '(coefficient: 0.5714026093482971, combine_rule: "")',
'bevy_rapier3d::geometry::collider::Group': '(73)',
'bevy_rapier3d::geometry::collider::Restitution': '(coefficient: 0.5714026093482971, combine_rule: "")',
'bevy_rapier3d::geometry::collider::Sensor': '()',
'bevy_rapier3d::geometry::collider::SolverGroups': '(filters: (73), memberships: (4))',
'bevy_render::camera::camera::Camera': '(clear_color: None, hdr: false, is_active: false, msaa_writeback: false, '
'order: 73, viewport: None)',
'bevy_render::camera::camera::CameraMainTextureUsages': 'None',
'bevy_render::camera::camera::CameraRenderGraph': 'None',
'bevy_render::camera::camera::Exposure': 'None',
'bevy_render::camera::projection::OrthographicProjection': '(area: (max: Vec2(x:0.5714026093482971, '
'y:0.42888906598091125), min: Vec2(x:0.5780913233757019, '
'y:0.20609822869300842)), far: 0.8133212327957153, near: '
'0.8235888481140137, scale: 0.6534725427627563, '
'scaling_mode: WindowSize(0.03440357372164726), '
'viewport_origin: Vec2(x:0.49008557200431824, '
'y:0.07608934491872787))', 'y:0.07608934491872787))',
'Outline': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_render::camera::projection::PerspectiveProjection': '(aspect_ratio: 0.5714026093482971, far: '
'alpha:0.20609822869300842), offset: VMax(0.4912964105606079), width: Percent(0.6534725427627563))', '0.42888906598091125, fov: 0.5780913233757019, near: '
'Parent': '(0)',
'PerspectiveProjection': '(aspect_ratio: 0.5714026093482971, far: 0.42888906598091125, fov: 0.5780913233757019, near: '
'0.20609822869300842)', '0.20609822869300842)',
'Pickable': '()', 'bevy_render::camera::projection::Projection': 'Perspective((aspect_ratio: 0.42888906598091125, far: '
'PlaybackSettings': '(mode: Once, paused: false, spatial: false, spatial_scale: "", speed: 0.5780913233757019, ' '0.5780913233757019, fov: 0.20609822869300842, near: '
'volume: (0.20609822869300842))', '0.8133212327957153))',
'Player': '()', 'bevy_render::mesh::mesh::skinning::SkinnedMesh': '(inverse_bindposes: Strong(""), joints: [0, 0])',
'PointLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_render::mesh::morph::MeshMorphWeights': '(weights: [0.42888906598091125])',
'alpha:0.20609822869300842), intensity: 0.8133212327957153, radius: 0.8235888481140137, range: ' 'bevy_render::mesh::morph::MorphWeights': '(first_mesh: "", weights: [0.42888906598091125])',
'0.6534725427627563, shadow_depth_bias: 0.16022956371307373, shadow_normal_bias: 0.5206693410873413, ' 'bevy_render::primitives::Aabb': '(center: Vec3A(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), '
'shadows_enabled: false)', 'half_extents: Vec3A(x:0.20609822869300842, y:0.8133212327957153, '
'PrimaryWindow': '()', 'z:0.8235888481140137))',
'Projection': 'Perspective((aspect_ratio: 0.42888906598091125, far: 0.5780913233757019, fov: 0.20609822869300842, ' 'bevy_render::primitives::CascadesFrusta': '()',
'near: 0.8133212327957153))', 'bevy_render::primitives::CubemapFrusta': '()',
'RelativeCursorPosition': '(normalized: "", normalized_visible_node_rect: (max: Vec2(x:0.5714026093482971, ' 'bevy_render::primitives::Frustum': '()',
'y:0.42888906598091125), min: Vec2(x:0.5780913233757019, y:0.20609822869300842)))', 'bevy_render::view::ColorGrading': '(exposure: 0.5714026093482971, gamma: 0.42888906598091125, post_saturation: '
'RenderLayers': '(73)', '0.5780913233757019, pre_saturation: 0.20609822869300842)',
'Restitution': '(coefficient: 0.5714026093482971, combine_rule: "")', 'bevy_render::view::visibility::InheritedVisibility': '(true)',
'RigidBody': 'Dynamic', 'bevy_render::view::visibility::NoFrustumCulling': '()',
'SSAOSettings': '()', 'bevy_render::view::visibility::ViewVisibility': '(true)',
'ScreenSpaceAmbientOcclusionSettings': '(quality_level: "")', 'bevy_render::view::visibility::Visibility': 'Visible',
'Sensor': '()', 'bevy_render::view::visibility::VisibleEntities': '()',
'ShadowFilteringMethod': 'Jimenez14', 'bevy_render::view::visibility::render_layers::RenderLayers': '(73)',
'SkinnedMesh': '(inverse_bindposes: Strong(""), joints: [0, 0])', 'bevy_sprite::mesh2d::mesh::Mesh2dHandle': '(Strong(""))',
'Sleeping': '(angular_threshold: 0.5714026093482971, linear_threshold: 0.42888906598091125, sleeping: true)', 'bevy_sprite::sprite::ImageScaleMode': 'Sliced((border: "", center_scale_mode: "", max_corner_scale: '
'SolverGroups': '(filters: (73), memberships: (4))', '0.42888906598091125, sides_scale_mode: ""))',
'SpatialListener': '(left_ear_offset: Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), ' 'bevy_sprite::sprite::Sprite': '(anchor: Custom(Vec2(x:0.03258506581187248, y:0.4825616776943207)), color: '
'right_ear_offset: Vec3(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))', 'Rgba(red:0.014832446351647377, green:0.46258050203323364, blue:0.4912964105606079, '
'SpawnHere': '()', 'alpha:0.27752065658569336), custom_size: "", flip_x: true, flip_y: false, rect: "")',
'SpotLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_text::pipeline::TextLayoutInfo': '(glyphs: "", logical_size: Vec2(x:0.5714026093482971, y:0.42888906598091125))',
'alpha:0.20609822869300842), inner_angle: 0.8133212327957153, intensity: 0.8235888481140137, ' 'bevy_text::text2d::Text2dBounds': '(size: Vec2(x:0.5714026093482971, y:0.42888906598091125))',
'outer_angle: 0.6534725427627563, radius: 0.16022956371307373, range: 0.5206693410873413, ' 'bevy_text::text::Text': '(justify: Right, linebreak_behavior: WordBoundary, sections: [(style: (color: '
'shadow_depth_bias: 0.3277728259563446, shadow_normal_bias: 0.24999667704105377, shadows_enabled: true)', 'Rgba(red:0.4825616776943207, green:0.014832446351647377, blue:0.46258050203323364, '
'Sprite': '(anchor: Custom(Vec2(x:0.03258506581187248, y:0.4825616776943207)), color: Rgba(red:0.014832446351647377, ' 'alpha:0.4912964105606079), font: Weak(Index(index: "")), font_size: 0.03440357372164726), '
'green:0.46258050203323364, blue:0.4912964105606079, alpha:0.27752065658569336), custom_size: "", flip_x: ' 'value: "pkchxlbn"), (style: (color: Rgba(red:0.8601610660552979, green:0.6031906008720398, '
'true, flip_y: false, rect: "")', 'blue:0.38160598278045654, alpha:0.2836182117462158), font: Weak(Uuid(uuid: '
'Style': '(align_content: SpaceAround, align_items: Default, align_self: Baseline, aspect_ratio: ' '"73b3b118-7d01-4778-8bcc-4e79055f5d22")), font_size: 0.17467059195041656), value: '
'Some(0.5780913233757019), border: (bottom: Px(0.46258050203323364), left: Vw(0.8235888481140137), right: ' '"jvleoyho")])',
'VMin(0.8106188178062439), top: Auto), bottom: Vh(0.49008557200431824), column_gap: Auto, direction: ' 'bevy_transform::components::global_transform::GlobalTransform': '((matrix3: (x_axis: Vec3A(x:0.5714026093482971, '
'Inherit, display: None, flex_basis: Percent(0.0445563830435276), flex_direction: Column, flex_grow: ' 'y:0.42888906598091125, z:0.5780913233757019), '
'0.6031906008720398, flex_shrink: 0.38160598278045654, flex_wrap: Wrap, grid_auto_columns: "", ' 'y_axis: Vec3A(x:0.20609822869300842, '
'grid_auto_flow: RowDense, grid_auto_rows: "", grid_column: (end: "", span: "", start: ""), grid_row: (end: ' 'y:0.8133212327957153, z:0.8235888481140137), '
'"", span: "", start: ""), grid_template_columns: "", grid_template_rows: "", height: ' 'z_axis: Vec3A(x:0.6534725427627563, '
'Vw(0.17467059195041656), justify_content: FlexEnd, justify_items: Stretch, justify_self: End, left: ' 'y:0.16022956371307373, z:0.5206693410873413)), '
'Px(0.45692843198776245), margin: (bottom: VMax(0.9824132323265076), left: Vw(0.6133268475532532), right: ' 'translation: Vec3A(x:0.3277728259563446, '
'Auto, top: Vh(0.004055144265294075)), max_height: Px(0.1949533075094223), max_width: ' 'y:0.24999667704105377, z:0.952816903591156)))',
'Percent(0.5363451838493347), min_height: VMax(0.8981962203979492), min_width: Percent(0.666689932346344), ' 'bevy_transform::components::transform::Transform': '(rotation: Quat(x:0.5714026093482971, y:0.42888906598091125, '
'overflow: (x: Clip, y: Clip), padding: (bottom: Vw(0.06499417871236801), left: Vh(0.32468828558921814), ' 'z:0.5780913233757019, w:0.20609822869300842), scale: '
'right: Vh(0.15641891956329346), top: Px(0.9697836637496948)), position_type: Relative, right: Auto, ' 'Vec3(x:0.8133212327957153, y:0.8235888481140137, '
'row_gap: Auto, top: Vw(0.3011642396450043), width: Vh(0.6578909158706665))', 'z:0.6534725427627563), translation: Vec3(x:0.16022956371307373, '
'Text': '(justify: Right, linebreak_behavior: WordBoundary, sections: [(style: (color: Rgba(red:0.4825616776943207, ' 'y:0.5206693410873413, z:0.3277728259563446))',
'green:0.014832446351647377, blue:0.46258050203323364, alpha:0.4912964105606079), font: Weak(Index(index: ' 'bevy_ui::focus::FocusPolicy': 'Block',
'"")), font_size: 0.03440357372164726), value: "pkchxlbn"), (style: (color: Rgba(red:0.8601610660552979, ' 'bevy_ui::focus::Interaction': 'None',
'green:0.6031906008720398, blue:0.38160598278045654, alpha:0.2836182117462158), font: Weak(Uuid(uuid: ' 'bevy_ui::focus::RelativeCursorPosition': '(normalized: "", normalized_visible_node_rect: (max: '
'"73b3b118-7d01-4778-8bcc-4e79055f5d22")), font_size: 0.17467059195041656), value: "jvleoyho")])', 'Vec2(x:0.5714026093482971, y:0.42888906598091125), min: '
'Text2dBounds': '(size: Vec2(x:0.5714026093482971, y:0.42888906598091125))', 'Vec2(x:0.5780913233757019, y:0.20609822869300842)))',
'TextFlags': '(needs_new_measure_func: true, needs_recompute: false)', 'bevy_ui::measurement::ContentSize': '()',
'TextLayoutInfo': '(glyphs: "", logical_size: Vec2(x:0.5714026093482971, y:0.42888906598091125))', 'bevy_ui::ui_node::BackgroundColor': '(Rgba(red:0.5714026093482971, green:0.42888906598091125, '
'Tonemapping': 'None', 'blue:0.5780913233757019, alpha:0.20609822869300842))',
'Transform': '(rotation: Quat(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019, ' 'bevy_ui::ui_node::BorderColor': '(Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
'w:0.20609822869300842), scale: Vec3(x:0.8133212327957153, y:0.8235888481140137, z:0.6534725427627563), '
'translation: Vec3(x:0.16022956371307373, y:0.5206693410873413, z:0.3277728259563446))',
'TupleTest2': '(0.5714026093482971, 54, "psagopiu")',
'TupleTestBool': '(true)',
'TupleTestColor': '(Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
'alpha:0.20609822869300842))', 'alpha:0.20609822869300842))',
'TupleTestF32': '(0.5714026093482971)', 'bevy_ui::ui_node::CalculatedClip': '(clip: (max: Vec2(x:0.5714026093482971, y:0.42888906598091125), min: '
'TupleTestStr': '("sbnpsago")', 'Vec2(x:0.5780913233757019, y:0.20609822869300842)))',
'TupleTestU64': '(73)', 'bevy_ui::ui_node::Node': '(calculated_size: Vec2(x:0.5714026093482971, y:0.42888906598091125), outline_offset: '
'TupleVec': '(["npsagopi"])', '0.5780913233757019, outline_width: 0.20609822869300842, stack_index: 62, unrounded_size: '
'TupleVec2': '(Vec2(x:0.5714026093482971, y:0.42888906598091125))', 'Vec2(x:0.8235888481140137, y:0.6534725427627563))',
'TupleVec3': '(Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019))', 'bevy_ui::ui_node::Outline': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, '
'TupleVecF32F32': '([(0.42888906598091125, 0.5780913233757019)])', 'blue:0.5780913233757019, alpha:0.20609822869300842), offset: VMax(0.4912964105606079), '
'UiImage': '(flip_x: true, flip_y: false, texture: Weak(Uuid(uuid: "73b3b118-7d01-4778-8bcc-4e79055f5d22")))', 'width: Percent(0.6534725427627563))',
'UiImageSize': '(size: Vec2(x:0.5714026093482971, y:0.42888906598091125))', 'bevy_ui::ui_node::Style': '(align_content: SpaceAround, align_items: Default, align_self: Baseline, aspect_ratio: '
'UnitTest': '()', 'Some(0.5780913233757019), border: (bottom: Px(0.46258050203323364), left: '
'VecOfColors': '([Rgba(red:0.42888906598091125, green:0.5780913233757019, blue:0.20609822869300842, ' 'Vw(0.8235888481140137), right: VMin(0.8106188178062439), top: Auto), bottom: '
'alpha:0.8133212327957153)])', 'Vh(0.49008557200431824), column_gap: Auto, direction: Inherit, display: None, flex_basis: '
'VecOfF32s': '([0.42888906598091125])', 'Percent(0.0445563830435276), flex_direction: Column, flex_grow: 0.6031906008720398, '
'VecOfVec3s2': '([(Vec3(x:0.42888906598091125, y:0.5780913233757019, z:0.20609822869300842))])', 'flex_shrink: 0.38160598278045654, flex_wrap: Wrap, grid_auto_columns: "", grid_auto_flow: '
'Velocity': '(angvel: Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), linvel: ' 'RowDense, grid_auto_rows: "", grid_column: (end: "", span: "", start: ""), grid_row: '
'Vec3(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))', '(end: "", span: "", start: ""), grid_template_columns: "", grid_template_rows: "", '
'ViewVisibility': '(true)', 'height: Vw(0.17467059195041656), justify_content: FlexEnd, justify_items: Stretch, '
'Visibility': 'Visible', 'justify_self: End, left: Px(0.45692843198776245), margin: (bottom: '
'VisibleEntities': '()', 'VMax(0.9824132323265076), left: Vw(0.6133268475532532), right: Auto, top: '
'Window': '(canvas: None, composite_alpha_mode: PostMultiplied, cursor: (grab_mode: Confined, hit_test: true, icon: ' 'Vh(0.004055144265294075)), max_height: Px(0.1949533075094223), max_width: '
'Default, visible: false), decorations: false, enabled_buttons: (close: true, maximize: false, minimize: ' 'Percent(0.5363451838493347), min_height: VMax(0.8981962203979492), min_width: '
'true), focused: false, ime_enabled: true, ime_position: Vec2(x:0.8106188178062439, y:0.03440357372164726), ' 'Percent(0.666689932346344), overflow: (x: Clip, y: Clip), padding: (bottom: '
'internal: (maximize_request: Some(false), minimize_request: None, physical_cursor_position: None), mode: ' 'Vw(0.06499417871236801), left: Vh(0.32468828558921814), right: Vh(0.15641891956329346), '
'SizedFullscreen, name: None, position: Centered(Current), present_mode: Immediate, ' 'top: Px(0.9697836637496948)), position_type: Relative, right: Auto, row_gap: Auto, top: '
'prevent_default_event_handling: false, resizable: false, resize_constraints: (max_height: ' 'Vw(0.3011642396450043), width: Vh(0.6578909158706665))',
'0.42126399278640747, max_width: 0.8268482089042664, min_height: 0.2623211145401001, min_width: ' 'bevy_ui::ui_node::UiImage': '(flip_x: true, flip_y: false, texture: Weak(Uuid(uuid: '
'0.17467059195041656), resolution: (physical_height: 38, physical_width: 84, scale_factor: ' '"73b3b118-7d01-4778-8bcc-4e79055f5d22")))',
'0.36258742213249207, scale_factor_override: Some(0.7678378224372864)), title: "hotmbsah", transparent: ' 'bevy_ui::ui_node::ZIndex': 'Local(54)',
'false, visible: false, window_level: Normal, window_theme: "")', 'bevy_ui::widget::button::Button': '()',
'Wireframe': '()', 'bevy_ui::widget::image::UiImageSize': '(size: Vec2(x:0.5714026093482971, y:0.42888906598091125))',
'WireframeColor': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, ' 'bevy_ui::widget::label::Label': '()',
'alpha:0.20609822869300842))', 'bevy_ui::widget::text::TextFlags': '(needs_new_measure_func: true, needs_recompute: false)',
'ZIndex': 'Local(54)'} 'bevy_window::window::PrimaryWindow': '()',
'bevy_window::window::Window': '(canvas: None, composite_alpha_mode: PostMultiplied, cursor: (grab_mode: Confined, '
'hit_test: true, icon: Default, visible: false), decorations: false, enabled_buttons: '
'(close: true, maximize: false, minimize: true), focused: false, ime_enabled: true, '
'ime_position: Vec2(x:0.8106188178062439, y:0.03440357372164726), internal: '
'(maximize_request: Some(false), minimize_request: None, physical_cursor_position: '
'None), mode: SizedFullscreen, name: None, position: Centered(Current), present_mode: '
'Immediate, prevent_default_event_handling: false, resizable: false, '
'resize_constraints: (max_height: 0.42126399278640747, max_width: 0.8268482089042664, '
'min_height: 0.2623211145401001, min_width: 0.17467059195041656), resolution: '
'(physical_height: 38, physical_width: 84, scale_factor: 0.36258742213249207, '
'scale_factor_override: Some(0.7678378224372864)), title: "hotmbsah", transparent: '
'false, visible: false, window_level: Normal, window_theme: "")'}

View File

@ -5,6 +5,7 @@ from ..propGroups.conversions_to_prop_group import property_group_value_from_cus
from ..propGroups.conversions_from_prop_group import property_group_value_to_custom_property_value from ..propGroups.conversions_from_prop_group import property_group_value_to_custom_property_value
from .component_values_shuffler import component_values_shuffler from .component_values_shuffler import component_values_shuffler
from .expected_component_values import (expected_custom_property_values, expected_custom_property_values_randomized) from .expected_component_values import (expected_custom_property_values, expected_custom_property_values_randomized)
from ..components.metadata import get_bevy_component_value_by_long_name, get_bevy_components, upsert_bevy_component
from .setup_data import setup_data from .setup_data import setup_data
@ -25,25 +26,24 @@ def test_components_should_generate_correct_custom_properties(setup_data):
for long_name in type_infos: for long_name in type_infos:
definition = type_infos[long_name] definition = type_infos[long_name]
component_type = definition["long_name"] long_name = definition["long_name"]
short_name = definition["short_name"]
is_component = definition['isComponent'] if "isComponent" in definition else False is_component = definition['isComponent'] if "isComponent" in definition else False
if not is_component: if not is_component:
continue continue
addable_components.append(component_type) addable_components.append(long_name)
try: try:
add_component_operator(component_type=component_type) add_component_operator(component_type=long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
added_components.append(component_type) added_components.append(long_name)
custom_property_values[short_name] = object[short_name] custom_property_values[long_name] = get_bevy_component_value_by_long_name(object, long_name)
assert object[short_name] == expected_custom_property_values[short_name] assert get_bevy_component_value_by_long_name(object, long_name) == expected_custom_property_values[long_name]
except Exception as error: except Exception as error:
errors.append(error) errors.append(error)
@ -53,7 +53,7 @@ def test_components_should_generate_correct_custom_properties(setup_data):
pp.pprint(custom_property_values) pp.pprint(custom_property_values)
assert len(errors) == 0 assert len(errors) == 0
assert len(added_components) == 159 assert len(added_components) == 173
def test_components_should_generate_correct_custom_properties_with_randomized_values(setup_data): def test_components_should_generate_correct_custom_properties_with_randomized_values(setup_data):
@ -74,30 +74,29 @@ def test_components_should_generate_correct_custom_properties_with_randomized_va
for long_name in type_infos: for long_name in type_infos:
definition = type_infos[long_name] definition = type_infos[long_name]
component_type = definition["long_name"] long_name = definition["long_name"]
short_name = definition["short_name"]
is_component = definition['isComponent'] if "isComponent" in definition else False is_component = definition['isComponent'] if "isComponent" in definition else False
if not is_component: if not is_component:
continue continue
addable_components.append(component_type) addable_components.append(long_name)
try: try:
add_component_operator(component_type=component_type) add_component_operator(component_type=long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
component_values_shuffler(seed= 10, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 10, property_group=propertyGroup, definition=definition, registry=registry)
added_components.append(component_type) added_components.append(long_name)
custom_property_values[short_name] = object[short_name] custom_property_values[long_name] = get_bevy_component_value_by_long_name(object, long_name)
assert object[short_name] == expected_custom_property_values_randomized[short_name] assert get_bevy_component_value_by_long_name(object, long_name) == expected_custom_property_values_randomized[long_name]
except Exception as error: except Exception as error:
errors.append(error) errors.append(error)
error_components.append(short_name) error_components.append(long_name)
pp = pprint.PrettyPrinter(depth=14, width=120) pp = pprint.PrettyPrinter(depth=14, width=120)
print("CUSTOM PROPERTY VALUES") print("CUSTOM PROPERTY VALUES")
@ -105,7 +104,7 @@ def test_components_should_generate_correct_custom_properties_with_randomized_va
print("error_components", error_components) print("error_components", error_components)
assert len(errors) == 0 assert len(errors) == 0
assert len(added_components) == 159 assert len(added_components) == 173
def test_components_should_generate_correct_propertyGroup_values_from_custom_properties(setup_data): def test_components_should_generate_correct_propertyGroup_values_from_custom_properties(setup_data):
registry = bpy.context.window_manager.components_registry registry = bpy.context.window_manager.components_registry
@ -123,47 +122,46 @@ def test_components_should_generate_correct_propertyGroup_values_from_custom_pro
for long_name in type_infos: for long_name in type_infos:
definition = type_infos[long_name] definition = type_infos[long_name]
component_type = definition["long_name"] long_name = definition["long_name"]
short_name = definition["short_name"]
is_component = definition['isComponent'] if "isComponent" in definition else False is_component = definition['isComponent'] if "isComponent" in definition else False
if not is_component: if not is_component:
continue continue
addable_components.append(component_type) addable_components.append(long_name)
try: try:
add_component_operator(component_type=component_type) add_component_operator(component_type=long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
added_components.append(component_type) added_components.append(long_name)
# randomise values # randomise values
component_values_shuffler(seed= 10, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 10, property_group=propertyGroup, definition=definition, registry=registry)
custom_property_value = object[short_name] custom_property_value = get_bevy_component_value_by_long_name(object, long_name)
# first check if custom property value matches what we expect # first check if custom property value matches what we expect
assert custom_property_value == expected_custom_property_values_randomized[short_name] assert custom_property_value == expected_custom_property_values_randomized[long_name]
# we update propgroup values from custom property values # we update propgroup values from custom property values
property_group_value_from_custom_property_value(propertyGroup, definition, registry, custom_property_value, nesting = []) property_group_value_from_custom_property_value(propertyGroup, definition, registry, custom_property_value, nesting = [])
# and then generate it back # and then generate it back
custom_property_value_regen = property_group_value_to_custom_property_value(propertyGroup, definition, registry, None) custom_property_value_regen = property_group_value_to_custom_property_value(propertyGroup, definition, registry, None)
assert custom_property_value_regen == expected_custom_property_values_randomized[short_name] assert custom_property_value_regen == expected_custom_property_values_randomized[long_name]
# custom_property_values[short_name] = object[short_name] # custom_property_values[long_name] = object[long_name]
#assert object[short_name] == expected_custom_property_values[short_name] #assert object[long_name] == expected_custom_property_values[long_name]
#print("CUSTOM PROPERTY ", object[short_name]) #print("CUSTOM PROPERTY ", object[long_name])
except Exception as error: except Exception as error:
errors.append(error) errors.append(error)
failing_components.append(short_name) failing_components.append(long_name)
for index, error in enumerate(errors): for index, error in enumerate(errors):
print("ERROR", error, failing_components[index]) print("ERROR", error, failing_components[index])
assert len(errors) == 0 assert len(errors) == 0
assert len(added_components) == 159 assert len(added_components) == 173
def test_remove_components(setup_data): def test_remove_components(setup_data):
@ -180,25 +178,18 @@ def test_remove_components(setup_data):
for long_name in type_infos: for long_name in type_infos:
definition = type_infos[long_name] definition = type_infos[long_name]
component_type = definition["long_name"] long_name = definition["long_name"]
short_name = definition["short_name"]
is_component = definition['isComponent'] if "isComponent" in definition else False is_component = definition['isComponent'] if "isComponent" in definition else False
if not is_component: if not is_component:
continue continue
addable_components.append(component_type) addable_components.append(long_name)
try: try:
add_component_operator(component_type=component_type) add_component_operator(component_type=long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
object = bpy.context.object object = bpy.context.object
target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None)
# print("propertyGroup", propertyGroup, propertyGroup.field_names) # print("propertyGroup", propertyGroup, propertyGroup.field_names)
added_components.append(component_type) added_components.append(long_name)
except Exception as error: except Exception as error:
errors.append(error) errors.append(error)
assert len(errors) == 0 assert len(errors) == 0
@ -206,10 +197,9 @@ def test_remove_components(setup_data):
# now test component removal # now test component removal
errors.clear() errors.clear()
remove_component_operator = bpy.ops.object.remove_bevy_component remove_component_operator = bpy.ops.object.remove_bevy_component
for component_type in added_components: for long_name in added_components:
component_name = type_infos[component_type]["short_name"]
try: try:
remove_component_operator(component_name=component_name) remove_component_operator(component_name=long_name)
except Exception as error: except Exception as error:
errors.append(error) errors.append(error)
assert len(errors) == 0 assert len(errors) == 0
@ -220,24 +210,23 @@ def test_copy_paste_components(setup_data):
registry.schemaPath = setup_data["schema_path"] registry.schemaPath = setup_data["schema_path"]
bpy.ops.object.reload_registry() bpy.ops.object.reload_registry()
short_name = "BasicTest" long_name = "bevy_example::test_components::BasicTest"
component_type = registry.short_names_to_long_names[short_name]
# SOURCE object setup # SOURCE object setup
add_component_operator = bpy.ops.object.add_bevy_component add_component_operator = bpy.ops.object.add_bevy_component
add_component_operator(component_type=component_type) add_component_operator(component_type=long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
object = context.object object = context.object
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
setattr(propertyGroup, propertyGroup.field_names[0], 25.0) setattr(propertyGroup, propertyGroup.field_names[0], 25.0)
copy_component_operator = bpy.ops.object.copy_bevy_component copy_component_operator = bpy.ops.object.copy_bevy_component
copy_component_operator(source_component_name=short_name, source_object_name=object.name) copy_component_operator(source_component_name=long_name, source_object_name=object.name)
# --------------------------------------- # ---------------------------------------
# TARGET object # TARGET object
@ -246,7 +235,7 @@ def test_copy_paste_components(setup_data):
# change name # change name
new_cube.name = "TargetCube" new_cube.name = "TargetCube"
target_components_metadata = new_cube.components_meta.components target_components_metadata = new_cube.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
# first check that there is no component currently # first check that there is no component currently
assert component_meta == None assert component_meta == None
@ -255,7 +244,7 @@ def test_copy_paste_components(setup_data):
paste_component_operator() paste_component_operator()
target_components_metadata = new_cube.components_meta.components target_components_metadata = new_cube.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
# now after pasting to the new object, it should have component meta # now after pasting to the new object, it should have component meta
assert component_meta != None assert component_meta != None

View File

@ -6,17 +6,16 @@ def test_blend(setup_data):
registry.schemaPath = setup_data["schema_path"] registry.schemaPath = setup_data["schema_path"]
bpy.ops.object.reload_registry() bpy.ops.object.reload_registry()
short_name = "BasicTest" long_name = "bevy_example::test_components::BasicTest"
component_type = registry.short_names_to_long_names[short_name]
add_component_operator = bpy.ops.object.add_bevy_component add_component_operator = bpy.ops.object.add_bevy_component
add_component_operator(component_type=component_type) add_component_operator(component_type=long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
object = bpy.context.object object = bpy.context.object
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)

View File

@ -4,6 +4,8 @@ import bpy
import pprint import pprint
import pytest import pytest
from ..components.metadata import get_bevy_component_value_by_long_name, get_bevy_components, is_bevy_component_in_object, upsert_bevy_component
from .setup_data import setup_data from .setup_data import setup_data
# small helpers # small helpers
@ -15,7 +17,7 @@ def get_component_metadata(object, component_name):
def get_component_propGroup(registry, component_name, component_meta): def get_component_propGroup(registry, component_name, component_meta):
# component_type = registry.short_names_to_long_names[component_name] # component_type = registry.short_names_to_long_names[component_name]
# add_component_operator = bpy.ops.object.add_bevy_component # add_component_operator = bpy.ops.object.add_bevy_component
property_group_name = registry.get_propertyGroupName_from_shortName(component_name) property_group_name = registry.get_propertyGroupName_from_longName(component_name)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
return propertyGroup return propertyGroup
@ -29,17 +31,17 @@ def test_rename_component_single_unit_struct(setup_data):
object = bpy.context.object object = bpy.context.object
source_component_name = "SomeOldUnitStruct" source_component_name = "bevy_example::test_components::SomeOldUnitStruct"
target_component_name = "UnitTest" target_component_name = "bevy_example::test_components::UnitTest"
object[source_component_name] = '()' upsert_bevy_component(object, source_component_name, '()')
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps([object.name])) rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps([object.name]))
is_old_component_in_object = source_component_name in object is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
is_new_component_in_object = target_component_name in object is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
assert is_old_component_in_object == False assert is_old_component_in_object == False
assert is_new_component_in_object == True assert is_new_component_in_object == True
assert object[target_component_name] == '()' assert get_bevy_component_value_by_long_name(object, target_component_name) == '()'
assert get_component_propGroup(registry, target_component_name, get_component_metadata(object, target_component_name)) != None assert get_component_propGroup(registry, target_component_name, get_component_metadata(object, target_component_name)) != None
@ -52,17 +54,17 @@ def test_rename_component_single_complex_struct(setup_data):
object = bpy.context.object object = bpy.context.object
source_component_name = "ProxyCollider" source_component_name = "bevy_example::test_components::ProxyCollider"
target_component_name = "Collider" target_component_name = "bevy_gltf_worlflow_examples_common_rapier::physics::physics_replace_proxies::Collider"
object[source_component_name] = 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)' upsert_bevy_component(object, source_component_name, 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)')
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps([object.name])) rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps([object.name]))
is_old_component_in_object = source_component_name in object is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
is_new_component_in_object = target_component_name in object is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
assert is_old_component_in_object == False assert is_old_component_in_object == False
assert is_new_component_in_object == True assert is_new_component_in_object == True
assert object[target_component_name] == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)' assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
assert get_component_propGroup(registry, target_component_name, get_component_metadata(object, target_component_name)) != None assert get_component_propGroup(registry, target_component_name, get_component_metadata(object, target_component_name)) != None
@ -73,22 +75,22 @@ def test_rename_component_bulk(setup_data):
rename_component_operator = bpy.ops.object.rename_bevy_component rename_component_operator = bpy.ops.object.rename_bevy_component
source_component_name = "SomeOldUnitStruct" source_component_name = "bevy_example::test_components::SomeOldUnitStruct"
target_component_name = "UnitTest" target_component_name = "bevy_example::test_components::UnitTest"
objects_names = [] objects_names = []
for object in bpy.data.objects: for object in bpy.data.objects:
object[source_component_name] = '()' upsert_bevy_component(object, source_component_name, '()')
objects_names.append(object.name) objects_names.append(object.name)
# bulk rename # bulk rename
rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps(objects_names)) rename_component_operator(original_name=source_component_name, new_name=target_component_name, target_objects=json.dumps(objects_names))
for object in bpy.data.objects: for object in bpy.data.objects:
is_old_component_in_object = source_component_name in object is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
is_new_component_in_object = target_component_name in object is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
assert is_old_component_in_object == False assert is_old_component_in_object == False
assert is_new_component_in_object == True assert is_new_component_in_object == True
assert object[target_component_name] == '()' assert get_bevy_component_value_by_long_name(object, target_component_name) == '()'
assert get_component_propGroup(registry, target_component_name, get_component_metadata(object, target_component_name)) != None assert get_component_propGroup(registry, target_component_name, get_component_metadata(object, target_component_name)) != None
def test_rename_component_single_error_handling(setup_data): def test_rename_component_single_error_handling(setup_data):
@ -100,9 +102,9 @@ def test_rename_component_single_error_handling(setup_data):
object = bpy.context.object object = bpy.context.object
source_component_name = "SomeOldUnitStruct" source_component_name = "bevy_example::test_components::SomeOldUnitStruct"
target_component_name = "UnitTest" target_component_name = "bevy_example::test_components::UnitTest"
object[source_component_name] = 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)' upsert_bevy_component(object, source_component_name, 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)')
expected_error = f'Error: Failed to rename component: Errors:["wrong custom property values to generate target component: object: \'{object.name}\', error: input string too big for a unit struct"]\n' expected_error = f'Error: Failed to rename component: Errors:["wrong custom property values to generate target component: object: \'{object.name}\', error: input string too big for a unit struct"]\n'
expected_error = re.escape(expected_error) expected_error = re.escape(expected_error)
@ -111,11 +113,11 @@ def test_rename_component_single_error_handling(setup_data):
target_component_metadata = get_component_metadata(object, target_component_name) target_component_metadata = get_component_metadata(object, target_component_name)
is_old_component_in_object = source_component_name in object is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
is_new_component_in_object = target_component_name in object is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
assert is_old_component_in_object == False assert is_old_component_in_object == False
assert is_new_component_in_object == True assert is_new_component_in_object == True
assert object[target_component_name] == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)' assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
assert get_component_propGroup(registry, target_component_name, target_component_metadata) != None assert get_component_propGroup(registry, target_component_name, target_component_metadata) != None
assert target_component_metadata.invalid == True assert target_component_metadata.invalid == True
@ -130,9 +132,9 @@ def test_rename_component_single_error_handling_clean_errors(setup_data):
object = bpy.context.object object = bpy.context.object
source_component_name = "SomeOldUnitStruct" source_component_name = "bevy_example::test_components::SomeOldUnitStruct"
target_component_name = "UnitTest" target_component_name = "bevy_example::test_components::UnitTest"
object[source_component_name] = 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)' upsert_bevy_component(object, source_component_name, 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)')
expected_error = f'Error: Failed to rename component: Errors:["wrong custom property values to generate target component: object: \'{object.name}\', error: input string too big for a unit struct"]\n' expected_error = f'Error: Failed to rename component: Errors:["wrong custom property values to generate target component: object: \'{object.name}\', error: input string too big for a unit struct"]\n'
expected_error = re.escape(expected_error) expected_error = re.escape(expected_error)
@ -141,11 +143,11 @@ def test_rename_component_single_error_handling_clean_errors(setup_data):
target_component_metadata = get_component_metadata(object, target_component_name) target_component_metadata = get_component_metadata(object, target_component_name)
is_old_component_in_object = source_component_name in object is_old_component_in_object = is_bevy_component_in_object(object, source_component_name)
is_new_component_in_object = target_component_name in object is_new_component_in_object = is_bevy_component_in_object(object, target_component_name)
assert is_old_component_in_object == False assert is_old_component_in_object == False
assert is_new_component_in_object == True assert is_new_component_in_object == True
assert object[target_component_name] == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)' assert get_bevy_component_value_by_long_name(object, target_component_name) == 'Capsule(Vec3(x:1.0, y:2.0, z:0.0), Vec3(x:0.0, y:0.0, z:0.0), 3.0)'
assert get_component_propGroup(registry, target_component_name, target_component_metadata) != None assert get_component_propGroup(registry, target_component_name, target_component_metadata) != None
assert target_component_metadata.invalid == True assert target_component_metadata.invalid == True

View File

@ -1,5 +1,6 @@
import bpy import bpy
from .component_values_shuffler import component_values_shuffler from .component_values_shuffler import component_values_shuffler
from ..components.metadata import get_bevy_component_value_by_long_name, get_bevy_components, upsert_bevy_component
from .setup_data import setup_data from .setup_data import setup_data
def test_shuffler(setup_data): def test_shuffler(setup_data):
@ -12,17 +13,15 @@ def test_shuffler(setup_data):
add_component_operator = bpy.ops.object.add_bevy_component add_component_operator = bpy.ops.object.add_bevy_component
short_name = "BasicTest" long_name = "bevy_example::test_components::BasicTest"
component_type = registry.short_names_to_long_names[short_name] add_component_operator(component_type=long_name)
add_component_operator(component_type=component_type) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type] definition = type_infos[long_name]
component_values_shuffler(seed= 10, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 10, property_group=propertyGroup, definition=definition, registry=registry)
assert getattr(propertyGroup, 'a') == 0.5714026093482971 assert getattr(propertyGroup, 'a') == 0.5714026093482971
@ -31,130 +30,121 @@ def test_shuffler(setup_data):
# Testing a more complex component # Testing a more complex component
short_name = "NestingTestLevel2" long_name = "bevy_example::test_components::NestingTestLevel2"
component_type = registry.short_names_to_long_names[short_name] add_component_operator(component_type=long_name)
add_component_operator(component_type=component_type)
property_group_name = registry.get_propertyGroupName_from_longName(long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type] definition = type_infos[long_name]
component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry)
print("propertyGroup", object[short_name]) #print("propertyGroup", object[long_name])
# cheating / making things easier for us for complex types: we use the custom property value # cheating / making things easier for us for complex types: we use the custom property value
assert object[short_name] == '(basic: (a: 0.5219839215278625, b: 38, c: "ljfywwrv"), color: (Rgba(red:0.2782765030860901, green:0.9174930453300476, blue:0.24890311062335968, alpha:0.815186083316803)), colors_list: ([Rgba(red:0.2523837685585022, green:0.5016026496887207, blue:0.317435085773468, alpha:0.8463277816772461), Rgba(red:0.945193886756897, green:0.4015909433364868, blue:0.9984470009803772, alpha:0.06219279021024704)]), enable: true, enum_inner: Wood, nested: (vec: (Vec3(x:0.1509154736995697, y:0.7055686116218567, z:0.5588918924331665))), text: "vgkrdwuc", toggle: (false))' assert get_bevy_component_value_by_long_name(object, long_name) == '(basic: (a: 0.5219839215278625, b: 38, c: "ljfywwrv"), color: (Rgba(red:0.2782765030860901, green:0.9174930453300476, blue:0.24890311062335968, alpha:0.815186083316803)), colors_list: ([Rgba(red:0.2523837685585022, green:0.5016026496887207, blue:0.317435085773468, alpha:0.8463277816772461), Rgba(red:0.945193886756897, green:0.4015909433364868, blue:0.9984470009803772, alpha:0.06219279021024704)]), enable: true, enum_inner: Wood, nested: (vec: (Vec3(x:0.1509154736995697, y:0.7055686116218567, z:0.5588918924331665))), text: "vgkrdwuc", toggle: (false))'
# And another complex component # And another complex component
short_name = "EnumComplex" long_name = "bevy_example::test_components::EnumComplex"
component_type = registry.short_names_to_long_names[short_name] add_component_operator(component_type=long_name)
add_component_operator(component_type=component_type)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type] definition = type_infos[long_name]
component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry)
print("propertyGroup", object[short_name]) print("propertyGroup", get_bevy_component_value_by_long_name(object, long_name))
# cheating / making things easier for us for complex types: we use the custom property value # cheating / making things easier for us for complex types: we use the custom property value
assert object[short_name] == 'StructLike(a: 0.41416797041893005, b: 38, c: "ljfywwrv")' assert get_bevy_component_value_by_long_name(object, long_name) == 'StructLike(a: 0.41416797041893005, b: 38, c: "ljfywwrv")'
# And another complex component # And another complex component
short_name = "AnimationPlayer" long_name = "bevy_animation::AnimationPlayer"
component_type = registry.short_names_to_long_names[short_name] add_component_operator(component_type=long_name)
add_component_operator(component_type=component_type)
property_group_name = registry.get_propertyGroupName_from_longName(long_name)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type] definition = type_infos[long_name]
component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry)
print("propertyGroup", object[short_name]) print("propertyGroup", get_bevy_component_value_by_long_name(object, long_name))
# cheating / making things easier for us for complex types: we use the custom property value # cheating / making things easier for us for complex types: we use the custom property value
assert object[short_name] == '(animation: "", paused: true)' assert get_bevy_component_value_by_long_name(object, long_name) == '(animation: "", paused: true)'
# And another complex component # And another complex component
short_name = "VecOfColors" long_name = "bevy_example::test_components::VecOfColors"
component_type = registry.short_names_to_long_names[short_name] add_component_operator(component_type=long_name)
add_component_operator(component_type=component_type)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type] definition = type_infos[long_name]
component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry)
print("propertyGroup", object[short_name]) print("propertyGroup", get_bevy_component_value_by_long_name(object, long_name))
# cheating / making things easier for us for complex types: we use the custom property value # cheating / making things easier for us for complex types: we use the custom property value
assert object[short_name] == '([Rgba(red:0.8066907525062561, green:0.9604947566986084, blue:0.2896253764629364, alpha:0.766107439994812), Rgba(red:0.7042198777198792, green:0.6613830327987671, blue:0.11016204953193665, alpha:0.02693677879869938)])' assert get_bevy_component_value_by_long_name(object, long_name) == '([Rgba(red:0.8066907525062561, green:0.9604947566986084, blue:0.2896253764629364, alpha:0.766107439994812), Rgba(red:0.7042198777198792, green:0.6613830327987671, blue:0.11016204953193665, alpha:0.02693677879869938)])'
# And another complex component # And another complex component
short_name = "VecOfF32s" long_name = "bevy_example::test_components::VecOfF32s"
component_type = registry.short_names_to_long_names[short_name] add_component_operator(component_type=long_name)
add_component_operator(component_type=component_type)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type] definition = type_infos[long_name]
component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry)
print("propertyGroup", object[short_name]) print("propertyGroup", get_bevy_component_value_by_long_name(object, long_name))
# cheating / making things easier for us for complex types: we use the custom property value # cheating / making things easier for us for complex types: we use the custom property value
assert object[short_name] == '([0.8066907525062561, 0.9604947566986084])' assert get_bevy_component_value_by_long_name(object, long_name) == '([0.8066907525062561, 0.9604947566986084])'
# And another complex component # And another complex component
short_name = "SkinnedMesh" long_name = "bevy_render::mesh::mesh::skinning::SkinnedMesh"
component_type = registry.short_names_to_long_names[short_name] add_component_operator(component_type=long_name)
add_component_operator(component_type=component_type)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type] definition = type_infos[long_name]
component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry)
print("propertyGroup", object[short_name]) print("propertyGroup", get_bevy_component_value_by_long_name(object, long_name))
# cheating / making things easier for us for complex types: we use the custom property value # cheating / making things easier for us for complex types: we use the custom property value
assert object[short_name] == '(inverse_bindposes: Weak(Uuid(uuid: "73b3b118-7d01-4778-8bcc-4e79055f5d22")), joints: [0, 0])' assert get_bevy_component_value_by_long_name(object, long_name) == '(inverse_bindposes: Weak(Uuid(uuid: "73b3b118-7d01-4778-8bcc-4e79055f5d22")), joints: [0, 0])'
# And another complex component # And another complex component
short_name = "CameraRenderGraph" long_name = "bevy_render::camera::camera::CameraRenderGraph"
component_type = registry.short_names_to_long_names[short_name] add_component_operator(component_type=long_name)
add_component_operator(component_type=component_type)
property_group_name = registry.get_propertyGroupName_from_shortName(short_name) property_group_name = registry.get_propertyGroupName_from_longName(long_name)
target_components_metadata = object.components_meta.components target_components_metadata = object.components_meta.components
component_meta = next(filter(lambda component: component["long_name"] == short_name, target_components_metadata), None) component_meta = next(filter(lambda component: component["long_name"] == long_name, target_components_metadata), None)
propertyGroup = getattr(component_meta, property_group_name, None) propertyGroup = getattr(component_meta, property_group_name, None)
definition = type_infos[component_type] definition = type_infos[long_name]
component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry) component_values_shuffler(seed= 17, property_group=propertyGroup, definition=definition, registry=registry)
print("propertyGroup", object[short_name]) print("propertyGroup", get_bevy_component_value_by_long_name(object, long_name))
# cheating / making things easier for us for complex types: we use the custom property value # cheating / making things easier for us for complex types: we use the custom property value
assert object[short_name] == 'None' assert get_bevy_component_value_by_long_name(object, long_name) == 'None'