Merge branch 'main' of github.com:kaosat-dev/Blender_bevy_components_worklflow into bevy_main
This commit is contained in:
commit
d00caaf414
|
@ -16,7 +16,7 @@ members = [
|
||||||
"examples/bevy_gltf_save_load/basic/",
|
"examples/bevy_gltf_save_load/basic/",
|
||||||
"examples/bevy_registry_export/basic",
|
"examples/bevy_registry_export/basic",
|
||||||
|
|
||||||
"testing/bevy_registry_export/basic"
|
"testing/bevy_example"
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
|
@ -34,9 +34,6 @@ semicolon_if_nothing_returned = "warn"
|
||||||
[profile.dev.package."*"]
|
[profile.dev.package."*"]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
[profile.dev.package.bevy]
|
|
||||||
features = ["dynamic"]
|
|
||||||
|
|
||||||
#### --------------------Production/ release-------------------------------
|
#### --------------------Production/ release-------------------------------
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = "debuginfo"
|
strip = "debuginfo"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bevy_gltf_blueprints"
|
name = "bevy_gltf_blueprints"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
authors = ["Mark 'kaosat-dev' Moissette"]
|
authors = ["Mark 'kaosat-dev' Moissette"]
|
||||||
description = "Adds the ability to define Blueprints/Prefabs for [Bevy](https://bevyengine.org/) inside gltf files and spawn them in Bevy."
|
description = "Adds the ability to define Blueprints/Prefabs for [Bevy](https://bevyengine.org/) inside gltf files and spawn them in Bevy."
|
||||||
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
|
|
|
@ -25,8 +25,8 @@ Here's a minimal usage example:
|
||||||
```toml
|
```toml
|
||||||
# Cargo.toml
|
# Cargo.toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy="0.12"
|
bevy="0.13"
|
||||||
bevy_gltf_blueprints = { version = "0.8"}
|
bevy_gltf_blueprints = { version = "0.9"}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ fn spawn_blueprint(
|
||||||
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
bevy_gltf_blueprints = "0.8"
|
bevy_gltf_blueprints = "0.9"
|
||||||
```
|
```
|
||||||
|
|
||||||
Or use `cargo add`:
|
Or use `cargo add`:
|
||||||
|
@ -346,8 +346,8 @@ The main branch is compatible with the latest Bevy release, while the branch `be
|
||||||
Compatibility of `bevy_gltf_blueprints` versions:
|
Compatibility of `bevy_gltf_blueprints` versions:
|
||||||
| `bevy_gltf_blueprints` | `bevy` |
|
| `bevy_gltf_blueprints` | `bevy` |
|
||||||
| :-- | :-- |
|
| :-- | :-- |
|
||||||
| `0.8` | `0.13` |
|
| `0.9` | `0.13` |
|
||||||
| `0.3 - 0.7` | `0.12` |
|
| `0.3 - 0.8` | `0.12` |
|
||||||
| `0.1 - 0.2` | `0.11` |
|
| `0.1 - 0.2` | `0.11` |
|
||||||
| branch `main` | `0.13` |
|
| branch `main` | `0.13` |
|
||||||
| branch `bevy_main` | `main` |
|
| branch `bevy_main` | `main` |
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bevy_gltf_components"
|
name = "bevy_gltf_components"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
authors = ["Mark 'kaosat-dev' Moissette"]
|
authors = ["Mark 'kaosat-dev' Moissette"]
|
||||||
description = "Allows you to define [Bevy](https://bevyengine.org/) components direclty inside gltf files and instanciate the components on the Bevy side."
|
description = "Allows you to define [Bevy](https://bevyengine.org/) components direclty inside gltf files and instanciate the components on the Bevy side."
|
||||||
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
|
|
|
@ -24,7 +24,7 @@ Here's a minimal usage example:
|
||||||
# Cargo.toml
|
# Cargo.toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy="0.13"
|
bevy="0.13"
|
||||||
bevy_gltf_components = { version = "0.4"}
|
bevy_gltf_components = { version = "0.5"}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ bevy_gltf_components = { version = "0.4"}
|
||||||
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
bevy_gltf_components = "0.4"
|
bevy_gltf_components = "0.5"
|
||||||
```
|
```
|
||||||
|
|
||||||
Or use `cargo add`:
|
Or use `cargo add`:
|
||||||
|
@ -71,7 +71,7 @@ cargo add bevy_gltf_components
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
starting with version 0.4, this plugin is configurable
|
starting with version 0.3, this plugin is configurable
|
||||||
Use the default configuration:
|
Use the default configuration:
|
||||||
|
|
||||||
```rust no_run
|
```rust no_run
|
||||||
|
@ -117,8 +117,8 @@ The main branch is compatible with the latest Bevy release, while the branch `be
|
||||||
Compatibility of `bevy_gltf_components` versions:
|
Compatibility of `bevy_gltf_components` versions:
|
||||||
| `bevy_gltf_components` | `bevy` |
|
| `bevy_gltf_components` | `bevy` |
|
||||||
| :-- | :-- |
|
| :-- | :-- |
|
||||||
| `0.4` | `0.13` |
|
| `0.5` | `0.13` |
|
||||||
| `0.2 - 0.3` | `0.12` |
|
| `0.2 - 0.4` | `0.12` |
|
||||||
| `0.1` | `0.11` |
|
| `0.1` | `0.11` |
|
||||||
| branch `main` | `0.13` |
|
| branch `main` | `0.13` |
|
||||||
| branch `bevy_main` | `main` |
|
| branch `bevy_main` | `main` |
|
||||||
|
|
|
@ -8,7 +8,13 @@ pub mod process_gltfs;
|
||||||
pub use process_gltfs::*;
|
pub use process_gltfs::*;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
|
<<<<<<< HEAD
|
||||||
ecs::{component::Component, reflect::ReflectComponent, system::Resource},
|
ecs::{component::Component, reflect::ReflectComponent, system::Resource},
|
||||||
|
=======
|
||||||
|
app::Startup,
|
||||||
|
ecs::system::{Res, Resource},
|
||||||
|
log::warn,
|
||||||
|
>>>>>>> 9cb9dda5d35c635d367fa81ca1a6c752cda9bc02
|
||||||
prelude::{App, IntoSystemConfigs, Plugin, SystemSet, Update},
|
prelude::{App, IntoSystemConfigs, Plugin, SystemSet, Update},
|
||||||
reflect::Reflect,
|
reflect::Reflect,
|
||||||
};
|
};
|
||||||
|
@ -72,12 +78,19 @@ impl Default for ComponentsFromGltfPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_for_legacy_mode(gltf_components_config: Res<GltfComponentsConfig>) {
|
||||||
|
if gltf_components_config.legacy_mode {
|
||||||
|
warn!("using simplified component definitions is deprecated since 0.3, prefer defining components with real ron values (use the bevy_components tool for Blender for simplicity) ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Plugin for ComponentsFromGltfPlugin {
|
impl Plugin for ComponentsFromGltfPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.register_type::<GltfProcessed>()
|
app.register_type::<GltfProcessed>()
|
||||||
.insert_resource(GltfComponentsConfig {
|
.insert_resource(GltfComponentsConfig {
|
||||||
legacy_mode: self.legacy_mode,
|
legacy_mode: self.legacy_mode,
|
||||||
})
|
})
|
||||||
|
.add_systems(Startup, check_for_legacy_mode)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(add_components_from_gltf_extras).in_set(GltfComponentsSet::Injection),
|
(add_components_from_gltf_extras).in_set(GltfComponentsSet::Injection),
|
||||||
|
|
|
@ -91,14 +91,11 @@ pub fn ronstring_to_reflect_component(
|
||||||
parsed_value = format!("({formated})");
|
parsed_value = format!("({formated})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: waaait this should be part of the legacy mode as it modifies the ron data ???
|
if parsed_value.is_empty() {
|
||||||
// so it means the values generated by the Blende add-on are incomplete (trivial to fix, but still)
|
parsed_value = "()".to_string();
|
||||||
if parsed_value.is_empty() {
|
}
|
||||||
parsed_value = "()".to_string();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ron_string = format!(
|
let ron_string = format!(
|
||||||
"{{ \"{}\":{} }}",
|
"{{ \"{}\":{} }}",
|
||||||
type_registration.type_info().type_path(),
|
type_registration.type_info().type_path(),
|
||||||
|
@ -106,7 +103,7 @@ pub fn ronstring_to_reflect_component(
|
||||||
);
|
);
|
||||||
|
|
||||||
// usefull to determine what an entity looks like Serialized
|
// usefull to determine what an entity looks like Serialized
|
||||||
/*let test_struct = VecOfColors(vec![Color::Rgba { red: 0., green: 0.0, blue: 0.0, alpha: 0.0 }]);//TuppleTestColor(Color::Rgba { red: 0., green: 0.0, blue: 0.0, alpha: 0.0 });
|
/*let test_struct = CameraRenderGraph::new("name");
|
||||||
let serializer = ReflectSerializer::new(&test_struct, &type_registry);
|
let serializer = ReflectSerializer::new(&test_struct, &type_registry);
|
||||||
let serialized =
|
let serialized =
|
||||||
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
|
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bevy_gltf_save_load"
|
name = "bevy_gltf_save_load"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
authors = ["Mark 'kaosat-dev' Moissette"]
|
authors = ["Mark 'kaosat-dev' Moissette"]
|
||||||
description = "Save & load your bevy games"
|
description = "Save & load your bevy games"
|
||||||
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
|
@ -18,5 +18,5 @@ bevy = { version = "0.13", default-features = false, features = ["bevy_asset", "
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.13", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] }
|
bevy = { version = "0.13", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] }
|
||||||
#bevy_gltf_blueprints = "0.7"
|
#bevy_gltf_blueprints = "0.9"
|
||||||
bevy_gltf_blueprints = { path = "../bevy_gltf_blueprints" }
|
bevy_gltf_blueprints = { path = "../bevy_gltf_blueprints" }
|
||||||
|
|
|
@ -35,8 +35,8 @@ Here's a minimal usage example:
|
||||||
# Cargo.toml
|
# Cargo.toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy="0.13"
|
bevy="0.13"
|
||||||
bevy_gltf_save_load = "0.3"
|
bevy_gltf_save_load = "0.4"
|
||||||
bevy_gltf_blueprints = "0.6" // also needed
|
bevy_gltf_blueprints = "0.9" // also needed
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust no_run
|
```rust no_run
|
||||||
|
@ -142,7 +142,11 @@ Add the following to your `[dependencies]` section in `Cargo.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
bevy_gltf_save_load = "0.3"
|
bevy_gltf_save_load = "0.3"
|
||||||
|
<<<<<<< HEAD
|
||||||
bevy_gltf_blueprints = "0.8" // also needed, as bevy_gltf_save_load does not re-export it at this time
|
bevy_gltf_blueprints = "0.8" // also needed, as bevy_gltf_save_load does not re-export it at this time
|
||||||
|
=======
|
||||||
|
bevy_gltf_blueprints = "0.6" // also needed, as bevy_gltf_save_load does not re-export it at this time
|
||||||
|
>>>>>>> 9cb9dda5d35c635d367fa81ca1a6c752cda9bc02
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -299,9 +303,9 @@ The main branch is compatible with the latest Bevy release, while the branch `be
|
||||||
Compatibility of `bevy_gltf_save_load` versions:
|
Compatibility of `bevy_gltf_save_load` versions:
|
||||||
| `bevy_gltf_save_load` | `bevy` |
|
| `bevy_gltf_save_load` | `bevy` |
|
||||||
| :-- | :-- |
|
| :-- | :-- |
|
||||||
| `0.3 ` | `0.13` |
|
| `0.4 ` | `0.13` |
|
||||||
| `0.1 - 0.2` | `0.12` |
|
| `0.1 -0.3` | `0.12` |
|
||||||
| branch `main` | `0.13` |
|
| branch `main` | `0.12` |
|
||||||
| branch `bevy_main` | `main` |
|
| branch `bevy_main` | `main` |
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bevy_registry_export"
|
name = "bevy_registry_export"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
authors = ["Mark 'kaosat-dev' Moissette", "Pascal 'Killercup' Hertleif"]
|
authors = ["Mark 'kaosat-dev' Moissette", "Pascal 'Killercup' Hertleif"]
|
||||||
description = "Allows you to define [Bevy](https://bevyengine.org/) components direclty inside gltf files and instanciate the components on the Bevy side."
|
description = "Allows you to define [Bevy](https://bevyengine.org/) components direclty inside gltf files and instanciate the components on the Bevy side."
|
||||||
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
homepage = "https://github.com/kaosat-dev/Blender_bevy_components_workflow"
|
||||||
|
|
|
@ -18,7 +18,7 @@ Here's a minimal usage example:
|
||||||
# Cargo.toml
|
# Cargo.toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy="0.13"
|
bevy="0.13"
|
||||||
bevy_registry_export = "0.2"
|
bevy_registry_export = "0.3"
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust no_run
|
```rust no_run
|
||||||
|
@ -44,7 +44,7 @@ take a look at the [example]('https://github.com/kaosat-dev/Blender_bevy_compone
|
||||||
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
bevy_registry_export = "0.2"
|
bevy_registry_export = "0.3"
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -112,9 +112,10 @@ The main branch is compatible with the latest Bevy release, while the branch `be
|
||||||
Compatibility of `bevy_registry_export` versions:
|
Compatibility of `bevy_registry_export` versions:
|
||||||
| `bevy_registry_export` | `bevy` | `bevy_components (Blender add-on)` |
|
| `bevy_registry_export` | `bevy` | `bevy_components (Blender add-on)` |
|
||||||
| :-- | :-- |:-- |
|
| :-- | :-- |:-- |
|
||||||
| `0.1 ` | `0.13` | `0.1 - 0.2` |
|
| `0.3 ` | `0.13` | `0.3` |
|
||||||
| `0.1 ` | `0.12` | `0.1 - 0.2` |
|
| `0.2 ` | `0.12` | `0.3` |
|
||||||
| branch `main` | `0.13` | `0.1.0` |
|
| `0.1 ` | `0.12` | `0.1 -0.2` |
|
||||||
|
| branch `main` | `0.12` | `0.1` |
|
||||||
| branch `bevy_main` | `main` | `n/a` |
|
| branch `bevy_main` | `main` | `n/a` |
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,14 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bevy_bevy_registry_export_basic_testing"
|
name = "bevy_example"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy="0.12"
|
bevy="0.12"
|
||||||
bevy_gltf_blueprints = { path = "../../../crates/bevy_gltf_blueprints" }
|
bevy_gltf_blueprints = { path = "../../crates/bevy_gltf_blueprints" }
|
||||||
bevy_registry_export = { path = "../../../crates/bevy_registry_export" }
|
bevy_registry_export = { path = "../../crates/bevy_registry_export" }
|
||||||
bevy_gltf_worlflow_examples_common = { path = "../../../examples/common" }
|
bevy_gltf_worlflow_examples_common = { path = "../../examples/common" }
|
||||||
|
|
||||||
bevy_rapier3d = { version = "0.23.0", features = [ "serde-serialize", "debug-render-3d", "enhanced-determinism"] }
|
bevy_rapier3d = { version = "0.23.0", features = [ "serde-serialize", "debug-render-3d", "enhanced-determinism"] }
|
||||||
bevy_asset_loader = { version = "0.18", features = ["standard_dynamic_assets" ]}
|
bevy_asset_loader = { version = "0.18", features = ["standard_dynamic_assets" ]}
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 645 KiB |
|
@ -0,0 +1,109 @@
|
||||||
|
pub mod in_game;
|
||||||
|
use std::{
|
||||||
|
fs::{self},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use bevy_gltf_blueprints::{AnimationPlayerLink, BlueprintName};
|
||||||
|
pub use in_game::*;
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
prelude::*, render::view::screenshot::ScreenshotManager, time::common_conditions::on_timer,
|
||||||
|
window::PrimaryWindow,
|
||||||
|
};
|
||||||
|
use bevy_gltf_worlflow_examples_common::{AppState, GameState};
|
||||||
|
|
||||||
|
use crate::{TupleTestF32, UnitTest};
|
||||||
|
|
||||||
|
fn start_game(mut next_app_state: ResMut<NextState<AppState>>) {
|
||||||
|
next_app_state.set(AppState::AppLoading);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the export from Blender worked correctly, we should have animations (simplified here by using AnimationPlayerLink)
|
||||||
|
// if the export from Blender worked correctly, we should have an Entity called "Cylinder" that has two components: UnitTest, TupleTestF32
|
||||||
|
// if the export from Blender worked correctly, we should have an Entity called "Blueprint4_nested" that has a child called "Blueprint3" that has a "BlueprintName" component with value Blueprint3
|
||||||
|
|
||||||
|
fn validate_export(
|
||||||
|
parents: Query<&Parent>,
|
||||||
|
children: Query<&Children>,
|
||||||
|
names: Query<&Name>,
|
||||||
|
blueprints: Query<(Entity, &Name, &BlueprintName)>,
|
||||||
|
animation_player_links: Query<(Entity, &AnimationPlayerLink)>,
|
||||||
|
exported_cylinder: Query<(Entity, &Name, &UnitTest, &TupleTestF32)>,
|
||||||
|
empties_candidates: Query<(Entity, &Name, &GlobalTransform)>,
|
||||||
|
) {
|
||||||
|
let animations_found = !animation_player_links.is_empty();
|
||||||
|
|
||||||
|
let mut cylinder_found = false;
|
||||||
|
if let Ok(nested_cylinder) = exported_cylinder.get_single() {
|
||||||
|
let parent_name = names
|
||||||
|
.get(parents.get(nested_cylinder.0).unwrap().get())
|
||||||
|
.unwrap();
|
||||||
|
cylinder_found = parent_name.to_string() == *"Cube.001"
|
||||||
|
&& nested_cylinder.1.to_string() == *"Cylinder"
|
||||||
|
&& nested_cylinder.3 .0 == 75.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nested_blueprint_found = false;
|
||||||
|
for (entity, name, blueprint_name) in blueprints.iter() {
|
||||||
|
if name.to_string() == *"Blueprint4_nested" && blueprint_name.0 == *"Blueprint4_nested" {
|
||||||
|
if let Ok(cur_children) = children.get(entity) {
|
||||||
|
for child in cur_children.iter() {
|
||||||
|
if let Ok((_, child_name, child_blueprint_name)) = blueprints.get(*child) {
|
||||||
|
if child_name.to_string() == *"Blueprint3"
|
||||||
|
&& child_blueprint_name.0 == *"Blueprint3"
|
||||||
|
{
|
||||||
|
nested_blueprint_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut empty_found = false;
|
||||||
|
for (_, name, _) in empties_candidates.iter() {
|
||||||
|
if name.to_string() == *"Empty" {
|
||||||
|
empty_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
"bevy_diagnostics.json",
|
||||||
|
format!(
|
||||||
|
"{{ \"animations\": {}, \"cylinder_found\": {} , \"nested_blueprint_found\": {}, \"empty_found\": {} }}",
|
||||||
|
animations_found, cylinder_found, nested_blueprint_found, empty_found
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("Unable to write file");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_screenshot(
|
||||||
|
main_window: Query<Entity, With<PrimaryWindow>>,
|
||||||
|
mut screenshot_manager: ResMut<ScreenshotManager>,
|
||||||
|
) {
|
||||||
|
screenshot_manager
|
||||||
|
.save_screenshot_to_disk(main_window.single(), "screenshot.png")
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exit_game(mut app_exit_events: ResMut<Events<bevy::app::AppExit>>) {
|
||||||
|
app_exit_events.send(bevy::app::AppExit);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GamePlugin;
|
||||||
|
impl Plugin for GamePlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(Update, (spawn_test).run_if(in_state(GameState::InGame)))
|
||||||
|
.add_systems(Update, validate_export)
|
||||||
|
.add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once
|
||||||
|
.add_systems(OnEnter(AppState::MenuRunning), start_game)
|
||||||
|
.add_systems(OnEnter(AppState::AppRunning), setup_game)
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
exit_game.run_if(on_timer(Duration::from_secs_f32(0.5))),
|
||||||
|
) // shut down the app after this time
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,11 +7,11 @@ use std::ops::Range;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct UnitTest;
|
pub struct UnitTest;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, Deref, DerefMut)]
|
#[derive(Component, Reflect, Default, Debug, Deref, DerefMut)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TupleTestF32(f32);
|
pub struct TupleTestF32(pub f32);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, Deref, DerefMut)]
|
#[derive(Component, Reflect, Default, Debug, Deref, DerefMut)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,98 +0,0 @@
|
||||||
use bevy::prelude::*;
|
|
||||||
use bevy_gltf_worlflow_examples_common::{AppState, InMainMenu};
|
|
||||||
|
|
||||||
pub fn setup_main_menu(mut commands: Commands) {
|
|
||||||
commands.spawn((Camera2dBundle::default(), InMainMenu));
|
|
||||||
|
|
||||||
commands.spawn((
|
|
||||||
TextBundle::from_section(
|
|
||||||
"SOME GAME TITLE !!",
|
|
||||||
TextStyle {
|
|
||||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
|
||||||
font_size: 18.0,
|
|
||||||
color: Color::WHITE,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.with_style(Style {
|
|
||||||
position_type: PositionType::Absolute,
|
|
||||||
top: Val::Px(100.0),
|
|
||||||
left: Val::Px(200.0),
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
InMainMenu,
|
|
||||||
));
|
|
||||||
|
|
||||||
commands.spawn((
|
|
||||||
TextBundle::from_section(
|
|
||||||
"New Game (press Enter to start, press T once the game is started for demo spawning)",
|
|
||||||
TextStyle {
|
|
||||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
|
||||||
font_size: 18.0,
|
|
||||||
color: Color::WHITE,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.with_style(Style {
|
|
||||||
position_type: PositionType::Absolute,
|
|
||||||
top: Val::Px(200.0),
|
|
||||||
left: Val::Px(200.0),
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
InMainMenu,
|
|
||||||
));
|
|
||||||
|
|
||||||
/*
|
|
||||||
commands.spawn((
|
|
||||||
TextBundle::from_section(
|
|
||||||
"Load Game",
|
|
||||||
TextStyle {
|
|
||||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
|
||||||
font_size: 18.0,
|
|
||||||
color: Color::WHITE,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.with_style(Style {
|
|
||||||
position_type: PositionType::Absolute,
|
|
||||||
top: Val::Px(250.0),
|
|
||||||
left: Val::Px(200.0),
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
InMainMenu
|
|
||||||
));
|
|
||||||
|
|
||||||
commands.spawn((
|
|
||||||
TextBundle::from_section(
|
|
||||||
"Exit Game",
|
|
||||||
TextStyle {
|
|
||||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
|
||||||
font_size: 18.0,
|
|
||||||
color: Color::WHITE,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.with_style(Style {
|
|
||||||
position_type: PositionType::Absolute,
|
|
||||||
top: Val::Px(300.0),
|
|
||||||
left: Val::Px(200.0),
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
InMainMenu
|
|
||||||
));*/
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn teardown_main_menu(bla: Query<Entity, With<InMainMenu>>, mut commands: Commands) {
|
|
||||||
for bli in bla.iter() {
|
|
||||||
commands.entity(bli).despawn_recursive();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main_menu(
|
|
||||||
keycode: Res<ButtonInput<KeyCode>>,
|
|
||||||
mut next_app_state: ResMut<NextState<AppState>>,
|
|
||||||
) {
|
|
||||||
if keycode.just_pressed(KeyCode::Enter) {
|
|
||||||
next_app_state.set(AppState::AppLoading);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
pub mod in_game;
|
|
||||||
pub use in_game::*;
|
|
||||||
|
|
||||||
pub mod in_main_menu;
|
|
||||||
pub use in_main_menu::*;
|
|
||||||
|
|
||||||
use bevy::prelude::*;
|
|
||||||
use bevy_gltf_worlflow_examples_common::{AppState, GameState};
|
|
||||||
|
|
||||||
pub struct GamePlugin;
|
|
||||||
impl Plugin for GamePlugin {
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.add_systems(
|
|
||||||
Update,
|
|
||||||
(spawn_test, spawn_test_unregisted_components).run_if(in_state(GameState::InGame)),
|
|
||||||
)
|
|
||||||
.add_systems(OnEnter(AppState::MenuRunning), setup_main_menu)
|
|
||||||
.add_systems(OnExit(AppState::MenuRunning), teardown_main_menu)
|
|
||||||
.add_systems(Update, main_menu.run_if(in_state(AppState::MenuRunning)))
|
|
||||||
.add_systems(OnEnter(AppState::AppRunning), setup_game);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,6 +18,8 @@ of your Bevy components you get a nicely packed custom_property to use with ...
|
||||||
> IMPORTANT !! if you have previously used v0.1 , v0.2 had a breaking change, please see [this](#regenerate-ui-values) section on how to upgrade your data to v0.2.\
|
> IMPORTANT !! if you have previously used v0.1 , v0.2 had a breaking change, please see [this](#regenerate-ui-values) section on how to upgrade your data to v0.2.\
|
||||||
This problem should not be present going forward
|
This problem should not be present going forward
|
||||||
|
|
||||||
|
> IMPORTANT !! if you have previously used v0.2 , v0.3 had a breaking change, please see [this](#regenerate-custom-property-values) section on how to upgrade your data to v0.3.
|
||||||
|
|
||||||
## Installation:
|
## Installation:
|
||||||
|
|
||||||
* grab the latest release zip file from the releases tab (choose the bevy_components releases !)
|
* grab the latest release zip file from the releases tab (choose the bevy_components releases !)
|
||||||
|
@ -206,6 +208,9 @@ It will add the component to the select object
|
||||||
|
|
||||||
![update custom properties for all](./docs/other_options2.png)
|
![update custom properties for all](./docs/other_options2.png)
|
||||||
|
|
||||||
|
> IMPORTANT !! use this if you have previously used v0.1 or v0.2 , as v0.3 had a breaking change, that makes it **necessary** to use this **once** to upgrade components data
|
||||||
|
You should also re-export your gltf files , otherwise you might run into issues
|
||||||
|
|
||||||
|
|
||||||
### regenerate UI values
|
### regenerate UI values
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ UI:
|
||||||
- [x] fix enums (see Clusterconfig)
|
- [x] fix enums (see Clusterconfig)
|
||||||
- [x] need an example with one tupple one struct
|
- [x] need an example with one tupple one struct
|
||||||
- [x] projection
|
- [x] projection
|
||||||
- [ ] additionalmassproperties
|
- [x] additionalmassproperties
|
||||||
- [x] fix tupleStructs (see TupleVecF32F32) => always the same problem of having us pre-parse data without knowing what we have inside
|
- [x] fix tupleStructs (see TupleVecF32F32) => always the same problem of having us pre-parse data without knowing what we have inside
|
||||||
- find a way to only split by level 0 (highest level) nesting "," seperators, ignoring any level of nesting until we dig one level deeper
|
- find a way to only split by level 0 (highest level) nesting "," seperators, ignoring any level of nesting until we dig one level deeper
|
||||||
- solve nesting level use issues
|
- solve nesting level use issues
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "bevy_components",
|
"name": "bevy_components",
|
||||||
"author": "kaosigh",
|
"author": "kaosigh",
|
||||||
"version": (0, 2, 0),
|
"version": (0, 3, 0),
|
||||||
"blender": (3, 4, 0),
|
"blender": (3, 4, 0),
|
||||||
"location": "VIEW_3D",
|
"location": "VIEW_3D",
|
||||||
"description": "UI to help create Bevy blueprints and components",
|
"description": "UI to help create Bevy blueprints and components",
|
||||||
|
|
|
@ -6,6 +6,7 @@ conversion_tables = {
|
||||||
"char": lambda value: '"'+value+'"',
|
"char": lambda value: '"'+value+'"',
|
||||||
"str": lambda value: '"'+value+'"',
|
"str": lambda value: '"'+value+'"',
|
||||||
"alloc::string::String": lambda value: '"'+value+'"',
|
"alloc::string::String": lambda value: '"'+value+'"',
|
||||||
|
"alloc::borrow::Cow<str>": lambda value: '"'+value+'"',
|
||||||
|
|
||||||
"glam::Vec2": lambda value: "Vec2(x:"+str(value[0])+ ", y:"+str(value[1])+")",
|
"glam::Vec2": lambda value: "Vec2(x:"+str(value[0])+ ", y:"+str(value[1])+")",
|
||||||
"glam::DVec2": lambda value: "DVec2(x:"+str(value[0])+ ", y:"+str(value[1])+")",
|
"glam::DVec2": lambda value: "DVec2(x:"+str(value[0])+ ", y:"+str(value[1])+")",
|
||||||
|
@ -39,7 +40,7 @@ def property_group_value_to_custom_property_value(property_group, definition, re
|
||||||
elif type_info == "Struct":
|
elif type_info == "Struct":
|
||||||
values = {}
|
values = {}
|
||||||
if len(property_group.field_names) ==0:
|
if len(property_group.field_names) ==0:
|
||||||
value = ''
|
value = '()'
|
||||||
else:
|
else:
|
||||||
for index, field_name in enumerate(property_group.field_names):
|
for index, field_name in enumerate(property_group.field_names):
|
||||||
item_type_name = definition["properties"][field_name]["type"]["$ref"].replace("#/$defs/", "")
|
item_type_name = definition["properties"][field_name]["type"]["$ref"].replace("#/$defs/", "")
|
||||||
|
@ -137,7 +138,6 @@ def property_group_value_to_custom_property_value(property_group, definition, re
|
||||||
value = conversion_tables[type_name](value) if is_value_type else value
|
value = conversion_tables[type_name](value) if is_value_type else value
|
||||||
value = '""' if isinstance(value, PropertyGroup) else value
|
value = '""' if isinstance(value, PropertyGroup) else value
|
||||||
|
|
||||||
|
|
||||||
#print("generating custom property value", value, type(value))
|
#print("generating custom property value", value, type(value))
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
value = value.replace("'", "")
|
value = value.replace("'", "")
|
||||||
|
|
|
@ -161,6 +161,8 @@ type_mappings = {
|
||||||
"glam::Quat": lambda value: parse_vec4(value, float, "Quat"),
|
"glam::Quat": lambda value: parse_vec4(value, float, "Quat"),
|
||||||
|
|
||||||
'alloc::string::String': lambda value: str(value.replace('"', "")),
|
'alloc::string::String': lambda value: str(value.replace('"', "")),
|
||||||
|
'alloc::borrow::Cow<str>': lambda value: str(value.replace('"', "")),
|
||||||
|
|
||||||
'bevy_render::color::Color': lambda value: parse_color(value, float, "Rgba"),
|
'bevy_render::color::Color': lambda value: parse_color(value, float, "Rgba"),
|
||||||
'bevy_ecs::Entity': lambda value: int(value),
|
'bevy_ecs::Entity': lambda value: int(value),
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ def toggle_watcher(self, context):
|
||||||
|
|
||||||
def watch_schema():
|
def watch_schema():
|
||||||
self = bpy.context.window_manager.components_registry
|
self = bpy.context.window_manager.components_registry
|
||||||
print("watching schema file for changes")
|
# print("watching schema file for changes")
|
||||||
try:
|
try:
|
||||||
stamp = os.stat(self.schemaFullPath).st_mtime
|
stamp = os.stat(self.schemaFullPath).st_mtime
|
||||||
stamp = str(stamp)
|
stamp = str(stamp)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut': '',
|
expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut': '()',
|
||||||
'Aabb': '(center: Vec3A(x:0.0, y:0.0, z:0.0), half_extents: Vec3A(x:0.0, y:0.0, z:0.0))',
|
'Aabb': '(center: Vec3A(x:0.0, y:0.0, z:0.0), half_extents: Vec3A(x:0.0, y:0.0, z:0.0))',
|
||||||
'AdditionalMassProperties': 'Mass(0.0)',
|
'AdditionalMassProperties': 'Mass(0.0)',
|
||||||
'AmbientLightSettings': '(brightness: 0.0, color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))',
|
'AmbientLightSettings': '(brightness: 0.0, color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))',
|
||||||
|
@ -14,20 +14,20 @@ expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNot
|
||||||
'0.0))',
|
'0.0))',
|
||||||
'BlueprintName': '(" ")',
|
'BlueprintName': '(" ")',
|
||||||
'BorderColor': '(Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))',
|
'BorderColor': '(Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0))',
|
||||||
'Button': '',
|
'Button': '()',
|
||||||
'CalculatedClip': '(clip: (max: Vec2(x:0.0, y:0.0), min: Vec2(x:0.0, y:0.0)))',
|
'CalculatedClip': '(clip: (max: Vec2(x:0.0, y:0.0), min: Vec2(x:0.0, y:0.0)))',
|
||||||
'Camera': '(hdr: true, is_active: true, msaa_writeback: true, order: 0, viewport: None)',
|
'Camera': '(hdr: true, is_active: true, msaa_writeback: true, order: 0, viewport: None)',
|
||||||
'Camera2d': '(clear_color: Default)',
|
'Camera2d': '(clear_color: Default)',
|
||||||
'Camera3d': '(clear_color: Default, depth_load_op: Clear(0.0), depth_texture_usages: "", '
|
'Camera3d': '(clear_color: Default, depth_load_op: Clear(0.0), depth_texture_usages: "", '
|
||||||
'screen_space_specular_transmission_quality: "", screen_space_specular_transmission_steps: 0)',
|
'screen_space_specular_transmission_quality: "", screen_space_specular_transmission_steps: 0)',
|
||||||
'CameraRenderGraph': '( )',
|
'CameraRenderGraph': '(" ")',
|
||||||
'CameraTrackable': '',
|
'CameraTrackable': '()',
|
||||||
'CameraTracking': '(offset: Vec3(x:0.0, y:0.0, z:0.0))',
|
'CameraTracking': '(offset: Vec3(x:0.0, y:0.0, z:0.0))',
|
||||||
'CameraTrackingOffset': '(Vec3(x:0.0, y:0.0, z:0.0))',
|
'CameraTrackingOffset': '(Vec3(x:0.0, y:0.0, z:0.0))',
|
||||||
'CascadeShadowConfig': '(bounds: [], minimum_distance: 0.0, overlap_proportion: 0.0)',
|
'CascadeShadowConfig': '(bounds: [], minimum_distance: 0.0, overlap_proportion: 0.0)',
|
||||||
'Cascades': '(cascades: "")',
|
'Cascades': '(cascades: "")',
|
||||||
'CascadesFrusta': '',
|
'CascadesFrusta': '()',
|
||||||
'CascadesVisibleEntities': '',
|
'CascadesVisibleEntities': '()',
|
||||||
'Ccd': '(enabled: true)',
|
'Ccd': '(enabled: true)',
|
||||||
'Children': '([])',
|
'Children': '([])',
|
||||||
'ClusterConfig': 'None',
|
'ClusterConfig': 'None',
|
||||||
|
@ -36,10 +36,10 @@ expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNot
|
||||||
'CollisionGroups': '(filters: (0), memberships: (0))',
|
'CollisionGroups': '(filters: (0), memberships: (0))',
|
||||||
'ColorGrading': '(exposure: 0.0, gamma: 0.0, post_saturation: 0.0, pre_saturation: 0.0)',
|
'ColorGrading': '(exposure: 0.0, gamma: 0.0, post_saturation: 0.0, pre_saturation: 0.0)',
|
||||||
'ContactForceEventThreshold': '(0.0)',
|
'ContactForceEventThreshold': '(0.0)',
|
||||||
'ContentSize': '',
|
'ContentSize': '()',
|
||||||
'ContrastAdaptiveSharpeningSettings': '(denoise: true, enabled: true, sharpening_strength: 0.0)',
|
'ContrastAdaptiveSharpeningSettings': '(denoise: true, enabled: true, sharpening_strength: 0.0)',
|
||||||
'CubemapFrusta': '',
|
'CubemapFrusta': '()',
|
||||||
'CubemapVisibleEntities': '',
|
'CubemapVisibleEntities': '()',
|
||||||
'Damping': '(angular_damping: 0.0, linear_damping: 0.0)',
|
'Damping': '(angular_damping: 0.0, linear_damping: 0.0)',
|
||||||
'DebandDither': 'Disabled',
|
'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, '
|
'DirectionalLight': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), illuminance: 0.0, shadow_depth_bias: 0.0, '
|
||||||
|
@ -53,7 +53,7 @@ expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNot
|
||||||
'FogSettings': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), directional_light_color: Rgba(red:1.0, '
|
'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: "")',
|
'green:1.0, blue:0.0, alpha:1.0), directional_light_exponent: 0.0, falloff: "")',
|
||||||
'Friction': '(coefficient: 0.0, combine_rule: "")',
|
'Friction': '(coefficient: 0.0, combine_rule: "")',
|
||||||
'Frustum': '',
|
'Frustum': '()',
|
||||||
'Fxaa': '(edge_threshold: "", edge_threshold_min: "", enabled: true)',
|
'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: '
|
'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)))',
|
'Vec3A(x:0.0, y:0.0, z:0.0)), translation: Vec3A(x:0.0, y:0.0, z:0.0)))',
|
||||||
|
@ -86,13 +86,13 @@ expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNot
|
||||||
'Handle<WireframeMaterial>': 'Strong("")',
|
'Handle<WireframeMaterial>': 'Strong("")',
|
||||||
'InheritedVisibility': '(true)',
|
'InheritedVisibility': '(true)',
|
||||||
'Interaction': 'Pressed',
|
'Interaction': 'Pressed',
|
||||||
'Label': '',
|
'Label': '()',
|
||||||
'LockedAxes': '(0)',
|
'LockedAxes': '(0)',
|
||||||
'MaterialInfo': '(name: " ", source: " ")',
|
'MaterialInfo': '(name: " ", source: " ")',
|
||||||
'Mesh2dHandle': '(Strong(""))',
|
'Mesh2dHandle': '(Strong(""))',
|
||||||
'MeshMorphWeights': '(weights: [])',
|
'MeshMorphWeights': '(weights: [])',
|
||||||
'MorphWeights': '(first_mesh: "", weights: [])',
|
'MorphWeights': '(first_mesh: "", weights: [])',
|
||||||
'Name': '(hash: 0, name: )',
|
'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)), '
|
'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))), '
|
'colors_list: ([]), enable: true, enum_inner: Metal, nested: (vec: (Vec3(x:0.0, y:0.0, z:0.0))), '
|
||||||
'text: " ", toggle: (true)))',
|
'text: " ", toggle: (true)))',
|
||||||
|
@ -100,37 +100,37 @@ expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNot
|
||||||
'colors_list: ([]), enable: true, enum_inner: Metal, nested: (vec: (Vec3(x:0.0, y:0.0, z:0.0))), '
|
'colors_list: ([]), enable: true, enum_inner: Metal, nested: (vec: (Vec3(x:0.0, y:0.0, z:0.0))), '
|
||||||
'text: " ", toggle: (true))',
|
'text: " ", toggle: (true))',
|
||||||
'NestingTestLevel3': '(vec: (Vec3(x:0.0, y:0.0, z:0.0)))',
|
'NestingTestLevel3': '(vec: (Vec3(x:0.0, y:0.0, z:0.0)))',
|
||||||
'NoFrustumCulling': '',
|
'NoFrustumCulling': '()',
|
||||||
'NoWireframe': '',
|
'NoWireframe': '()',
|
||||||
'Node': '(calculated_size: Vec2(x:0.0, y:0.0), outline_offset: 0.0, outline_width: 0.0, stack_index: 0, '
|
'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))',
|
'unrounded_size: Vec2(x:0.0, y:0.0))',
|
||||||
'NotShadowCaster': '',
|
'NotShadowCaster': '()',
|
||||||
'NotShadowReceiver': '',
|
'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: '
|
'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))',
|
'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)',
|
'Outline': '(color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), offset: Auto, width: Auto)',
|
||||||
'Parent': '(0)',
|
'Parent': '(0)',
|
||||||
'PerspectiveProjection': '(aspect_ratio: 0.0, far: 0.0, fov: 0.0, near: 0.0)',
|
'PerspectiveProjection': '(aspect_ratio: 0.0, far: 0.0, fov: 0.0, near: 0.0)',
|
||||||
'Pickable': '',
|
'Pickable': '()',
|
||||||
'Player': '',
|
'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, '
|
'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)',
|
'shadow_depth_bias: 0.0, shadow_normal_bias: 0.0, shadows_enabled: true)',
|
||||||
'PrimaryWindow': '',
|
'PrimaryWindow': '()',
|
||||||
'Projection': 'Perspective((aspect_ratio: 0.0, far: 0.0, fov: 0.0, near: 0.0))',
|
'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, '
|
'RelativeCursorPosition': '(normalized: "", normalized_visible_node_rect: (max: Vec2(x:0.0, y:0.0), min: Vec2(x:0.0, '
|
||||||
'y:0.0)))',
|
'y:0.0)))',
|
||||||
'RenderLayers': '(0)',
|
'RenderLayers': '(0)',
|
||||||
'Restitution': '(coefficient: 0.0, combine_rule: "")',
|
'Restitution': '(coefficient: 0.0, combine_rule: "")',
|
||||||
'RigidBody': 'Dynamic',
|
'RigidBody': 'Dynamic',
|
||||||
'SSAOSettings': '',
|
'SSAOSettings': '()',
|
||||||
'ScreenSpaceAmbientOcclusionSettings': '(quality_level: "")',
|
'ScreenSpaceAmbientOcclusionSettings': '(quality_level: "")',
|
||||||
'Sensor': '',
|
'Sensor': '()',
|
||||||
'ShadowFilteringMethod': 'Hardware2x2',
|
'ShadowFilteringMethod': 'Hardware2x2',
|
||||||
'ShadowmapSettings': '(size: 0)',
|
'ShadowmapSettings': '(size: 0)',
|
||||||
'SkinnedMesh': '(inverse_bindposes: Strong(""), joints: [])',
|
'SkinnedMesh': '(inverse_bindposes: Strong(""), joints: [])',
|
||||||
'Sleeping': '(angular_threshold: 0.0, linear_threshold: 0.0, sleeping: true)',
|
'Sleeping': '(angular_threshold: 0.0, linear_threshold: 0.0, sleeping: true)',
|
||||||
'SolverGroups': '(filters: (0), memberships: (0))',
|
'SolverGroups': '(filters: (0), memberships: (0))',
|
||||||
'SpawnHere': '',
|
'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: '
|
'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)',
|
'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, '
|
'Sprite': '(anchor: Center, color: Rgba(red:1.0, green:1.0, blue:0.0, alpha:1.0), custom_size: "", flip_x: true, '
|
||||||
|
@ -167,14 +167,14 @@ expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNot
|
||||||
'UiImage': '(flip_x: true, flip_y: true, texture: Strong(""))',
|
'UiImage': '(flip_x: true, flip_y: true, texture: Strong(""))',
|
||||||
'UiImageSize': '(size: Vec2(x:0.0, y:0.0))',
|
'UiImageSize': '(size: Vec2(x:0.0, y:0.0))',
|
||||||
'UiTextureAtlasImage': '(flip_x: true, flip_y: true, index: 0)',
|
'UiTextureAtlasImage': '(flip_x: true, flip_y: true, index: 0)',
|
||||||
'UnitTest': '',
|
'UnitTest': '()',
|
||||||
'VecOfColors': '([])',
|
'VecOfColors': '([])',
|
||||||
'VecOfF32s': '([])',
|
'VecOfF32s': '([])',
|
||||||
'VecOfVec3s2': '([])',
|
'VecOfVec3s2': '([])',
|
||||||
'Velocity': '(angvel: Vec3(x:0.0, y:0.0, z:0.0), linvel: Vec3(x:0.0, y:0.0, z:0.0))',
|
'Velocity': '(angvel: Vec3(x:0.0, y:0.0, z:0.0), linvel: Vec3(x:0.0, y:0.0, z:0.0))',
|
||||||
'ViewVisibility': '(true)',
|
'ViewVisibility': '(true)',
|
||||||
'Visibility': 'Inherited',
|
'Visibility': 'Inherited',
|
||||||
'VisibleEntities': '',
|
'VisibleEntities': '()',
|
||||||
'Window': '(canvas: None, composite_alpha_mode: Auto, cursor: (grab_mode: None, hit_test: true, icon: Default, '
|
'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), '
|
'visible: true), decorations: true, enabled_buttons: (close: true, maximize: true, minimize: true), '
|
||||||
'fit_canvas_to_parent: true, focused: true, ime_enabled: true, ime_position: Vec2(x:0.0, y:0.0), internal: '
|
'fit_canvas_to_parent: true, focused: true, ime_enabled: true, ime_position: Vec2(x:0.0, y:0.0), internal: '
|
||||||
|
@ -183,12 +183,13 @@ expected_custom_property_values = {'AComponentWithAnExtremlyExageratedOrMaybeNot
|
||||||
'resize_constraints: (max_height: 0.0, max_width: 0.0, min_height: 0.0, min_width: 0.0), resolution: '
|
'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: " ", '
|
'(physical_height: 0, physical_width: 0, scale_factor: 0.0, scale_factor_override: None), title: " ", '
|
||||||
'transparent: true, visible: true, window_level: AlwaysOnBottom, window_theme: "")',
|
'transparent: true, visible: true, window_level: AlwaysOnBottom, window_theme: "")',
|
||||||
'Wireframe': '',
|
'Wireframe': '()',
|
||||||
'ZIndex': 'Local(0)'}
|
'ZIndex': 'Local(0)'}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut': '',
|
|
||||||
|
expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExageratedOrMaybeNotButCouldBeNameOrWut': '()',
|
||||||
'Aabb': '(center: Vec3A(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), half_extents: '
|
'Aabb': '(center: Vec3A(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), half_extents: '
|
||||||
'Vec3A(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))',
|
'Vec3A(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))',
|
||||||
'AdditionalMassProperties': 'Mass(0.42888906598091125)',
|
'AdditionalMassProperties': 'Mass(0.42888906598091125)',
|
||||||
|
@ -207,22 +208,22 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'BlueprintName': '("sbnpsago")',
|
'BlueprintName': '("sbnpsago")',
|
||||||
'BorderColor': '(Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
|
'BorderColor': '(Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
|
||||||
'alpha:0.20609822869300842))',
|
'alpha:0.20609822869300842))',
|
||||||
'Button': '',
|
'Button': '()',
|
||||||
'CalculatedClip': '(clip: (max: Vec2(x:0.5714026093482971, y:0.42888906598091125), min: Vec2(x:0.5780913233757019, '
|
'CalculatedClip': '(clip: (max: Vec2(x:0.5714026093482971, y:0.42888906598091125), min: Vec2(x:0.5780913233757019, '
|
||||||
'y:0.20609822869300842)))',
|
'y:0.20609822869300842)))',
|
||||||
'Camera': '(hdr: true, is_active: false, msaa_writeback: false, order: 61, viewport: None)',
|
'Camera': '(hdr: true, is_active: false, msaa_writeback: false, order: 61, viewport: None)',
|
||||||
'Camera2d': '(clear_color: None)',
|
'Camera2d': '(clear_color: None)',
|
||||||
'Camera3d': '(clear_color: None, depth_load_op: Clear(0.42888906598091125), depth_texture_usages: "", '
|
'Camera3d': '(clear_color: None, depth_load_op: Clear(0.42888906598091125), depth_texture_usages: "", '
|
||||||
'screen_space_specular_transmission_quality: "", screen_space_specular_transmission_steps: 73)',
|
'screen_space_specular_transmission_quality: "", screen_space_specular_transmission_steps: 73)',
|
||||||
'CameraRenderGraph': '(sbnpsago)',
|
'CameraRenderGraph': '("sbnpsago")',
|
||||||
'CameraTrackable': '',
|
'CameraTrackable': '()',
|
||||||
'CameraTracking': '(offset: Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019))',
|
'CameraTracking': '(offset: Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019))',
|
||||||
'CameraTrackingOffset': '(Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019))',
|
'CameraTrackingOffset': '(Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019))',
|
||||||
'CascadeShadowConfig': '(bounds: [0.42888906598091125], minimum_distance: 0.5780913233757019, overlap_proportion: '
|
'CascadeShadowConfig': '(bounds: [0.42888906598091125], minimum_distance: 0.5780913233757019, overlap_proportion: '
|
||||||
'0.20609822869300842)',
|
'0.20609822869300842)',
|
||||||
'Cascades': '(cascades: "")',
|
'Cascades': '(cascades: "")',
|
||||||
'CascadesFrusta': '',
|
'CascadesFrusta': '()',
|
||||||
'CascadesVisibleEntities': '',
|
'CascadesVisibleEntities': '()',
|
||||||
'Ccd': '(enabled: true)',
|
'Ccd': '(enabled: true)',
|
||||||
'Children': '([0])',
|
'Children': '([0])',
|
||||||
'ClusterConfig': 'None',
|
'ClusterConfig': 'None',
|
||||||
|
@ -232,10 +233,10 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'ColorGrading': '(exposure: 0.5714026093482971, gamma: 0.42888906598091125, post_saturation: 0.5780913233757019, '
|
'ColorGrading': '(exposure: 0.5714026093482971, gamma: 0.42888906598091125, post_saturation: 0.5780913233757019, '
|
||||||
'pre_saturation: 0.20609822869300842)',
|
'pre_saturation: 0.20609822869300842)',
|
||||||
'ContactForceEventThreshold': '(0.5714026093482971)',
|
'ContactForceEventThreshold': '(0.5714026093482971)',
|
||||||
'ContentSize': '',
|
'ContentSize': '()',
|
||||||
'ContrastAdaptiveSharpeningSettings': '(denoise: true, enabled: false, sharpening_strength: 0.42888906598091125)',
|
'ContrastAdaptiveSharpeningSettings': '(denoise: true, enabled: false, sharpening_strength: 0.42888906598091125)',
|
||||||
'CubemapFrusta': '',
|
'CubemapFrusta': '()',
|
||||||
'CubemapVisibleEntities': '',
|
'CubemapVisibleEntities': '()',
|
||||||
'Damping': '(angular_damping: 0.5714026093482971, linear_damping: 0.42888906598091125)',
|
'Damping': '(angular_damping: 0.5714026093482971, linear_damping: 0.42888906598091125)',
|
||||||
'DebandDither': 'Disabled',
|
'DebandDither': 'Disabled',
|
||||||
'DirectionalLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
|
'DirectionalLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
|
||||||
|
@ -254,7 +255,7 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'green:0.8235888481140137, blue:0.6534725427627563, alpha:0.16022956371307373), '
|
'green:0.8235888481140137, blue:0.6534725427627563, alpha:0.16022956371307373), '
|
||||||
'directional_light_exponent: 0.5206693410873413, falloff: "")',
|
'directional_light_exponent: 0.5206693410873413, falloff: "")',
|
||||||
'Friction': '(coefficient: 0.5714026093482971, combine_rule: "")',
|
'Friction': '(coefficient: 0.5714026093482971, combine_rule: "")',
|
||||||
'Frustum': '',
|
'Frustum': '()',
|
||||||
'Fxaa': '(edge_threshold: "", edge_threshold_min: "", enabled: true)',
|
'Fxaa': '(edge_threshold: "", edge_threshold_min: "", enabled: true)',
|
||||||
'GlobalTransform': '((matrix3: (x_axis: Vec3A(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), '
|
'GlobalTransform': '((matrix3: (x_axis: Vec3A(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019), '
|
||||||
'y_axis: Vec3A(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137), z_axis: '
|
'y_axis: Vec3A(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137), z_axis: '
|
||||||
|
@ -289,13 +290,13 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'Handle<WireframeMaterial>': 'Strong("")',
|
'Handle<WireframeMaterial>': 'Strong("")',
|
||||||
'InheritedVisibility': '(true)',
|
'InheritedVisibility': '(true)',
|
||||||
'Interaction': 'None',
|
'Interaction': 'None',
|
||||||
'Label': '',
|
'Label': '()',
|
||||||
'LockedAxes': '(73)',
|
'LockedAxes': '(73)',
|
||||||
'MaterialInfo': '(name: "sbnpsago", source: "piuzfbqp")',
|
'MaterialInfo': '(name: "sbnpsago", source: "piuzfbqp")',
|
||||||
'Mesh2dHandle': '(Strong(""))',
|
'Mesh2dHandle': '(Strong(""))',
|
||||||
'MeshMorphWeights': '(weights: [0.42888906598091125])',
|
'MeshMorphWeights': '(weights: [0.42888906598091125])',
|
||||||
'MorphWeights': '(first_mesh: "", weights: [0.42888906598091125])',
|
'MorphWeights': '(first_mesh: "", weights: [0.42888906598091125])',
|
||||||
'Name': '(hash: 73, name: bnpsagop)',
|
'Name': '(hash: 73, name: "bnpsagop")',
|
||||||
'NestedTupleStuff': '(0.5714026093482971, 54, (basic: (a: 0.4825616776943207, b: 1, c: "gopiuzfb"), color: '
|
'NestedTupleStuff': '(0.5714026093482971, 54, (basic: (a: 0.4825616776943207, b: 1, c: "gopiuzfb"), color: '
|
||||||
'(Rgba(red:0.5206693410873413, green:0.3277728259563446, blue:0.24999667704105377, '
|
'(Rgba(red:0.5206693410873413, green:0.3277728259563446, blue:0.24999667704105377, '
|
||||||
'alpha:0.952816903591156)), colors_list: ([Rgba(red:0.0445563830435276, green:0.8601610660552979, '
|
'alpha:0.952816903591156)), colors_list: ([Rgba(red:0.0445563830435276, green:0.8601610660552979, '
|
||||||
|
@ -311,13 +312,13 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'(vec: (Vec3(x:0.1329781413078308, y:0.7678378224372864, z:0.9824132323265076))), text: '
|
'(vec: (Vec3(x:0.1329781413078308, y:0.7678378224372864, z:0.9824132323265076))), text: '
|
||||||
'"otmbsahe", toggle: (false))',
|
'"otmbsahe", toggle: (false))',
|
||||||
'NestingTestLevel3': '(vec: (Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019)))',
|
'NestingTestLevel3': '(vec: (Vec3(x:0.5714026093482971, y:0.42888906598091125, z:0.5780913233757019)))',
|
||||||
'NoFrustumCulling': '',
|
'NoFrustumCulling': '()',
|
||||||
'NoWireframe': '',
|
'NoWireframe': '()',
|
||||||
'Node': '(calculated_size: Vec2(x:0.5714026093482971, y:0.42888906598091125), outline_offset: 0.5780913233757019, '
|
'Node': '(calculated_size: Vec2(x:0.5714026093482971, y:0.42888906598091125), outline_offset: 0.5780913233757019, '
|
||||||
'outline_width: 0.20609822869300842, stack_index: 62, unrounded_size: Vec2(x:0.8235888481140137, '
|
'outline_width: 0.20609822869300842, stack_index: 62, unrounded_size: Vec2(x:0.8235888481140137, '
|
||||||
'y:0.6534725427627563))',
|
'y:0.6534725427627563))',
|
||||||
'NotShadowCaster': '',
|
'NotShadowCaster': '()',
|
||||||
'NotShadowReceiver': '',
|
'NotShadowReceiver': '()',
|
||||||
'OrthographicProjection': '(area: (max: Vec2(x:0.5714026093482971, y:0.42888906598091125), min: '
|
'OrthographicProjection': '(area: (max: Vec2(x:0.5714026093482971, y:0.42888906598091125), min: '
|
||||||
'Vec2(x:0.5780913233757019, y:0.20609822869300842)), far: 0.8133212327957153, near: '
|
'Vec2(x:0.5780913233757019, y:0.20609822869300842)), far: 0.8133212327957153, near: '
|
||||||
'0.8235888481140137, scale: 0.6534725427627563, scaling_mode: '
|
'0.8235888481140137, scale: 0.6534725427627563, scaling_mode: '
|
||||||
|
@ -328,13 +329,13 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'Parent': '(0)',
|
'Parent': '(0)',
|
||||||
'PerspectiveProjection': '(aspect_ratio: 0.5714026093482971, far: 0.42888906598091125, fov: 0.5780913233757019, near: '
|
'PerspectiveProjection': '(aspect_ratio: 0.5714026093482971, far: 0.42888906598091125, fov: 0.5780913233757019, near: '
|
||||||
'0.20609822869300842)',
|
'0.20609822869300842)',
|
||||||
'Pickable': '',
|
'Pickable': '()',
|
||||||
'Player': '',
|
'Player': '()',
|
||||||
'PointLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
|
'PointLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
|
||||||
'alpha:0.20609822869300842), intensity: 0.8133212327957153, radius: 0.8235888481140137, range: '
|
'alpha:0.20609822869300842), intensity: 0.8133212327957153, radius: 0.8235888481140137, range: '
|
||||||
'0.6534725427627563, shadow_depth_bias: 0.16022956371307373, shadow_normal_bias: 0.5206693410873413, '
|
'0.6534725427627563, shadow_depth_bias: 0.16022956371307373, shadow_normal_bias: 0.5206693410873413, '
|
||||||
'shadows_enabled: false)',
|
'shadows_enabled: false)',
|
||||||
'PrimaryWindow': '',
|
'PrimaryWindow': '()',
|
||||||
'Projection': 'Perspective((aspect_ratio: 0.42888906598091125, far: 0.5780913233757019, fov: 0.20609822869300842, '
|
'Projection': 'Perspective((aspect_ratio: 0.42888906598091125, far: 0.5780913233757019, fov: 0.20609822869300842, '
|
||||||
'near: 0.8133212327957153))',
|
'near: 0.8133212327957153))',
|
||||||
'RelativeCursorPosition': '(normalized: "", normalized_visible_node_rect: (max: Vec2(x:0.5714026093482971, '
|
'RelativeCursorPosition': '(normalized: "", normalized_visible_node_rect: (max: Vec2(x:0.5714026093482971, '
|
||||||
|
@ -342,15 +343,15 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'RenderLayers': '(73)',
|
'RenderLayers': '(73)',
|
||||||
'Restitution': '(coefficient: 0.5714026093482971, combine_rule: "")',
|
'Restitution': '(coefficient: 0.5714026093482971, combine_rule: "")',
|
||||||
'RigidBody': 'Dynamic',
|
'RigidBody': 'Dynamic',
|
||||||
'SSAOSettings': '',
|
'SSAOSettings': '()',
|
||||||
'ScreenSpaceAmbientOcclusionSettings': '(quality_level: "")',
|
'ScreenSpaceAmbientOcclusionSettings': '(quality_level: "")',
|
||||||
'Sensor': '',
|
'Sensor': '()',
|
||||||
'ShadowFilteringMethod': 'Jimenez14',
|
'ShadowFilteringMethod': 'Jimenez14',
|
||||||
'ShadowmapSettings': '(size: 73)',
|
'ShadowmapSettings': '(size: 73)',
|
||||||
'SkinnedMesh': '(inverse_bindposes: Strong(""), joints: [0, 0])',
|
'SkinnedMesh': '(inverse_bindposes: Strong(""), joints: [0, 0])',
|
||||||
'Sleeping': '(angular_threshold: 0.5714026093482971, linear_threshold: 0.42888906598091125, sleeping: true)',
|
'Sleeping': '(angular_threshold: 0.5714026093482971, linear_threshold: 0.42888906598091125, sleeping: true)',
|
||||||
'SolverGroups': '(filters: (73), memberships: (4))',
|
'SolverGroups': '(filters: (73), memberships: (4))',
|
||||||
'SpawnHere': '',
|
'SpawnHere': '()',
|
||||||
'SpotLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
|
'SpotLight': '(color: Rgba(red:0.5714026093482971, green:0.42888906598091125, blue:0.5780913233757019, '
|
||||||
'alpha:0.20609822869300842), inner_angle: 0.8133212327957153, intensity: 0.8235888481140137, '
|
'alpha:0.20609822869300842), inner_angle: 0.8133212327957153, intensity: 0.8235888481140137, '
|
||||||
'outer_angle: 0.6534725427627563, radius: 0.16022956371307373, range: 0.5206693410873413, '
|
'outer_angle: 0.6534725427627563, radius: 0.16022956371307373, range: 0.5206693410873413, '
|
||||||
|
@ -402,7 +403,7 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'UiImage': '(flip_x: true, flip_y: false, texture: Weak(Uuid(uuid: "73b3b118-7d01-4778-8bcc-4e79055f5d22")))',
|
'UiImage': '(flip_x: true, flip_y: false, texture: Weak(Uuid(uuid: "73b3b118-7d01-4778-8bcc-4e79055f5d22")))',
|
||||||
'UiImageSize': '(size: Vec2(x:0.5714026093482971, y:0.42888906598091125))',
|
'UiImageSize': '(size: Vec2(x:0.5714026093482971, y:0.42888906598091125))',
|
||||||
'UiTextureAtlasImage': '(flip_x: true, flip_y: false, index: 54)',
|
'UiTextureAtlasImage': '(flip_x: true, flip_y: false, index: 54)',
|
||||||
'UnitTest': '',
|
'UnitTest': '()',
|
||||||
'VecOfColors': '([Rgba(red:0.42888906598091125, green:0.5780913233757019, blue:0.20609822869300842, '
|
'VecOfColors': '([Rgba(red:0.42888906598091125, green:0.5780913233757019, blue:0.20609822869300842, '
|
||||||
'alpha:0.8133212327957153)])',
|
'alpha:0.8133212327957153)])',
|
||||||
'VecOfF32s': '([0.42888906598091125])',
|
'VecOfF32s': '([0.42888906598091125])',
|
||||||
|
@ -411,7 +412,7 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'Vec3(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))',
|
'Vec3(x:0.20609822869300842, y:0.8133212327957153, z:0.8235888481140137))',
|
||||||
'ViewVisibility': '(true)',
|
'ViewVisibility': '(true)',
|
||||||
'Visibility': 'Visible',
|
'Visibility': 'Visible',
|
||||||
'VisibleEntities': '',
|
'VisibleEntities': '()',
|
||||||
'Window': '(canvas: None, composite_alpha_mode: PostMultiplied, cursor: (grab_mode: Confined, hit_test: true, icon: '
|
'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: '
|
'Default, visible: false), decorations: false, enabled_buttons: (close: true, maximize: false, minimize: '
|
||||||
'true), fit_canvas_to_parent: false, focused: true, ime_enabled: true, ime_position: '
|
'true), fit_canvas_to_parent: false, focused: true, ime_enabled: true, ime_position: '
|
||||||
|
@ -423,5 +424,6 @@ expected_custom_property_values_randomized = {'AComponentWithAnExtremlyExagerate
|
||||||
'0.36258742213249207), resolution: (physical_height: 58, physical_width: 98, scale_factor: '
|
'0.36258742213249207), resolution: (physical_height: 58, physical_width: 98, scale_factor: '
|
||||||
'0.8600491285324097, scale_factor_override: None), title: "otmbsahe", transparent: false, visible: true, '
|
'0.8600491285324097, scale_factor_override: None), title: "otmbsahe", transparent: false, visible: true, '
|
||||||
'window_level: Normal, window_theme: "")',
|
'window_level: Normal, window_theme: "")',
|
||||||
'Wireframe': '',
|
'Wireframe': '()',
|
||||||
'ZIndex': 'Local(54)'}
|
'ZIndex': 'Local(54)'}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import bpy
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def setup_data(request):
|
||||||
|
print("\nSetting up resources...")
|
||||||
|
|
||||||
|
schemaPath = "../../testing/bevy_example/assets/registry.json"
|
||||||
|
|
||||||
|
yield {"schema_path": schemaPath}
|
||||||
|
|
||||||
|
def finalizer():
|
||||||
|
print("\nPerforming teardown...")
|
||||||
|
registry = bpy.context.window_manager.components_registry
|
||||||
|
|
||||||
|
type_infos = registry.type_infos
|
||||||
|
object = bpy.context.object
|
||||||
|
remove_component_operator = bpy.ops.object.remove_bevy_component
|
||||||
|
|
||||||
|
for type_name in type_infos:
|
||||||
|
definition = type_infos[type_name]
|
||||||
|
component_name = definition["short_name"]
|
||||||
|
if component_name in object:
|
||||||
|
try:
|
||||||
|
remove_component_operator(component_name=component_name)
|
||||||
|
except Exception as error:
|
||||||
|
pass
|
||||||
|
|
||||||
|
request.addfinalizer(finalizer)
|
||||||
|
|
||||||
|
return None
|
|
@ -1,5 +1,4 @@
|
||||||
import bpy
|
import bpy
|
||||||
import pytest
|
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
from ..propGroups.conversions_to_prop_group import property_group_value_from_custom_property_value
|
from ..propGroups.conversions_to_prop_group import property_group_value_from_custom_property_value
|
||||||
|
@ -7,37 +6,11 @@ from ..propGroups.conversions_from_prop_group import property_group_value_to_cus
|
||||||
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)
|
||||||
|
|
||||||
@pytest.fixture
|
from .setup_data import setup_data
|
||||||
def setup_data(request):
|
|
||||||
print("\nSetting up resources...")
|
|
||||||
|
|
||||||
def finalizer():
|
|
||||||
print("\nPerforming teardown...")
|
|
||||||
registry = bpy.context.window_manager.components_registry
|
|
||||||
#registry.schemaPath = "../../testing/bevy_registry_export/basic/assets/registry.json"
|
|
||||||
#bpy.ops.object.reload_registry()
|
|
||||||
|
|
||||||
type_infos = registry.type_infos
|
|
||||||
object = bpy.context.object
|
|
||||||
remove_component_operator = bpy.ops.object.remove_bevy_component
|
|
||||||
|
|
||||||
for type_name in type_infos:
|
|
||||||
definition = type_infos[type_name]
|
|
||||||
component_name = definition["short_name"]
|
|
||||||
if component_name in object:
|
|
||||||
try:
|
|
||||||
remove_component_operator(component_name=component_name)
|
|
||||||
except Exception as error:
|
|
||||||
pass
|
|
||||||
|
|
||||||
request.addfinalizer(finalizer)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def test_components_should_generate_correct_custom_properties(setup_data):
|
def test_components_should_generate_correct_custom_properties(setup_data):
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
registry.schemaPath = "../../testing/bevy_registry_export/basic/assets/registry.json"
|
registry.schemaPath = setup_data["schema_path"]
|
||||||
bpy.ops.object.reload_registry()
|
bpy.ops.object.reload_registry()
|
||||||
|
|
||||||
type_infos = registry.type_infos
|
type_infos = registry.type_infos
|
||||||
|
@ -83,9 +56,9 @@ def test_components_should_generate_correct_custom_properties(setup_data):
|
||||||
assert len(added_components) == 152
|
assert len(added_components) == 152
|
||||||
|
|
||||||
|
|
||||||
def test_components_should_generate_correct_custom_properties_with_randomozied_values(setup_data):
|
def test_components_should_generate_correct_custom_properties_with_randomized_values(setup_data):
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
registry.schemaPath = "../../testing/bevy_registry_export/basic/assets/registry.json"
|
registry.schemaPath = setup_data["schema_path"]
|
||||||
bpy.ops.object.reload_registry()
|
bpy.ops.object.reload_registry()
|
||||||
|
|
||||||
type_infos = registry.type_infos
|
type_infos = registry.type_infos
|
||||||
|
@ -136,7 +109,7 @@ def test_components_should_generate_correct_custom_properties_with_randomozied_v
|
||||||
|
|
||||||
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
|
||||||
registry.schemaPath = "../../testing/bevy_registry_export/basic/assets/registry.json"
|
registry.schemaPath = setup_data["schema_path"]
|
||||||
bpy.ops.object.reload_registry()
|
bpy.ops.object.reload_registry()
|
||||||
|
|
||||||
type_infos = registry.type_infos
|
type_infos = registry.type_infos
|
||||||
|
@ -195,7 +168,7 @@ def test_components_should_generate_correct_propertyGroup_values_from_custom_pro
|
||||||
|
|
||||||
def test_remove_components(setup_data):
|
def test_remove_components(setup_data):
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
registry.schemaPath = "../../testing/bevy_registry_export/basic/assets/registry.json"
|
registry.schemaPath = setup_data["schema_path"]
|
||||||
bpy.ops.object.reload_registry()
|
bpy.ops.object.reload_registry()
|
||||||
|
|
||||||
type_infos = registry.type_infos
|
type_infos = registry.type_infos
|
||||||
|
@ -244,10 +217,9 @@ def test_remove_components(setup_data):
|
||||||
def test_copy_paste_components(setup_data):
|
def test_copy_paste_components(setup_data):
|
||||||
context = bpy.context
|
context = bpy.context
|
||||||
registry = context.window_manager.components_registry
|
registry = context.window_manager.components_registry
|
||||||
registry.schemaPath = "../../testing/bevy_registry_export/basic/assets/registry.json"
|
registry.schemaPath = setup_data["schema_path"]
|
||||||
bpy.ops.object.reload_registry()
|
bpy.ops.object.reload_registry()
|
||||||
|
|
||||||
#component_type = "bevy_bevy_registry_export_basic_example::test_components::BasicTest"
|
|
||||||
short_name = "BasicTest"
|
short_name = "BasicTest"
|
||||||
component_type = registry.short_names_to_long_names[short_name]
|
component_type = registry.short_names_to_long_names[short_name]
|
||||||
|
|
||||||
|
@ -294,4 +266,3 @@ def test_copy_paste_components(setup_data):
|
||||||
|
|
||||||
a_fieldValue = getattr(propertyGroup, propertyGroup.field_names[0])
|
a_fieldValue = getattr(propertyGroup, propertyGroup.field_names[0])
|
||||||
assert a_fieldValue == 25.0
|
assert a_fieldValue == 25.0
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import bpy
|
import bpy
|
||||||
|
from .setup_data import setup_data
|
||||||
|
|
||||||
|
def test_blend(setup_data):
|
||||||
def test_blend():
|
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
registry.schemaPath = "../../testing/bevy_registry_export/basic/assets/registry.json"
|
registry.schemaPath = setup_data["schema_path"]
|
||||||
bpy.ops.object.reload_registry()
|
bpy.ops.object.reload_registry()
|
||||||
#print("registry type infos", registry.type_infos)
|
|
||||||
|
|
||||||
short_name = "BasicTest"
|
short_name = "BasicTest"
|
||||||
component_type = registry.short_names_to_long_names[short_name]
|
component_type = registry.short_names_to_long_names[short_name]
|
||||||
|
@ -19,11 +18,6 @@ def test_blend():
|
||||||
target_components_metadata = object.components_meta.components
|
target_components_metadata = object.components_meta.components
|
||||||
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
|
component_meta = next(filter(lambda component: component["name"] == short_name, target_components_metadata), None)
|
||||||
propertyGroup = getattr(component_meta, property_group_name, None)
|
propertyGroup = getattr(component_meta, property_group_name, None)
|
||||||
print("propertyGroup", propertyGroup, propertyGroup.field_names)
|
|
||||||
|
|
||||||
|
|
||||||
"""copy_component_operator = bpy.ops.object.copy_bevy_component
|
|
||||||
copy_component_operator()"""
|
|
||||||
|
|
||||||
|
|
||||||
assert propertyGroup.field_names == ['a', 'b', 'c']
|
assert propertyGroup.field_names == ['a', 'b', 'c']
|
|
@ -1,9 +1,10 @@
|
||||||
import bpy
|
import bpy
|
||||||
from .component_values_shuffler import component_values_shuffler
|
from .component_values_shuffler import component_values_shuffler
|
||||||
|
from .setup_data import setup_data
|
||||||
|
|
||||||
def test_shuffler():
|
def test_shuffler(setup_data):
|
||||||
registry = bpy.context.window_manager.components_registry
|
registry = bpy.context.window_manager.components_registry
|
||||||
registry.schemaPath = "../../testing/bevy_registry_export/basic/assets/registry.json"
|
registry.schemaPath = setup_data["schema_path"]
|
||||||
bpy.ops.object.reload_registry()
|
bpy.ops.object.reload_registry()
|
||||||
|
|
||||||
type_infos = registry.type_infos
|
type_infos = registry.type_infos
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "gltf_auto_export",
|
"name": "gltf_auto_export",
|
||||||
"author": "kaosigh",
|
"author": "kaosigh",
|
||||||
"version": (0, 12, 1),
|
"version": (0, 14, 0),
|
||||||
"blender": (3, 4, 0),
|
"blender": (3, 4, 0),
|
||||||
"location": "File > Import-Export",
|
"location": "File > Import-Export",
|
||||||
"description": "glTF/glb auto-export",
|
"description": "glTF/glb auto-export",
|
||||||
|
|
|
@ -21,6 +21,9 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
||||||
folder_path = os.path.dirname(file_path)
|
folder_path = os.path.dirname(file_path)
|
||||||
# get the preferences for our addon
|
# get the preferences for our addon
|
||||||
|
|
||||||
|
#should we use change detection or not
|
||||||
|
export_change_detection = getattr(addon_prefs, "export_change_detection")
|
||||||
|
|
||||||
export_blueprints = getattr(addon_prefs,"export_blueprints")
|
export_blueprints = getattr(addon_prefs,"export_blueprints")
|
||||||
export_output_folder = getattr(addon_prefs,"export_output_folder")
|
export_output_folder = getattr(addon_prefs,"export_output_folder")
|
||||||
|
|
||||||
|
@ -75,7 +78,7 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
||||||
if matching_collection is not None:
|
if matching_collection is not None:
|
||||||
changed_collections.append(matching_collection)
|
changed_collections.append(matching_collection)
|
||||||
|
|
||||||
collections_to_export = list(set(changed_collections + collections_not_on_disk))
|
collections_to_export = list(set(changed_collections + collections_not_on_disk)) if export_change_detection else collections
|
||||||
|
|
||||||
# we need to re_export everything if the export parameters have been changed
|
# we need to re_export everything if the export parameters have been changed
|
||||||
collections_to_export = collections if changed_export_parameters else collections_to_export
|
collections_to_export = collections if changed_export_parameters else collections_to_export
|
||||||
|
@ -110,14 +113,14 @@ def auto_export(changes_per_scene, changed_export_parameters, addon_prefs):
|
||||||
print("export MAIN scenes")
|
print("export MAIN scenes")
|
||||||
for scene_name in main_scene_names:
|
for scene_name in main_scene_names:
|
||||||
# we have more relaxed rules to determine if the main scenes have changed : any change is ok, (allows easier handling of changes, render settings etc)
|
# we have more relaxed rules to determine if the main scenes have changed : any change is ok, (allows easier handling of changes, render settings etc)
|
||||||
do_export_main_scene = changed_export_parameters or scene_name in changes_per_scene.keys() or not check_if_blueprint_on_disk(scene_name, export_levels_path, gltf_extension)
|
do_export_main_scene = not export_change_detection or changed_export_parameters or scene_name in changes_per_scene.keys() or not check_if_blueprint_on_disk(scene_name, export_levels_path, gltf_extension)
|
||||||
if do_export_main_scene:
|
if do_export_main_scene:
|
||||||
print(" exporting scene:", scene_name)
|
print(" exporting scene:", scene_name)
|
||||||
export_main_scene(bpy.data.scenes[scene_name], folder_path, addon_prefs, library_collections)
|
export_main_scene(bpy.data.scenes[scene_name], folder_path, addon_prefs, library_collections)
|
||||||
|
|
||||||
|
|
||||||
# now deal with blueprints/collections
|
# now deal with blueprints/collections
|
||||||
do_export_library_scene = changed_export_parameters or len(collections_to_export) > 0 # export_library_scene_name in changes_per_scene.keys()
|
do_export_library_scene = not export_change_detection or changed_export_parameters or len(collections_to_export) > 0 # export_library_scene_name in changes_per_scene.keys()
|
||||||
print("export LIBRARY")
|
print("export LIBRARY")
|
||||||
if do_export_library_scene:
|
if do_export_library_scene:
|
||||||
# we only want to go through the library scenes where our collections to export are present
|
# we only want to go through the library scenes where our collections to export are present
|
||||||
|
|
|
@ -33,7 +33,8 @@ def generate_gltf_export_preferences(addon_prefs):
|
||||||
export_skins=True,
|
export_skins=True,
|
||||||
export_morph=False,
|
export_morph=False,
|
||||||
export_apply=False,
|
export_apply=False,
|
||||||
export_animations=False
|
export_animations=False,
|
||||||
|
export_optimize_animation_size=False
|
||||||
)
|
)
|
||||||
|
|
||||||
for key in addon_prefs.__annotations__.keys():
|
for key in addon_prefs.__annotations__.keys():
|
||||||
|
|
|
@ -9,7 +9,8 @@ from ..helpers.helpers_collections import (get_exportable_collections)
|
||||||
from .auto_export import auto_export
|
from .auto_export import auto_export
|
||||||
|
|
||||||
class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
||||||
"""test"""
|
"""auto export gltf"""
|
||||||
|
#bl_idname = "object.xxx"
|
||||||
bl_idname = "export_scenes.auto_gltf"
|
bl_idname = "export_scenes.auto_gltf"
|
||||||
bl_label = "Apply settings"
|
bl_label = "Apply settings"
|
||||||
bl_options = {'PRESET', 'UNDO'}
|
bl_options = {'PRESET', 'UNDO'}
|
||||||
|
@ -21,7 +22,7 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
||||||
'export_main_scene_name',
|
'export_main_scene_name',
|
||||||
'export_output_folder',
|
'export_output_folder',
|
||||||
'export_library_scene_name',
|
'export_library_scene_name',
|
||||||
|
'export_change_detection',
|
||||||
'export_blueprints',
|
'export_blueprints',
|
||||||
'export_blueprints_path',
|
'export_blueprints_path',
|
||||||
|
|
||||||
|
@ -79,7 +80,17 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
||||||
# we inject all that we need, the above is not sufficient
|
# we inject all that we need, the above is not sufficient
|
||||||
for (k, v) in self.properties.items():
|
for (k, v) in self.properties.items():
|
||||||
if k in self.white_list or k not in AutoExportGltfPreferenceNames:
|
if k in self.white_list or k not in AutoExportGltfPreferenceNames:
|
||||||
export_props[k] = v
|
value = v
|
||||||
|
# FIXME: really weird having to do this
|
||||||
|
if k == "collection_instances_combine_mode":
|
||||||
|
value = self.collection_instances_combine_mode
|
||||||
|
if k == "export_format":
|
||||||
|
value = self.export_format
|
||||||
|
if k == "export_image_format":
|
||||||
|
value = self.export_image_format
|
||||||
|
if k == "export_materials":
|
||||||
|
value = self.export_materials
|
||||||
|
export_props[k] = value
|
||||||
# we add main & library scene names to our preferences
|
# we add main & library scene names to our preferences
|
||||||
|
|
||||||
export_props['main_scene_names'] = list(map(lambda scene_data: scene_data.name, getattr(self,"main_scenes")))
|
export_props['main_scene_names'] = list(map(lambda scene_data: scene_data.name, getattr(self,"main_scenes")))
|
||||||
|
@ -93,7 +104,7 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
||||||
#print("saving settings", bpy.data.texts[".gltf_auto_export_settings"].as_string(), "raw", json.dumps(export_props))
|
#print("saving settings", bpy.data.texts[".gltf_auto_export_settings"].as_string(), "raw", json.dumps(export_props))
|
||||||
|
|
||||||
def load_settings(self, context):
|
def load_settings(self, context):
|
||||||
#print("loading settings")
|
# print("loading settings")
|
||||||
settings = None
|
settings = None
|
||||||
try:
|
try:
|
||||||
settings = bpy.data.texts[".gltf_auto_export_settings"].as_string()
|
settings = bpy.data.texts[".gltf_auto_export_settings"].as_string()
|
||||||
|
@ -102,10 +113,10 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
||||||
|
|
||||||
self.will_save_settings = False
|
self.will_save_settings = False
|
||||||
if settings:
|
if settings:
|
||||||
#print("loading settings in invoke AutoExportGLTF", settings)
|
print("loading settings in invoke AutoExportGLTF", settings)
|
||||||
try:
|
try:
|
||||||
for (k, v) in settings.items():
|
for (k, v) in settings.items():
|
||||||
#print("loading setting", k, v)
|
print("loading setting", k, v)
|
||||||
setattr(self, k, v)
|
setattr(self, k, v)
|
||||||
self.will_save_settings = True
|
self.will_save_settings = True
|
||||||
|
|
||||||
|
@ -128,7 +139,8 @@ class AutoExportGLTF(Operator, AutoExportGltfAddonPreferences, ExportHelper):
|
||||||
item = library_scenes.add()
|
item = library_scenes.add()
|
||||||
item.name = item_name
|
item.name = item_name
|
||||||
|
|
||||||
except (AttributeError, TypeError):
|
except Exception as error:
|
||||||
|
print("error", error)
|
||||||
self.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
|
self.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings")
|
||||||
bpy.data.texts.remove(bpy.data.texts[".gltf_auto_export_settings"])
|
bpy.data.texts.remove(bpy.data.texts[".gltf_auto_export_settings"])
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ AutoExportGltfPreferenceNames = [
|
||||||
'export_main_scene_name',
|
'export_main_scene_name',
|
||||||
'export_output_folder',
|
'export_output_folder',
|
||||||
'export_library_scene_name',
|
'export_library_scene_name',
|
||||||
|
'export_change_detection',
|
||||||
|
|
||||||
'export_blueprints',
|
'export_blueprints',
|
||||||
'export_blueprints_path',
|
'export_blueprints_path',
|
||||||
|
@ -39,7 +40,7 @@ AutoExportGltfPreferenceNames = [
|
||||||
'library_scene_names',
|
'library_scene_names',
|
||||||
'previous_export_settings',
|
'previous_export_settings',
|
||||||
'filter_glob',
|
'filter_glob',
|
||||||
'will_save_settings'
|
'will_save_settings',
|
||||||
]
|
]
|
||||||
|
|
||||||
class AutoExportGltfAddonPreferences(AddonPreferences):
|
class AutoExportGltfAddonPreferences(AddonPreferences):
|
||||||
|
@ -86,6 +87,11 @@ class AutoExportGltfAddonPreferences(AddonPreferences):
|
||||||
description='The name of the library scene to auto export',
|
description='The name of the library scene to auto export',
|
||||||
default='Library'
|
default='Library'
|
||||||
)
|
)
|
||||||
|
export_change_detection: BoolProperty(
|
||||||
|
name='Change detection',
|
||||||
|
description='Use change detection to determine what/if should be exported',
|
||||||
|
default=True
|
||||||
|
)
|
||||||
# scene components
|
# scene components
|
||||||
export_scene_settings: BoolProperty(
|
export_scene_settings: BoolProperty(
|
||||||
name='Export scene settings',
|
name='Export scene settings',
|
||||||
|
|
|
@ -2,18 +2,60 @@ import bpy
|
||||||
from .helpers_collections import (set_active_collection)
|
from .helpers_collections import (set_active_collection)
|
||||||
from .object_makers import (make_empty)
|
from .object_makers import (make_empty)
|
||||||
|
|
||||||
|
|
||||||
|
# these are mostly for when using this add-on together with the bevy_components add-on
|
||||||
|
custom_properties_to_filter_out = ['_combine', 'template', 'components_meta']
|
||||||
|
|
||||||
|
def is_component_valid(object, component_name):
|
||||||
|
if "components_meta" in object:
|
||||||
|
target_components_metadata = object.components_meta.components
|
||||||
|
component_meta = next(filter(lambda component: component["name"] == component_name, target_components_metadata), None)
|
||||||
|
if component_meta != None:
|
||||||
|
return component_meta.enabled and not component_meta.invalid
|
||||||
|
return True
|
||||||
|
|
||||||
|
def remove_unwanted_custom_properties(object):
|
||||||
|
to_remove = []
|
||||||
|
for component_name in object.keys():
|
||||||
|
if not is_component_valid(object, component_name):
|
||||||
|
to_remove.append(component_name)
|
||||||
|
|
||||||
|
for cp in custom_properties_to_filter_out + to_remove:
|
||||||
|
if cp in object:
|
||||||
|
del object[cp]
|
||||||
|
|
||||||
|
def duplicate_object(object):
|
||||||
|
obj_copy = object.copy()
|
||||||
|
if object.data:
|
||||||
|
data = object.data.copy()
|
||||||
|
obj_copy.data = data
|
||||||
|
if object.animation_data and object.animation_data.action:
|
||||||
|
obj_copy.animation_data.action = object.animation_data.action.copy()
|
||||||
|
return obj_copy
|
||||||
|
|
||||||
|
#also removes unwanted custom_properties for all objects in hiearchy
|
||||||
|
def duplicate_object_recursive(object, parent, collection):
|
||||||
|
original_name = object.name
|
||||||
|
object.name = original_name + "____bak"
|
||||||
|
copy = duplicate_object(object)
|
||||||
|
copy.name = original_name
|
||||||
|
collection.objects.link(copy)
|
||||||
|
|
||||||
|
remove_unwanted_custom_properties(copy)
|
||||||
|
|
||||||
|
if parent:
|
||||||
|
copy.parent = parent
|
||||||
|
|
||||||
|
for child in object.children:
|
||||||
|
duplicate_object_recursive(child, copy, collection)
|
||||||
|
return copy
|
||||||
|
|
||||||
|
|
||||||
# copies the contents of a collection into another one while replacing library instances with empties
|
# copies the contents of a collection into another one while replacing library instances with empties
|
||||||
def copy_hollowed_collection_into(source_collection, destination_collection, parent_empty=None, filter=None, library_collections=[], addon_prefs={}):
|
def copy_hollowed_collection_into(source_collection, destination_collection, parent_empty=None, filter=None, library_collections=[], addon_prefs={}):
|
||||||
collection_instances_combine_mode = getattr(addon_prefs, "collection_instances_combine_mode")
|
collection_instances_combine_mode = getattr(addon_prefs, "collection_instances_combine_mode")
|
||||||
legacy_mode = getattr(addon_prefs, "export_legacy_mode")
|
legacy_mode = getattr(addon_prefs, "export_legacy_mode")
|
||||||
|
|
||||||
root_objects = []
|
|
||||||
special_properties= { # to be able to reset any special property afterwards
|
|
||||||
"combine": [],
|
|
||||||
}
|
|
||||||
|
|
||||||
collection_instances_combine_mode= collection_instances_combine_mode
|
collection_instances_combine_mode= collection_instances_combine_mode
|
||||||
|
|
||||||
for object in source_collection.objects:
|
for object in source_collection.objects:
|
||||||
if filter is not None and filter(object) is False:
|
if filter is not None and filter(object) is False:
|
||||||
continue
|
continue
|
||||||
|
@ -29,25 +71,22 @@ def copy_hollowed_collection_into(source_collection, destination_collection, par
|
||||||
empty_obj = make_empty(original_name, object.location, object.rotation_euler, object.scale, destination_collection)
|
empty_obj = make_empty(original_name, object.location, object.rotation_euler, object.scale, destination_collection)
|
||||||
"""we inject the collection/blueprint name, as a component called 'BlueprintName', but we only do this in the empty, not the original object"""
|
"""we inject the collection/blueprint name, as a component called 'BlueprintName', but we only do this in the empty, not the original object"""
|
||||||
empty_obj['BlueprintName'] = '"'+collection_name+'"' if legacy_mode else '("'+collection_name+'")'
|
empty_obj['BlueprintName'] = '"'+collection_name+'"' if legacy_mode else '("'+collection_name+'")'
|
||||||
empty_obj['SpawnHere'] = ''
|
empty_obj['SpawnHere'] = '()'
|
||||||
|
|
||||||
for k, v in object.items():
|
# we copy custom properties over from our original object to our empty
|
||||||
if k != 'template' or k != '_combine': # do not copy these properties
|
for component_name, component_value in object.items():
|
||||||
empty_obj[k] = v
|
if component_name not in custom_properties_to_filter_out and is_component_valid(object, component_name): #copy only valid properties
|
||||||
|
empty_obj[component_name] = component_value
|
||||||
if parent_empty is not None:
|
if parent_empty is not None:
|
||||||
empty_obj.parent = parent_empty
|
empty_obj.parent = parent_empty
|
||||||
else:
|
else:
|
||||||
# we backup special properties that we do not want to export, and remove them
|
|
||||||
if '_combine' in object:
|
# we create a copy of our object and its children, to leave the original one as it is
|
||||||
special_properties["combine"].append((object, object['_combine']))
|
if object.parent == None:
|
||||||
del object['_combine']
|
copy = duplicate_object_recursive(object, None, destination_collection)
|
||||||
|
|
||||||
if parent_empty is not None:
|
if parent_empty is not None:
|
||||||
object.parent = parent_empty
|
copy.parent = parent_empty
|
||||||
destination_collection.objects.link(object)
|
|
||||||
else:
|
|
||||||
root_objects.append(object)
|
|
||||||
destination_collection.objects.link(object)
|
|
||||||
|
|
||||||
# for every sub-collection of the source, copy its content into a new sub-collection of the destination
|
# for every sub-collection of the source, copy its content into a new sub-collection of the destination
|
||||||
for collection in source_collection.children:
|
for collection in source_collection.children:
|
||||||
|
@ -58,7 +97,7 @@ def copy_hollowed_collection_into(source_collection, destination_collection, par
|
||||||
if parent_empty is not None:
|
if parent_empty is not None:
|
||||||
collection_placeholder.parent = parent_empty
|
collection_placeholder.parent = parent_empty
|
||||||
|
|
||||||
nested_results = copy_hollowed_collection_into(
|
copy_hollowed_collection_into(
|
||||||
source_collection = collection,
|
source_collection = collection,
|
||||||
destination_collection = destination_collection,
|
destination_collection = destination_collection,
|
||||||
parent_empty = collection_placeholder,
|
parent_empty = collection_placeholder,
|
||||||
|
@ -66,19 +105,11 @@ def copy_hollowed_collection_into(source_collection, destination_collection, par
|
||||||
library_collections = library_collections,
|
library_collections = library_collections,
|
||||||
addon_prefs=addon_prefs
|
addon_prefs=addon_prefs
|
||||||
)
|
)
|
||||||
sub_root_objects = nested_results["root_objects"]
|
|
||||||
sub_special_properties = nested_results["special_properties"]
|
return {}
|
||||||
|
|
||||||
root_objects.extend(sub_root_objects)
|
|
||||||
for s in sub_special_properties.keys():
|
|
||||||
if not s in special_properties.keys():
|
|
||||||
special_properties[s] = []
|
|
||||||
special_properties[s].extend(sub_special_properties[s])
|
|
||||||
|
|
||||||
return {"root_objects": root_objects, "special_properties": special_properties}
|
|
||||||
|
|
||||||
# clear & remove "hollow scene"
|
# clear & remove "hollow scene"
|
||||||
def clear_hollow_scene(temp_scene, original_root_collection, root_objects, special_properties):
|
def clear_hollow_scene(temp_scene, original_root_collection):
|
||||||
def restore_original_names(collection):
|
def restore_original_names(collection):
|
||||||
if collection.name.endswith("____bak"):
|
if collection.name.endswith("____bak"):
|
||||||
collection.name = collection.name.replace("____bak", "")
|
collection.name = collection.name.replace("____bak", "")
|
||||||
|
@ -86,6 +117,9 @@ def clear_hollow_scene(temp_scene, original_root_collection, root_objects, speci
|
||||||
if object.instance_type == 'COLLECTION':
|
if object.instance_type == 'COLLECTION':
|
||||||
if object.name.endswith("____bak"):
|
if object.name.endswith("____bak"):
|
||||||
object.name = object.name.replace("____bak", "")
|
object.name = object.name.replace("____bak", "")
|
||||||
|
else:
|
||||||
|
if object.name.endswith("____bak"):
|
||||||
|
object.name = object.name.replace("____bak", "")
|
||||||
for child_collection in collection.children:
|
for child_collection in collection.children:
|
||||||
restore_original_names(child_collection)
|
restore_original_names(child_collection)
|
||||||
|
|
||||||
|
@ -96,37 +130,15 @@ def clear_hollow_scene(temp_scene, original_root_collection, root_objects, speci
|
||||||
temp_root_collection = temp_scene.collection
|
temp_root_collection = temp_scene.collection
|
||||||
temp_scene_objects = [o for o in temp_root_collection.objects]
|
temp_scene_objects = [o for o in temp_root_collection.objects]
|
||||||
for object in temp_scene_objects:
|
for object in temp_scene_objects:
|
||||||
if object.type == 'EMPTY':
|
bpy.data.objects.remove(object, do_unlink=True)
|
||||||
if hasattr(object, "SpawnHere"):
|
|
||||||
bpy.data.objects.remove(object, do_unlink=True)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
temp_root_collection.objects.unlink(object)
|
|
||||||
except:
|
|
||||||
print("failed to unlink", object)
|
|
||||||
if object in root_objects:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
bpy.data.objects.remove(object, do_unlink=True)
|
|
||||||
else:
|
|
||||||
temp_root_collection.objects.unlink(object)
|
|
||||||
|
|
||||||
# remove temporary collections
|
|
||||||
"""for collection in temporary_collections:
|
|
||||||
bpy.data.collections.remove(collection)"""
|
|
||||||
|
|
||||||
# put back special properties
|
|
||||||
for (object, value) in special_properties["combine"]:
|
|
||||||
object['_combine'] = value
|
|
||||||
|
|
||||||
# remove the temporary scene
|
# remove the temporary scene
|
||||||
bpy.data.scenes.remove(temp_scene)
|
bpy.data.scenes.remove(temp_scene)
|
||||||
|
|
||||||
|
|
||||||
# convenience utility to get lists of scenes
|
# convenience utility to get lists of scenes
|
||||||
def get_scenes(addon_prefs):
|
def get_scenes(addon_prefs):
|
||||||
level_scene_names= list(map(lambda scene: scene.name, getattr(addon_prefs,"main_scenes")))
|
level_scene_names= list(map(lambda scene: scene.name, getattr(addon_prefs,"main_scenes"))) # getattr(addon_prefs, "main_scene_names_compact").split(',')#
|
||||||
library_scene_names = list(map(lambda scene: scene.name, getattr(addon_prefs,"library_scenes")))
|
library_scene_names = list(map(lambda scene: scene.name, getattr(addon_prefs,"library_scenes"))) #getattr(addon_prefs, "main_scene_names_compact").split(',')#
|
||||||
|
|
||||||
level_scene_names = list(filter(lambda name: name in bpy.data.scenes, level_scene_names))
|
level_scene_names = list(filter(lambda name: name in bpy.data.scenes, level_scene_names))
|
||||||
library_scene_names = list(filter(lambda name: name in bpy.data.scenes, library_scene_names))
|
library_scene_names = list(filter(lambda name: name in bpy.data.scenes, library_scene_names))
|
||||||
|
|
|
@ -219,4 +219,24 @@ def did_export_parameters_change(current_params, previous_params):
|
||||||
print("copying ", key,"to", components_holder)
|
print("copying ", key,"to", components_holder)
|
||||||
if not key in components_holder:
|
if not key in components_holder:
|
||||||
components_holder[key] = components[key]
|
components_holder[key] = components[key]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# potentially useful alternative
|
||||||
|
def duplicate_object2(object, original_name):
|
||||||
|
print("copy object", object)
|
||||||
|
|
||||||
|
with bpy.context.temp_override(object=object, active_object = object):
|
||||||
|
bpy.ops.object.duplicate(linked=False)
|
||||||
|
new_obj = bpy.context.active_object
|
||||||
|
|
||||||
|
print("new obj", new_obj, "bpy.context.view_layer", bpy.context.view_layer.objects)
|
||||||
|
for obj in bpy.context.view_layer.objects:
|
||||||
|
print("obj", obj)
|
||||||
|
bpy.context.view_layer.update()
|
||||||
|
new_obj.name = original_name
|
||||||
|
|
||||||
|
if object.animation_data:
|
||||||
|
print("OJECT ANIMATION")
|
||||||
|
new_obj.animation_data.action = object.animation_data.action.copy()
|
||||||
|
|
||||||
|
return new_obj
|
|
@ -0,0 +1,9 @@
|
||||||
|
[pytest]
|
||||||
|
blender-template = ../../testing/bevy_example/assets/testing.blend
|
||||||
|
addopts = -svv
|
||||||
|
testpaths =
|
||||||
|
tests
|
||||||
|
|
||||||
|
# dependencies:
|
||||||
|
# pytest_blender
|
||||||
|
# pixelmatch
|
|
@ -0,0 +1,212 @@
|
||||||
|
import bpy
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
import pytest
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def setup_data(request):
|
||||||
|
print("\nSetting up resources...")
|
||||||
|
root_path = "../../testing/bevy_example"
|
||||||
|
assets_root_path = os.path.join(root_path, "assets")
|
||||||
|
|
||||||
|
models_path = os.path.join(assets_root_path, "models")
|
||||||
|
materials_path = os.path.join(assets_root_path, "materials")
|
||||||
|
other_materials_path = os.path.join(assets_root_path, "other_materials")
|
||||||
|
yield {"root_path": root_path, "assets_root_path": assets_root_path, "models_path": models_path, "materials_path": materials_path, "other_materials_path": other_materials_path}
|
||||||
|
|
||||||
|
def finalizer():
|
||||||
|
print("\nPerforming teardown...")
|
||||||
|
if os.path.exists(models_path):
|
||||||
|
shutil.rmtree(models_path)
|
||||||
|
|
||||||
|
if os.path.exists(materials_path):
|
||||||
|
shutil.rmtree(materials_path)
|
||||||
|
|
||||||
|
if os.path.exists(other_materials_path):
|
||||||
|
shutil.rmtree(other_materials_path)
|
||||||
|
|
||||||
|
|
||||||
|
request.addfinalizer(finalizer)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def test_export_do_not_export_blueprints(setup_data):
|
||||||
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
# first, configure things
|
||||||
|
# we use the global settings for that
|
||||||
|
export_props = {
|
||||||
|
"main_scene_names" : ['World'],
|
||||||
|
"library_scene_names": ['Library']
|
||||||
|
}
|
||||||
|
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||||
|
stored_settings.clear()
|
||||||
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
|
auto_export_operator(
|
||||||
|
direct_mode=True,
|
||||||
|
export_output_folder="./models",
|
||||||
|
export_scene_settings=True,
|
||||||
|
export_blueprints=False,
|
||||||
|
)
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "World.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint1.glb")) == False
|
||||||
|
|
||||||
|
def test_export_custom_blueprints_path(setup_data):
|
||||||
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
# first, configure things
|
||||||
|
# we use the global settings for that
|
||||||
|
export_props = {
|
||||||
|
"main_scene_names" : ['World'],
|
||||||
|
"library_scene_names": ['Library']
|
||||||
|
}
|
||||||
|
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||||
|
stored_settings.clear()
|
||||||
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
|
auto_export_operator(
|
||||||
|
direct_mode=True,
|
||||||
|
export_output_folder="./models",
|
||||||
|
export_scene_settings=True,
|
||||||
|
export_blueprints=True,
|
||||||
|
export_blueprints_path = "another_library_path"
|
||||||
|
)
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "World.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "another_library_path", "Blueprint1.glb")) == True
|
||||||
|
|
||||||
|
def test_export_materials_library(setup_data):
|
||||||
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
# first, configure things
|
||||||
|
# we use the global settings for that
|
||||||
|
export_props = {
|
||||||
|
"main_scene_names" : ['World'],
|
||||||
|
"library_scene_names": ['Library']
|
||||||
|
}
|
||||||
|
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||||
|
stored_settings.clear()
|
||||||
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
|
auto_export_operator(
|
||||||
|
direct_mode=True,
|
||||||
|
export_output_folder="./models",
|
||||||
|
export_scene_settings=True,
|
||||||
|
export_blueprints=True,
|
||||||
|
export_materials_library = True
|
||||||
|
)
|
||||||
|
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint1.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["materials_path"], "testing_materials_library.glb")) == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_materials_library_custom_path(setup_data):
|
||||||
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
# first, configure things
|
||||||
|
# we use the global settings for that
|
||||||
|
export_props = {
|
||||||
|
"main_scene_names" : ['World'],
|
||||||
|
"library_scene_names": ['Library']
|
||||||
|
}
|
||||||
|
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||||
|
stored_settings.clear()
|
||||||
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
|
auto_export_operator(
|
||||||
|
direct_mode=True,
|
||||||
|
export_output_folder="./models",
|
||||||
|
export_scene_settings=True,
|
||||||
|
export_blueprints=True,
|
||||||
|
export_materials_library = True,
|
||||||
|
export_materials_path="other_materials"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint1.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["materials_path"], "testing_materials_library.glb")) == False
|
||||||
|
assert os.path.exists(os.path.join(setup_data["other_materials_path"], "testing_materials_library.glb")) == True
|
||||||
|
|
||||||
|
def test_export_collection_instances_combine_mode(setup_data): # TODO: change & check this
|
||||||
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
# first, configure things
|
||||||
|
# we use the global settings for that
|
||||||
|
export_props = {
|
||||||
|
"main_scene_names" : ['World'],
|
||||||
|
"library_scene_names": ['Library']
|
||||||
|
}
|
||||||
|
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||||
|
stored_settings.clear()
|
||||||
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
|
|
||||||
|
bpy.data.objects["Cube"]["dynamic"] = True
|
||||||
|
|
||||||
|
auto_export_operator(
|
||||||
|
direct_mode=True,
|
||||||
|
export_output_folder="./models",
|
||||||
|
export_blueprints=True,
|
||||||
|
collection_instances_combine_mode = 'Embed'
|
||||||
|
)
|
||||||
|
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "World.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "World_dynamic.glb")) == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_do_not_export_marked_assets(setup_data):
|
||||||
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
# first, configure things
|
||||||
|
# we use the global settings for that
|
||||||
|
export_props = {
|
||||||
|
"main_scene_names" : ['World'],
|
||||||
|
"library_scene_names": ['Library']
|
||||||
|
}
|
||||||
|
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||||
|
stored_settings.clear()
|
||||||
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
|
auto_export_operator(
|
||||||
|
direct_mode=True,
|
||||||
|
export_output_folder="./models",
|
||||||
|
export_scene_settings=True,
|
||||||
|
export_blueprints=True,
|
||||||
|
export_marked_assets = False
|
||||||
|
)
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "World.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint1.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint2.glb")) == False
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint3.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint4_nested.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "library", "Blueprint5.glb")) == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_separate_dynamic_and_static_objects(setup_data):
|
||||||
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
# first, configure things
|
||||||
|
# we use the global settings for that
|
||||||
|
export_props = {
|
||||||
|
"main_scene_names" : ['World'],
|
||||||
|
"library_scene_names": ['Library']
|
||||||
|
}
|
||||||
|
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||||
|
stored_settings.clear()
|
||||||
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
|
|
||||||
|
bpy.data.objects["Cube"]["dynamic"] = True
|
||||||
|
|
||||||
|
auto_export_operator(
|
||||||
|
direct_mode=True,
|
||||||
|
export_output_folder="./models",
|
||||||
|
export_scene_settings=True,
|
||||||
|
export_blueprints=True,
|
||||||
|
export_separate_dynamic_and_static_objects = True
|
||||||
|
)
|
||||||
|
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "World.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(setup_data["models_path"], "World_dynamic.glb")) == True
|
|
@ -0,0 +1,125 @@
|
||||||
|
import bpy
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
import pytest
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
from pixelmatch.contrib.PIL import pixelmatch
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def setup_data(request):
|
||||||
|
print("\nSetting up resources...")
|
||||||
|
|
||||||
|
def finalizer():
|
||||||
|
root_path = "../../testing/bevy_example"
|
||||||
|
assets_root_path = os.path.join(root_path, "assets")
|
||||||
|
models_path = os.path.join(assets_root_path, "models")
|
||||||
|
#materials_path = os.path.join("../../testing", "materials")
|
||||||
|
#other_materials_path = os.path.join("../../testing", "other_materials")
|
||||||
|
|
||||||
|
print("\nPerforming teardown...")
|
||||||
|
if os.path.exists(models_path):
|
||||||
|
shutil.rmtree(models_path)
|
||||||
|
|
||||||
|
"""if os.path.exists(materials_path):
|
||||||
|
shutil.rmtree(materials_path)
|
||||||
|
|
||||||
|
if os.path.exists(other_materials_path):
|
||||||
|
shutil.rmtree(other_materials_path)"""
|
||||||
|
diagnostics_file_path = os.path.join(root_path, "bevy_diagnostics.json")
|
||||||
|
if os.path.exists(diagnostics_file_path):
|
||||||
|
os.remove(diagnostics_file_path)
|
||||||
|
|
||||||
|
screenshot_observed_path = os.path.join(root_path, "screenshot.png")
|
||||||
|
if os.path.exists(screenshot_observed_path):
|
||||||
|
os.remove(screenshot_observed_path)
|
||||||
|
|
||||||
|
request.addfinalizer(finalizer)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
- removes existing gltf files if needed
|
||||||
|
- calls exporter on the testing scene
|
||||||
|
- launches bevy app & checks for output
|
||||||
|
- if all worked => test is a-ok
|
||||||
|
"""
|
||||||
|
def test_export_complex(setup_data):
|
||||||
|
root_path = "../../testing/bevy_example"
|
||||||
|
assets_root_path = os.path.join(root_path, "assets")
|
||||||
|
models_path = os.path.join(assets_root_path, "models")
|
||||||
|
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||||
|
|
||||||
|
# with change detection
|
||||||
|
# first, configure things
|
||||||
|
# we use the global settings for that
|
||||||
|
export_props = {
|
||||||
|
"main_scene_names" : ['World'],
|
||||||
|
"library_scene_names": ['Library']
|
||||||
|
}
|
||||||
|
stored_settings = bpy.data.texts[".gltf_auto_export_settings"] if ".gltf_auto_export_settings" in bpy.data.texts else bpy.data.texts.new(".gltf_auto_export_settings")
|
||||||
|
stored_settings.clear()
|
||||||
|
stored_settings.write(json.dumps(export_props))
|
||||||
|
|
||||||
|
# move the main cube
|
||||||
|
bpy.data.objects["Cube"].location = [1, 0, 0]
|
||||||
|
# move the cube in the library
|
||||||
|
bpy.data.objects["Blueprint1_mesh"].location = [1, 2, 1]
|
||||||
|
|
||||||
|
auto_export_operator(
|
||||||
|
direct_mode=True,
|
||||||
|
export_output_folder="./models",
|
||||||
|
export_scene_settings=True,
|
||||||
|
export_blueprints=True,
|
||||||
|
export_legacy_mode=False,
|
||||||
|
export_animations=True
|
||||||
|
)
|
||||||
|
# blueprint1 => has an instance, got changed, should export
|
||||||
|
# blueprint2 => has NO instance, but marked as asset, should export
|
||||||
|
# blueprint3 => has NO instance, not marked as asset, used inside blueprint 4: should export
|
||||||
|
# blueprint4 => has an instance, with nested blueprint3, should export
|
||||||
|
# blueprint5 => has NO instance, not marked as asset, should NOT export
|
||||||
|
|
||||||
|
assert os.path.exists(os.path.join(models_path, "World.glb")) == True
|
||||||
|
|
||||||
|
assert os.path.exists(os.path.join(models_path, "library", "Blueprint1.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(models_path, "library", "Blueprint2.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(models_path, "library", "Blueprint3.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(models_path, "library", "Blueprint4_nested.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(models_path, "library", "Blueprint5.glb")) == False
|
||||||
|
assert os.path.exists(os.path.join(models_path, "library", "Blueprint6_animated.glb")) == True
|
||||||
|
assert os.path.exists(os.path.join(models_path, "library", "Blueprint7_hierarchy.glb")) == True
|
||||||
|
|
||||||
|
# now run bevy
|
||||||
|
bla = "cargo run --features bevy/dynamic_linking"
|
||||||
|
# assert getattr(propertyGroup, 'a') == 0.5714026093482971
|
||||||
|
FNULL = open(os.devnull, 'w') #use this if you want to suppress output to stdout from the subprocess
|
||||||
|
filename = "my_file.dat"
|
||||||
|
args = bla
|
||||||
|
#subprocess.call(args, stdout=FNULL, stderr=FNULL, shell=False, cwd=bevy_run_exec_path)
|
||||||
|
return_code = subprocess.call(["cargo", "run", "--features", "bevy/dynamic_linking"], cwd=root_path)
|
||||||
|
print("RETURN CODE OF BEVY APP", return_code)
|
||||||
|
assert return_code == 0
|
||||||
|
|
||||||
|
with open(os.path.join(root_path, "bevy_diagnostics.json")) as diagnostics_file:
|
||||||
|
diagnostics = json.load(diagnostics_file)
|
||||||
|
print("diagnostics", diagnostics)
|
||||||
|
assert diagnostics["animations"] == True
|
||||||
|
assert diagnostics["cylinder_found"] == True
|
||||||
|
assert diagnostics["empty_found"] == True
|
||||||
|
|
||||||
|
# last but not least, do a visual compare
|
||||||
|
screenshot_expected_path = os.path.join(root_path, "expected_screenshot.png")
|
||||||
|
screenshot_observed_path = os.path.join(root_path, "screenshot.png")
|
||||||
|
img_a = Image.open(screenshot_expected_path)
|
||||||
|
img_b = Image.open(screenshot_observed_path)
|
||||||
|
img_diff = Image.new("RGBA", img_a.size)
|
||||||
|
mismatch = pixelmatch(img_a, img_b, img_diff, includeAA=True)
|
||||||
|
print("image mismatch", mismatch)
|
||||||
|
assert mismatch < 50
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ class GLTF_PT_auto_export_main(bpy.types.Panel):
|
||||||
|
|
||||||
sfile = context.space_data
|
sfile = context.space_data
|
||||||
|
|
||||||
|
|
||||||
class GLTF_PT_auto_export_root(bpy.types.Panel):
|
class GLTF_PT_auto_export_root(bpy.types.Panel):
|
||||||
bl_space_type = 'FILE_BROWSER'
|
bl_space_type = 'FILE_BROWSER'
|
||||||
bl_region_type = 'TOOL_PROPS'
|
bl_region_type = 'TOOL_PROPS'
|
||||||
|
@ -66,6 +65,7 @@ class GLTF_PT_auto_export_root(bpy.types.Panel):
|
||||||
|
|
||||||
layout.active = operator.auto_export
|
layout.active = operator.auto_export
|
||||||
layout.prop(operator, 'will_save_settings')
|
layout.prop(operator, 'will_save_settings')
|
||||||
|
layout.prop(operator, "export_change_detection")
|
||||||
layout.prop(operator, "export_output_folder")
|
layout.prop(operator, "export_output_folder")
|
||||||
layout.prop(operator, "export_scene_settings")
|
layout.prop(operator, "export_scene_settings")
|
||||||
layout.prop(operator, "export_legacy_mode")
|
layout.prop(operator, "export_legacy_mode")
|
||||||
|
@ -124,8 +124,6 @@ class GLTF_PT_auto_export_root(bpy.types.Panel):
|
||||||
remove_operator.action = 'REMOVE'
|
remove_operator.action = 'REMOVE'
|
||||||
remove_operator.scene_type = 'library'
|
remove_operator.scene_type = 'library'
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GLTF_PT_auto_export_blueprints(bpy.types.Panel):
|
class GLTF_PT_auto_export_blueprints(bpy.types.Panel):
|
||||||
bl_space_type = 'FILE_BROWSER'
|
bl_space_type = 'FILE_BROWSER'
|
||||||
|
|
Loading…
Reference in New Issue