Compare commits
11 Commits
b0b241df21
...
acb66efa4c
Author | SHA1 | Date |
---|---|---|
Mark Moissette | acb66efa4c | |
kaosat.dev | 7e71e30187 | |
kaosat.dev | d15a9b7176 | |
kaosat.dev | 792672c2ef | |
kaosat.dev | e3cec403a2 | |
kaosat.dev | cb1f7b59a2 | |
kaosat.dev | 3f104fd7e9 | |
kaosat.dev | 72dbad0152 | |
kaosat.dev | 8c8e502f3a | |
kaosat.dev | 2031d1b8f2 | |
kaosat.dev | 1a7ea5bd4a |
|
@ -13,6 +13,15 @@ inside Blender. Aka "Blender as editor for Bevy"
|
|||
|
||||
It also allows you to setup 'blueprints' in Blender by using collections (the recomended way to go most of the time), or directly on single use objects .
|
||||
|
||||
|
||||
> [!CAUTION]
|
||||
> Blenvy is currently in **Alpha 1** state so there are still quite a few bugs, missing functionality, missing docs, broken examples etc
|
||||
> Please make sure you back up your Blender files before using it !
|
||||
|
||||
> [!CAUTION]
|
||||
> Please make sure to use matching versions numbers for the Blender add-on & the rust crate !
|
||||
> This is the only way to make sure everything works as intended
|
||||
|
||||
## Quickstart
|
||||
|
||||
Want to jump right in? See the [quickstart guide](./docs/quickstart/readme.md) for how to setup a basic project as fast as possible.
|
||||
|
|
34
TODO.md
|
@ -361,3 +361,37 @@ Bevy Side:
|
|||
- [x] finally deal cleanly with gltf export failures & make sure to always reset the state of the blend file
|
||||
|
||||
clear && pytest -svv --blender-template ../../testing/bevy_example/art/testing_library.blend --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration_prepare.py && pytest -svv --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration.py
|
||||
|
||||
-----------
|
||||
PRE ALPHA1 RELEASE:
|
||||
- [x] compress images in blender docs
|
||||
- [x] add a small note about using the same version of the Blender add-on & the Bevy crate
|
||||
- [x] do a quick check for the basics
|
||||
- [x] blender add-on
|
||||
- [x] barebones bevy test
|
||||
- [x] hot reload => some of it works, the rest not anymore ? (see bug https://github.com/bevyengine/bevy/issues/14698)
|
||||
- [ ] merge blenvy branch into main
|
||||
- [ ] push to crates.io
|
||||
- [ ] tag
|
||||
|
||||
------------
|
||||
POST ALPHA1 RELEASE:
|
||||
BEVY:
|
||||
- [ ] split up "spawn from blueprint"
|
||||
- [ ] cleanup very verbose messages
|
||||
- [ ] fix & cleanup trigger_instance_animation_markers_events
|
||||
- [ ] fix & cleanup save & load
|
||||
- [ ] experiment with Bevy side for splitting out animations
|
||||
- [ ] test hot reload a bit more , improve missing parts (see above)
|
||||
- [ ] make a fleshed out demo
|
||||
|
||||
BLENDER:
|
||||
- [ ] add "right click to edit blueprint"
|
||||
- [ ] overall cleanup
|
||||
- [ ] review wonky logic for cross file components injections
|
||||
- [ ] update & fix tests
|
||||
|
||||
------------
|
||||
BEFORE FINAL RELASE:
|
||||
- [ ] cleanup & regenerate all examples assets
|
||||
- [ ] cleanup & improve all docs
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
## SystemSet
|
||||
|
||||
the ordering of systems is very important !
|
||||
|
||||
For example to replace your proxy components (stand-in components when you cannot/ do not want to use real components in the gltf file) with actual ones, which should happen **AFTER** the Blueprint based spawning,
|
||||
|
||||
so ```blenvy``` provides a **SystemSet** for that purpose: ```GltfBlueprintsSet```
|
||||
|
||||
Typically , the order of systems should be
|
||||
|
||||
***blenvy (GltfComponentsSet::Injection)*** => ***blenvy (GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)*** => ***replace_proxies***
|
||||
|
||||
see https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/basic for how to set it up correctly
|
||||
|
||||
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ This way all your levels, your dynamic entities etc, are kept seperated from UI
|
|||
|
||||
## Registry
|
||||
|
||||
Blenvy automatically exports a Json file containing of all your registered components/ types, in order to be able to create UIs that allows you to add & edit your components directly in Blender in the [Blenvy](https://github.com/kaosat-dev/Blenvy/tree/main/tools/blenvy) Blender add-on
|
||||
Blenvy automatically exports a Json file containing of all your registered components/ types, in order to create UIs that allows you to add & edit your components directly in Blender in the [Blenvy](https://github.com/kaosat-dev/Blenvy/tree/main/tools/blenvy) Blender add-on
|
||||
- The output file will be generated in the ```Startup``` schedule whenever you run your app.
|
||||
- Every time you compile & run your app, the output json file will be updated.
|
||||
|
||||
|
@ -314,7 +314,7 @@ The main branch is compatible with the latest Bevy release, while the branch `be
|
|||
Compatibility of `blenvy` versions:
|
||||
| `blenvy` | `bevy` |
|
||||
| :-- | :-- |
|
||||
| `0.1` | `0.14` |
|
||||
| `0.1.0-alpha.1` | `0.14` |
|
||||
| branch `main` | `0.14` |
|
||||
| branch `bevy_main` | `main` |
|
||||
|
||||
|
|
|
@ -1,362 +0,0 @@
|
|||
[![Crates.io](https://img.shields.io/crates/v/bevy_gltf_blueprints)](https://crates.io/crates/bevy_gltf_blueprints)
|
||||
[![Docs](https://img.shields.io/docsrs/bevy_gltf_blueprints)](https://docs.rs/bevy_gltf_blueprints/latest/bevy_gltf_blueprints/)
|
||||
[![License](https://img.shields.io/crates/l/bevy_gltf_blueprints)](https://github.com/kaosat-dev/Blenvy/blob/main/crates/bevy_gltf_blueprints/License.md)
|
||||
[![Bevy tracking](https://img.shields.io/badge/Bevy%20tracking-released%20version-lightblue)](https://github.com/bevyengine/bevy/blob/main/docs/plugins_guidelines.md#main-branch-tracking)
|
||||
|
||||
# bevy_gltf_blueprints (deprecated in favor of Blenvy)
|
||||
|
||||
> bevy_gltf_blueprints has been deprecated in favor of its successor [Blenvy](https://crates.io/crates/blenvy), part of the [Blenvy project](https://github.com/kaosat-dev/Blenvy). No further development or maintenance will be done for Bevy bevy_gltf_blueprints. See [#194](https://github.com/kaosat-dev/Blenvy/issues/194) for background.
|
||||
|
||||
Built on [bevy_gltf_components](https://crates.io/crates/bevy_gltf_components) this crate adds the ability to define Blueprints/Prefabs for [Bevy](https://bevyengine.org/) inside gltf files and spawn them in Bevy.
|
||||
|
||||
* Allows you to create lightweight levels, where all assets are different gltf files and loaded after the main level is loaded
|
||||
* Allows you to spawn different entities from gtlf files at runtime in a clean manner, including simplified animation support !
|
||||
|
||||
A blueprint is a set of **overrideable** components + a hierarchy: ie
|
||||
|
||||
* just a Gltf file with Gltf_extras specifying components
|
||||
* a component called BlueprintName
|
||||
|
||||
Particularly useful when using [Blender](https://www.blender.org/) as an editor for the [Bevy](https://bevyengine.org/) game engine, combined with the Blender add-ons that do a lot of the work for you
|
||||
- [gltf_auto_export](https://github.com/kaosat-dev/Blenvy/tree/main/tools/gltf_auto_export)
|
||||
- [bevy_components](https://github.com/kaosat-dev/Blenvy/tree/main/tools/bevy_components)
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Here's a minimal usage example:
|
||||
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[dependencies]
|
||||
bevy="0.14"
|
||||
bevy_gltf_blueprints = { version = "0.11.0"}
|
||||
|
||||
```
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugins(BlueprintsPlugin)
|
||||
|
||||
.run();
|
||||
}
|
||||
|
||||
// not shown here: any other setup that is not specific to blueprints
|
||||
|
||||
fn spawn_blueprint(
|
||||
mut commands: Commands,
|
||||
keycode: Res<Input<KeyCode>>,
|
||||
){
|
||||
if keycode.just_pressed(KeyCode::S) {
|
||||
let new_entity = commands.spawn((
|
||||
BlueprintName("Health_Pickup".to_string()), // mandatory !!
|
||||
SpawnHere, // mandatory !!
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)), // VERY important !!
|
||||
// any other component you want to insert
|
||||
));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
bevy_gltf_blueprints = "0.11.0"
|
||||
```
|
||||
|
||||
Or use `cargo add`:
|
||||
|
||||
```toml
|
||||
cargo add bevy_gltf_blueprints
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugin(BlueprintsPlugin)
|
||||
|
||||
.run();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
you may want to configure your "library"/"blueprints" settings:
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
BlueprintsPlugin{
|
||||
library_folder: "advanced/models/library".into() // replace this with your blueprints library path , relative to the assets folder,
|
||||
format: GltfFormat::GLB,// optional, use either format: GltfFormat::GLB, or format: GltfFormat::GLTF, or ..Default::default() if you want to keep the default .glb extension, this sets what extensions/ gltf files will be looked for by the library
|
||||
aabbs: true, // defaults to false, enable this to automatically calculate aabb for the scene/blueprint
|
||||
material_library: true, // defaults to false, enable this to enable automatic injection of materials from material library files
|
||||
material_library_folder: "materials".into() //defaults to "materials" the folder to look for for the material files
|
||||
..Default::default()
|
||||
}
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Spawning entities from blueprints
|
||||
|
||||
You can spawn entities from blueprints like this:
|
||||
```rust no_run
|
||||
commands.spawn((
|
||||
BlueprintName("Health_Pickup".to_string()), // mandatory !!
|
||||
SpawnHere, // mandatory !!
|
||||
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)), // optional
|
||||
// any other component you want to insert
|
||||
))
|
||||
|
||||
```
|
||||
|
||||
Once spawning of the actual entity is done, the spawned Blueprint will be *gone/merged* with the contents of Blueprint !
|
||||
|
||||
> Important :
|
||||
you can **add** or **override** components present inside your Blueprint when spawning the BluePrint itself: ie
|
||||
|
||||
### Adding components not specified inside the blueprint
|
||||
|
||||
you can just add any additional components you need when spawning :
|
||||
|
||||
```rust no_run
|
||||
commands.spawn((
|
||||
BlueprintName("Health_Pickup".to_string()),
|
||||
SpawnHere,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
// from Rapier/bevy_xpbd: this means the entity will also have a velocity component when inserted into the world
|
||||
Velocity {
|
||||
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||
},
|
||||
))
|
||||
|
||||
```
|
||||
### Overriding components specified inside the blueprint
|
||||
|
||||
any component you specify when spawning the Blueprint that is also specified **within** the Blueprint will **override** that component in the final spawned entity
|
||||
|
||||
for example
|
||||
```rust no_run
|
||||
commands.spawn((
|
||||
BlueprintName("Health_Pickup".to_string()),
|
||||
SpawnHere,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
HealthPowerUp(20)// if this is component is also present inside the "Health_Pickup" blueprint, that one will be replaced with this component during spawning
|
||||
))
|
||||
|
||||
```
|
||||
|
||||
### BluePrintBundle
|
||||
|
||||
There is also a ```BluePrintBundle``` for convenience , which just has
|
||||
* a ```BlueprintName``` component
|
||||
* a ```SpawnHere``` component
|
||||
|
||||
## Additional information
|
||||
|
||||
- When a blueprint is spawned, all its children entities (and nested children etc) also have an ```InBlueprint``` component that gets insert
|
||||
- In cases where that is undesirable, you can add a ```NoInBlueprint``` component on the entity you spawn the blueprint with, and the components above will not be add
|
||||
- if you want to overwrite the **path** where this crate looks for blueprints (gltf files) , you can add a ```Library``` component , and that will be used instead of the default path
|
||||
ie :
|
||||
|
||||
```rust no_run
|
||||
commands
|
||||
.spawn((
|
||||
Name::from("test"),
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("TestBlueprint".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
Library("models".into()) // now the path to the blueprint above will be /assets/models/TestBlueprint.glb
|
||||
))
|
||||
```
|
||||
- this crate also provides a special optional ```GameWorldTag``` component: this is useful when you want to keep all your spawned entities inside a root entity
|
||||
|
||||
You can use it in your queries to add your entities as children of this "world"
|
||||
This way all your levels, your dynamic entities etc, are kept seperated from UI nodes & other entities that are not relevant to the game world
|
||||
|
||||
> Note: you should only have a SINGLE entity tagged with that component !
|
||||
|
||||
```rust no_run
|
||||
commands.spawn((
|
||||
SceneBundle {
|
||||
scene: models
|
||||
.get(game_assets.world.id())
|
||||
.expect("main level should have been loaded")
|
||||
.scenes[0]
|
||||
.clone(),
|
||||
..default()
|
||||
},
|
||||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag, // here it is
|
||||
));
|
||||
```
|
||||
|
||||
|
||||
## SystemSet
|
||||
|
||||
the ordering of systems is very important !
|
||||
|
||||
For example to replace your proxy components (stand-in components when you cannot/ do not want to use real components in the gltf file) with actual ones, which should happen **AFTER** the Blueprint based spawning,
|
||||
|
||||
so ```bevy_gltf_blueprints``` provides a **SystemSet** for that purpose: ```GltfBlueprintsSet```
|
||||
|
||||
Typically , the order of systems should be
|
||||
|
||||
***bevy_gltf_components (GltfComponentsSet::Injection)*** => ***bevy_gltf_blueprints (GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)*** => ***replace_proxies***
|
||||
|
||||
see an example [here](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/basic) for how to set it up correctly
|
||||
|
||||
|
||||
|
||||
## Animation
|
||||
|
||||
```bevy_gltf_blueprints``` provides some lightweight helpers to deal with animations stored in gltf files
|
||||
|
||||
* an ```Animations``` component that gets inserted into spawned (root) entities that contains a hashmap of all animations contained inside that entity/gltf file .
|
||||
(this is a copy of the ```named_animations``` inside Bevy's gltf structures )
|
||||
* an ```AnimationPlayerLink``` component that gets inserted into spawned (root) entities, to make it easier to trigger/ control animations than it usually is inside Bevy + Gltf files
|
||||
|
||||
The workflow for animations is as follows:
|
||||
* create a gltf file with animations (using Blender & co) as you would normally do
|
||||
* inside Bevy, use the ```bevy_gltf_blueprints``` boilerplate (see sections above), no specific setup beyond that is required
|
||||
* to control the animation of an entity, you need to query for entities that have both ```AnimationPlayerLink``` and ```Animations``` components (added by ```bevy_gltf_blueprints```) AND entities with the ```AnimationPlayer``` component
|
||||
|
||||
For example:
|
||||
|
||||
```rust no_run
|
||||
// example of changing animation of entities based on proximity to the player, for "fox" entities (Tag component)
|
||||
pub fn animation_change_on_proximity_foxes(
|
||||
players: Query<&GlobalTransform, With<Player>>,
|
||||
animated_foxes: Query<(&GlobalTransform, &AnimationPlayerLink, &Animations ), With<Fox>>,
|
||||
|
||||
mut animation_players: Query<&mut AnimationPlayer>,
|
||||
|
||||
){
|
||||
for player_transforms in players.iter() {
|
||||
for (fox_tranforms, link, animations) in animated_foxes.iter() {
|
||||
let distance = player_transforms
|
||||
.translation()
|
||||
.distance(fox_tranforms.translation());
|
||||
let mut anim_name = "Walk";
|
||||
if distance < 8.5 {
|
||||
anim_name = "Run";
|
||||
}
|
||||
else if distance >= 8.5 && distance < 10.0{
|
||||
anim_name = "Walk";
|
||||
}
|
||||
else if distance >= 10.0 && distance < 15.0{
|
||||
anim_name = "Survey";
|
||||
}
|
||||
// now play the animation based on the chosen animation name
|
||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
||||
animation_player.play_with_transition(
|
||||
animations.named_animations.get(anim_name).expect("animation name should be in the list").clone(),
|
||||
Duration::from_secs(3)
|
||||
).repeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
see [here](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/animation) for how to set it up correctly
|
||||
|
||||
particularly from [here](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/animation/src/game/in_game.rs)
|
||||
|
||||
|
||||
## Materials
|
||||
|
||||
You have the option of using "material libraries" to share common textures/materials between blueprints, in order to avoid asset & memory bloat:
|
||||
|
||||
Ie for example without this option, 56 different blueprints using the same material with a large texture would lead to the material/texture being embeded
|
||||
56 times !!
|
||||
|
||||
|
||||
you can configure this with the settings:
|
||||
```rust
|
||||
material_library: true // defaults to false, enable this to enable automatic injection of materials from material library files
|
||||
material_library_folder: "materials".into() //defaults to "materials" the folder to look for for the material files
|
||||
```
|
||||
|
||||
> Important! you must take care of preloading your material librairy gltf files in advance, using for example ```bevy_asset_loader```since
|
||||
```bevy_gltf_blueprints``` currently does NOT take care of loading those at runtime
|
||||
|
||||
|
||||
see an example [here](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/materials) for how to set it up correctly
|
||||
|
||||
Generating optimised blueprints and material libraries can be automated using the latests version of the [Blender plugin](https://github.com/kaosat-dev/Blenvy/tree/main/tools/gltf_auto_export)
|
||||
|
||||
|
||||
## Legacy mode
|
||||
|
||||
Starting in version 0.7 there is a new parameter ```legacy_mode``` for backwards compatibility
|
||||
|
||||
To disable the legacy mode: (enabled by default)
|
||||
|
||||
```rust no_run
|
||||
BlueprintsPlugin{legacy_mode: false}
|
||||
```
|
||||
|
||||
|
||||
You **need** to disable legacy mode if you want to use the [```bevy_components```](https://github.com/kaosat-dev/Blenvy/tree/tools_bevy_blueprints/tools/bevy_components) Blender addon + the [```bevy_registry_export crate```](https://crates.io/crates/bevy_registry_export) !
|
||||
As it create custom properties that are writen in real **ron** file format instead of a simplified version (the one in the legacy mode)
|
||||
|
||||
|
||||
> Note: the legacy mode support will be dropped in future versions, and the default behaviour will be NO legacy mode
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
* [basic](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/basic)
|
||||
|
||||
* [xbpd](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/basic_xpbd_physics)
|
||||
|
||||
* [animation](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/animation)
|
||||
|
||||
* [materials](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/materials)
|
||||
|
||||
* [multiple_levels_multiple_blendfiles](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_blueprints/multiple_levels_multiple_blendfiles)
|
||||
|
||||
|
||||
## Compatible Bevy versions
|
||||
|
||||
The main branch is compatible with the latest Bevy release, while the branch `bevy_main` tries to track the `main` branch of Bevy (PRs updating the tracked commit are welcome).
|
||||
|
||||
Compatibility of `bevy_gltf_blueprints` versions:
|
||||
| `bevy_gltf_blueprints` | `bevy` |
|
||||
| :-- | :-- |
|
||||
| `0.11` | `0.14` |
|
||||
| `0.9 - 0.10` | `0.13` |
|
||||
| `0.3 - 0.8` | `0.12` |
|
||||
| `0.1 - 0.2` | `0.11` |
|
||||
| branch `main` | `0.13` |
|
||||
| branch `bevy_main` | `main` |
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This crate, all its code, contents & assets is Dual-licensed under either of
|
||||
|
||||
- Apache License, Version 2.0, ([LICENSE-APACHE](./LICENSE_APACHE.md) or https://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](./LICENSE_MIT.md) or https://opensource.org/licenses/MIT)
|
|
@ -1,145 +0,0 @@
|
|||
[![Crates.io](https://img.shields.io/crates/v/bevy_gltf_components)](https://crates.io/crates/bevy_gltf_components)
|
||||
[![Docs](https://img.shields.io/docsrs/bevy_gltf_components)](https://docs.rs/bevy_gltf_components/latest/bevy_gltf_components/)
|
||||
[![License](https://img.shields.io/crates/l/bevy_gltf_components)](https://github.com/kaosat-dev/Blenvy/blob/main/crates/bevy_gltf_components/License.md)
|
||||
[![Bevy tracking](https://img.shields.io/badge/Bevy%20tracking-released%20version-lightblue)](https://github.com/bevyengine/bevy/blob/main/docs/plugins_guidelines.md#main-branch-tracking)
|
||||
|
||||
|
||||
# bevy_gltf_components (deprecated in favor of Blenvy)
|
||||
|
||||
> bevy_gltf_components has been deprecated in favor of its successor [Blenvy](https://crates.io/crates/blenvy), part of the [Blenvy project](https://github.com/kaosat-dev/Blenvy). No further development or maintenance will be done for Bevy bevy_gltf_components. See [#194](https://github.com/kaosat-dev/Blenvy/issues/194) for background.
|
||||
|
||||
This crate allows you to define [Bevy](https://bevyengine.org/) components direclty inside gltf files and instanciate the components on the Bevy side.
|
||||
|
||||
## Usage
|
||||
|
||||
***important*** : the plugin for processing gltf files runs in ***update*** , so you cannot use the components directly if you spawn your scene from gltf in ***setup*** (the additional components will not show up)
|
||||
|
||||
Please see the
|
||||
* [example](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_components/basic)
|
||||
* or use [```bevy_asset_loader```](https://github.com/NiklasEi/bevy_asset_loader) for reliable preloading of files, as this crate does not deal with loading your assets.
|
||||
* alternatively, use the [```bevy_gltf_blueprints```](https://crates.io/crates/bevy_gltf_blueprints) crate, built on this crate's features,
|
||||
that allows you to directly spawn entities from gltf based blueprints.
|
||||
|
||||
Here's a minimal usage example:
|
||||
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[dependencies]
|
||||
bevy="0.14"
|
||||
bevy_gltf_components = { version = "0.6"}
|
||||
|
||||
```
|
||||
|
||||
```rust no_run
|
||||
//too barebones of an example to be meaningfull, please see https://github.com/kaosat-dev/Blenvy/bevy_gltf_components/examples/basic for a real example
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugin(ComponentsFromGltfPlugin::default())
|
||||
.add_system(spawn_level)
|
||||
.run();
|
||||
}
|
||||
|
||||
fn spawn_level(
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: bevy::prelude::Commands,
|
||||
keycode: Res<Input<KeyCode>>,
|
||||
|
||||
){
|
||||
if keycode.just_pressed(KeyCode::Return) {
|
||||
commands.spawn(SceneBundle {
|
||||
scene: asset_server.load("basic/models/level1.glb#Scene0"),
|
||||
transform: Transform::from_xyz(2.0, 0.0, -5.0),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
bevy_gltf_components = "0.6"
|
||||
```
|
||||
|
||||
Or use `cargo add`:
|
||||
|
||||
```toml
|
||||
cargo add bevy_gltf_components
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
starting with version 0.3, this plugin is configurable
|
||||
Use the default configuration:
|
||||
|
||||
```rust no_run
|
||||
ComponentsFromGltfPlugin::default()
|
||||
```
|
||||
|
||||
Or disable the legacy mode: (enabled by default)
|
||||
|
||||
```rust no_run
|
||||
ComponentsFromGltfPlugin{legacy_mode: false}
|
||||
```
|
||||
|
||||
You **need** to disable legacy mode if you want to use the [```bevy_components```](https://github.com/kaosat-dev/Blenvy/tree/main/tools/bevy_components) Blender addon + the [```bevy_registry_export crate```](https://crates.io/crates/bevy_registry_export) !
|
||||
As it create custom properties that are writen in real **ron** file format
|
||||
instead of a simplified version (the one in the legacy mode)
|
||||
|
||||
> Note: the legacy mode support will be dropped in future versions, and the default behaviour will be NO legacy mode
|
||||
|
||||
## SystemSet
|
||||
|
||||
the ordering of systems is very important !
|
||||
|
||||
For example to replace your proxy components (stand-in components when you cannot/ do not want to use real components in the gltf file) with actual ones,
|
||||
|
||||
which should happen **AFTER** the components from the gltf files have been injected,
|
||||
|
||||
so ```bevy_gltf_components``` provides a **SystemSet** for that purpose:```GltfComponentsSet```
|
||||
|
||||
Typically , the order of systems should be
|
||||
|
||||
***bevy_gltf_components (GltfComponentsSet::Injection)*** => ***replace_proxies***
|
||||
|
||||
## Additional features
|
||||
|
||||
- as of version 0.5 , this crate also includes automatic handling of lights in gltf files, to attempt to match Blender's eevee rendering as close as possible:
|
||||
* **BlenderLightShadows** (automatically generated by the gltf_auto_export Blender add-on) allows you to toggle light's shadows on/off in Blender and have matching
|
||||
behaviour in Bevy
|
||||
* **BlenderBackgroundShader** aka background color is also automatically set on the Bevy side
|
||||
* **BlenderShadowSettings** sets the cascade_size on the bevy side to match the one configured in Blender
|
||||
|
||||
If these components are present in your gltf file, they will be handled automatically by this crate, will be ignored otherwise.
|
||||
|
||||
## Examples
|
||||
|
||||
https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_components/basic
|
||||
|
||||
|
||||
|
||||
## Compatible Bevy versions
|
||||
|
||||
The main branch is compatible with the latest Bevy release, while the branch `bevy_main` tries to track the `main` branch of Bevy (PRs updating the tracked commit are welcome).
|
||||
|
||||
Compatibility of `bevy_gltf_components` versions:
|
||||
| `bevy_gltf_components` | `bevy` |
|
||||
| :-- | :-- |
|
||||
| `0.6` | `0.14` |
|
||||
| `0.5` | `0.13` |
|
||||
| `0.2 - 0.4` | `0.12` |
|
||||
| `0.1` | `0.11` |
|
||||
| branch `main` | `0.13` |
|
||||
| branch `bevy_main` | `main` |
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This crate, all its code, contents & assets is Dual-licensed under either of
|
||||
|
||||
- Apache License, Version 2.0, ([LICENSE-APACHE](./LICENSE_APACHE.md) or https://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](./LICENSE_MIT.md) or https://opensource.org/licenses/MIT)
|
|
@ -1,136 +0,0 @@
|
|||
[![Crates.io](https://img.shields.io/crates/v/bevy_registry_export)](https://crates.io/crates/bevy_registry_export)
|
||||
[![Docs](https://img.shields.io/docsrs/bevy_registry_export)](https://docs.rs/bevy_registry_export/latest/bevy_registry_export/)
|
||||
[![License](https://img.shields.io/crates/l/bevy_registry_export)](https://github.com/kaosat-dev/Blenvy/blob/main/crates/bevy_registry_export/License.md)
|
||||
[![Bevy tracking](https://img.shields.io/badge/Bevy%20tracking-released%20version-lightblue)](https://github.com/bevyengine/bevy/blob/main/docs/plugins_guidelines.md#main-branch-tracking)
|
||||
|
||||
# bevy_registry_export (deprecated in favor of Blenvy)
|
||||
|
||||
> bevy_registry_export has been deprecated in favor of its successor [Blenvy](https://crates.io/crates/blenvy), part of the [Blenvy project](https://github.com/kaosat-dev/Blenvy). No further development or maintenance will be done for Bevy bevy_registry_export. See [#194](https://github.com/kaosat-dev/Blenvy/issues/194) for background.
|
||||
|
||||
|
||||
This plugin allows you to create a Json export of all your components/ registered types.
|
||||
Its main use case is as a backbone for the [```bevy_components``` Blender add-on](https://github.com/kaosat-dev/Blenvy/tree/main/tools/bevy_components), that allows you to add & edit components directly in Blender, using the actual type definitions from Bevy
|
||||
(and any of your custom types & components that you register in Bevy).
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Here's a minimal usage example:
|
||||
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[dependencies]
|
||||
bevy="0.14"
|
||||
bevy_registry_export = "0.4"
|
||||
```
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_registry_export::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins,
|
||||
ExportRegistryPlugin::default() // will save your registry schema json file to assets/registry.json
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
take a look at the [example](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_registry_export/basic/src/core/mod.rs) for more clarity
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
bevy_registry_export = "0.4"
|
||||
|
||||
```
|
||||
|
||||
Or use `cargo add`:
|
||||
|
||||
```toml
|
||||
cargo add bevy_registry_export
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_registry_export::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins
|
||||
ExportRegistryPlugin::default()
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
you can also configure the output path
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_registry_export::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins
|
||||
ExportRegistryPlugin {
|
||||
save_path: "assets/registry.json".into(),
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
- The output file will be generated in the ```Startup``` schedule whenever you run your app.
|
||||
- Every time you compile & run your app, the output json file will be updated.
|
||||
|
||||
## Examples
|
||||
|
||||
All examples are here:
|
||||
|
||||
> the examples use ```bevy_gltf_blueprints``` with the **legacy_mode** set to **FALSE** as the new custom properties generated by the Blender add-on require newer/ non legacy logic.
|
||||
|
||||
- https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_registry_export/basic
|
||||
|
||||
|
||||
## Compatible Bevy versions
|
||||
|
||||
The main branch is compatible with the latest Bevy release, while the branch `bevy_main` tries to track the `main` branch of Bevy (PRs updating the tracked commit are welcome).
|
||||
|
||||
Compatibility of `bevy_registry_export` versions:
|
||||
| `bevy_registry_export` | `bevy` | `bevy_components (Blender add-on)` |
|
||||
| :-- | :-- |:-- |
|
||||
| `0.4 ` | `0.14` | `0.3` |
|
||||
| `0.3 ` | `0.13` | `0.3` |
|
||||
| `0.2 ` | `0.12` | `0.3` |
|
||||
| `0.1 ` | `0.12` | `0.1 -0.2` |
|
||||
| branch `main` | `0.12` | `0.1` |
|
||||
| branch `bevy_main` | `main` | `n/a` |
|
||||
|
||||
|
||||
## Contributors
|
||||
|
||||
Thanks to all the contributors helping out with this project ! Big kudos to you, contributions are always appreciated ! :)
|
||||
A big shout out to [killercup](https://github.com/killercup), that did the bulk of the Bevy side code !
|
||||
|
||||
## License
|
||||
|
||||
This crate, all its code, contents & assets is Dual-licensed under either of
|
||||
|
||||
- Apache License, Version 2.0, ([LICENSE-APACHE](./LICENSE_APACHE.md) or https://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](./LICENSE_MIT.md) or https://opensource.org/licenses/MIT)
|
|
@ -1,315 +0,0 @@
|
|||
[![Crates.io](https://img.shields.io/crates/v/bevy_gltf_save_load)](https://crates.io/crates/bevy_gltf_save_load)
|
||||
[![Docs](https://img.shields.io/docsrs/bevy_gltf_save_load)](https://docs.rs/bevy_gltf_save_load/latest/bevy_gltf_save_load/)
|
||||
[![License](https://img.shields.io/crates/l/bevy_gltf_save_load)](https://github.com/kaosat-dev/Blenvy/blob/main/crates/bevy_gltf_save_load/License.md)
|
||||
[![Bevy tracking](https://img.shields.io/badge/Bevy%20tracking-released%20version-lightblue)](https://github.com/bevyengine/bevy/blob/main/docs/plugins_guidelines.md#main-branch-tracking)
|
||||
|
||||
# bevy_gltf_save_load (deprecated in favor of Blenvy)
|
||||
|
||||
> bevy_gltf_save_load has been deprecated in favor of its successor [Blenvy](https://crates.io/crates/blenvy), part of the [Blenvy project](https://github.com/kaosat-dev/Blenvy). No further development or maintenance will be done for Bevy bevy_gltf_save_load. See [#194](https://github.com/kaosat-dev/Blenvy/issues/194) for background.
|
||||
|
||||
Built upon [bevy_gltf_blueprints](https://crates.io/crates/bevy_gltf_blueprints) this crate adds the ability to easilly **save** and **load** your game worlds for [Bevy](https://bevyengine.org/) .
|
||||
|
||||
* leverages blueprints & seperation between
|
||||
* **dynamic** entities : entities that can change during the lifetime of your app/game
|
||||
* **static** entities : entities that do NOT change (typically, a part of your levels/ environements)
|
||||
* and allows allow for :
|
||||
* a simple save/load workflow thanks to the above
|
||||
* ability to specify **which entities** to save or to exclude
|
||||
* ability to specify **which components** to save or to exclude
|
||||
* ability to specify **which resources** to save or to exclude
|
||||
* small(er) save files (only a portion of the entities is saved)
|
||||
|
||||
Particularly useful when using [Blender](https://www.blender.org/) as an editor for the [Bevy](https://bevyengine.org/) game engine, combined with the [Blender plugin](https://github.com/kaosat-dev/Blenvy/tree/main/tools/gltf_auto_export) that does a lot of the work for you (including spliting generating seperate gltf files for your static vs dynamic assets)
|
||||
|
||||
|
||||
A bit of heads up:
|
||||
|
||||
* very opinionated !
|
||||
* still in the early stages & not 100% feature complete
|
||||
* fun fact: as the static level structure is stored seperatly, you can change your level layout & **still** reload an existing save file
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Here's a minimal usage example:
|
||||
|
||||
```toml
|
||||
# Cargo.toml
|
||||
[dependencies]
|
||||
bevy="0.14"
|
||||
bevy_gltf_save_load = "0.5"
|
||||
bevy_gltf_blueprints = "0.11" // also needed
|
||||
```
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_save_load::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins,
|
||||
SaveLoadPlugin::default()
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add a system to trigger saving
|
||||
pub fn request_save(
|
||||
mut save_requests: EventWriter<SavingRequest>,
|
||||
keycode: Res<Input<KeyCode>>,
|
||||
)
|
||||
{
|
||||
if keycode.just_pressed(KeyCode::S) {
|
||||
save_requests.send(SavingRequest {
|
||||
path: "save.scn.ron".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// add a system to trigger loading
|
||||
pub fn request_load(
|
||||
mut load_requests: EventWriter<LoadRequest>,
|
||||
keycode: Res<Input<KeyCode>>,
|
||||
)
|
||||
{
|
||||
if keycode.just_pressed(KeyCode::L) {
|
||||
save_requests.send(LoadRequest {
|
||||
path: "save.scn.ron".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// setting up your world
|
||||
// on initial setup, the static entities & the dynamic entities are kept seperate for clarity & loaded as blueprints from 2 seperate files
|
||||
pub fn setup_game(
|
||||
mut commands: Commands,
|
||||
mut next_game_state: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
info!("setting up game world");
|
||||
// here we actually spawn our game world/level
|
||||
let world_root = commands
|
||||
.spawn((
|
||||
Name::from("world"),
|
||||
GameWorldTag,
|
||||
InAppRunning,
|
||||
TransformBundle::default(),
|
||||
InheritedVisibility::default(),
|
||||
))
|
||||
.id();
|
||||
|
||||
// and we fill it with static entities
|
||||
let static_data = commands
|
||||
.spawn((
|
||||
Name::from("static"),
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("World".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
StaticEntitiesRoot,
|
||||
Library("models".into())
|
||||
))
|
||||
.id();
|
||||
|
||||
// and we fill it with dynamic entities
|
||||
let dynamic_data = commands
|
||||
.spawn((
|
||||
Name::from("dynamic"),
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("World_dynamic".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
DynamicEntitiesRoot,
|
||||
NoInBlueprint,
|
||||
Library("models".into())
|
||||
))
|
||||
.id();
|
||||
commands.entity(world_root).add_child(static_data);
|
||||
commands.entity(world_root).add_child(dynamic_data);
|
||||
|
||||
next_game_state.set(GameState::InGame)
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
take a look at the [example](https://github.com/kaosat-dev/Blenvy/blob/main/examples/bevy_gltf_save_load/basic/src/game/mod.rs) for more clarity
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Add the following to your `[dependencies]` section in `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
bevy_gltf_save_load = "0.3"
|
||||
bevy_gltf_blueprints = "0.10" // also needed, as bevy_gltf_save_load does not re-export it at this time
|
||||
```
|
||||
|
||||
Or use `cargo add`:
|
||||
|
||||
```toml
|
||||
cargo add bevy_gltf_save_load
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_save_load::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins
|
||||
SaveLoadPlugin::default()
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
you likely need to configure your settings (otherwise, not much will be saved)
|
||||
|
||||
```rust no_run
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_save_load::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins,
|
||||
SaveLoadPlugin {
|
||||
save_path: "scenes".into(), // where do we save files to (under assets for now) defaults to "scenes"
|
||||
component_filter: SceneFilter::Allowlist(HashSet::from([ // this is using Bevy's build in SceneFilter, you can compose what components you want to allow/deny
|
||||
TypeId::of::<Name>(),
|
||||
TypeId::of::<Transform>(),
|
||||
TypeId::of::<Velocity>(),
|
||||
// and any other commponent you want to include/exclude
|
||||
])),
|
||||
resource_filter: SceneFilter::deny_all(), // same logic as above, but for resources : also be careful & remember to register your resources !
|
||||
..Default::default()
|
||||
},
|
||||
// you need to configure the blueprints plugin as well (might be pre_configured in the future, but for now you need to do it manually)
|
||||
BlueprintsPlugin {
|
||||
library_folder: "models/library".into(),
|
||||
format: GltfFormat::GLB,
|
||||
aabbs: true,
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
||||
```
|
||||
### How to make sure your entites will be saved
|
||||
|
||||
- only entites that have a **Dynamic** component will be saved ! (the component is provided as part of the crate)
|
||||
- you can either add that component at runtime or have it baked-in in the Blueprint
|
||||
|
||||
### Component Filter:
|
||||
|
||||
- by default only the following components are going to be saved
|
||||
- **Parent**
|
||||
- **Children**
|
||||
- **BlueprintName** : part of bevy_gltf_blueprints, used under the hood
|
||||
- **SpawnHere** :part of bevy_gltf_blueprints, used under the hood
|
||||
- **Dynamic** : included in this crate, allows you to tag components as dynamic aka saveable ! Use this to make sure your entities are saved !
|
||||
|
||||
- you **CANNOT** remove these as they are part of the boilerplate
|
||||
- you **CAN** add however many other components you want, allow them all etc as you see fit
|
||||
- you can find more information about the SceneFilter object [here](https://bevyengine.org/news/bevy-0-11/#scene-filtering) and [here](https://docs.rs/bevy/latest/bevy/scene/enum.SceneFilter.html)
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
|
||||
- to trigger **saving** use the ```SavingRequest``` event
|
||||
```rust no_run
|
||||
// add a system to trigger saving
|
||||
pub fn request_save(
|
||||
mut save_requests: EventWriter<SavingRequest>,
|
||||
keycode: Res<Input<KeyCode>>,
|
||||
)
|
||||
{
|
||||
if keycode.just_pressed(KeyCode::S) {
|
||||
save_requests.send(SavingRequest {
|
||||
path: "save.scn.ron".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
- to trigger **loading** use the ```LoadRequest``` event
|
||||
|
||||
```rust no_run
|
||||
// add a system to trigger saving
|
||||
pub fn request_load(
|
||||
mut load_requests: EventWriter<LoadRequest>,
|
||||
keycode: Res<Input<KeyCode>>,
|
||||
)
|
||||
{
|
||||
if keycode.just_pressed(KeyCode::L) {
|
||||
save_requests.send(LoadRequest {
|
||||
path: "save.scn.ron".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- you also notified when saving / loading is done
|
||||
- ```SavingFinished``` for saving
|
||||
- ```LoadingFinished``` for loading
|
||||
|
||||
> Note: I **highly** recomend you change states when you start/finish saving & loading, otherwise things **will** get unpredictable
|
||||
Please see [the example](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_save_load/basic/src/game/mod.rs) for this.
|
||||
|
||||
## Additional notes
|
||||
|
||||
- the name + path of the **static** level blueprint/gltf file will be saved as part of the save file, and reused to dynamically
|
||||
load the correct static assets, which is necessary when you have multiple levels, and thus all required information to reload a save is contained within the save
|
||||
|
||||
## SystemSet
|
||||
|
||||
For convenience ```bevy_gltf_save_load``` provides two **SystemSets**
|
||||
- [```LoadingSet```](./src/lib.rs#19)
|
||||
- [```SavingSet```](./src/lib.rs#24)
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Highly advised to get a better understanding of how things work !
|
||||
To get started I recomend looking at
|
||||
|
||||
- [world setup](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_save_load/basic/src/game/in_game.rs)
|
||||
- [various events & co](https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_save_load/basic/src/game/mod.rs)
|
||||
|
||||
|
||||
All examples are here:
|
||||
|
||||
- https://github.com/kaosat-dev/Blenvy/tree/main/examples/bevy_gltf_save_load/basic
|
||||
|
||||
|
||||
## Compatible Bevy versions
|
||||
|
||||
The main branch is compatible with the latest Bevy release, while the branch `bevy_main` tries to track the `main` branch of Bevy (PRs updating the tracked commit are welcome).
|
||||
|
||||
Compatibility of `bevy_gltf_save_load` versions:
|
||||
| `bevy_gltf_save_load` | `bevy` |
|
||||
| :-- | :-- |
|
||||
| `0.5 ` | `0.14` |
|
||||
| `0.4 ` | `0.13` |
|
||||
| `0.1 -0.3` | `0.12` |
|
||||
| branch `main` | `0.12` |
|
||||
| branch `bevy_main` | `main` |
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This crate, all its code, contents & assets is Dual-licensed under either of
|
||||
|
||||
- Apache License, Version 2.0, ([LICENSE-APACHE](./LICENSE_APACHE.md) or https://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](./LICENSE_MIT.md) or https://opensource.org/licenses/MIT)
|
|
@ -164,6 +164,7 @@ pub fn trigger_blueprint_animation_markers_events(
|
|||
}
|
||||
|
||||
/// triggers events when a given animation marker is reached for INSTANCE animations
|
||||
// TODO: implement this correctly
|
||||
pub fn trigger_instance_animation_markers_events(
|
||||
animation_infos: Query<(
|
||||
Entity,
|
||||
|
@ -174,22 +175,23 @@ pub fn trigger_instance_animation_markers_events(
|
|||
)>,
|
||||
animation_players: Query<&AnimationPlayer>,
|
||||
animation_clips: Res<Assets<AnimationClip>>,
|
||||
animation_graphs: Res<Assets<AnimationGraph>>,
|
||||
mut animation_marker_events: EventWriter<AnimationMarkerReached>,
|
||||
__animation_graphs: Res<Assets<AnimationGraph>>,
|
||||
mut _animation_marker_events: EventWriter<AnimationMarkerReached>,
|
||||
) {
|
||||
for (entity, markers, player_link, animations, animation_infos) in animation_infos.iter() {
|
||||
for (__entity, __markers, player_link, animations, __animation_infos) in animation_infos.iter()
|
||||
{
|
||||
//let (animation_player, animation_transitions) = animation_players.get(player_link.0).unwrap();
|
||||
//let foo = animation_transitions.get_main_animation().unwrap();
|
||||
|
||||
for (animation_name, node_index) in animations.named_indices.iter() {
|
||||
let animation_player = animation_players.get(player_link.0).unwrap();
|
||||
if animation_player.animation_is_playing(*node_index) {
|
||||
if let Some(animation) = animation_player.animation(*node_index) {
|
||||
if let Some(__animation) = animation_player.animation(*node_index) {
|
||||
if let Some(animation_clip_handle) =
|
||||
animations.named_animations.get(animation_name)
|
||||
{
|
||||
if let Some(animation_clip) = animation_clips.get(animation_clip_handle) {
|
||||
println!("helooo")
|
||||
if let Some(__animation_clip) = animation_clips.get(animation_clip_handle) {
|
||||
println!("found the animation clip");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,41 +59,30 @@ pub struct AssetLoadTracker {
|
|||
}
|
||||
|
||||
/// helper component, for tracking loaded assets
|
||||
#[derive(Component, Debug)]
|
||||
#[derive(Component, Default, Debug)]
|
||||
pub(crate) struct BlueprintAssetsLoadState {
|
||||
pub all_loaded: bool,
|
||||
pub asset_infos: Vec<AssetLoadTracker>,
|
||||
pub progress: f32,
|
||||
}
|
||||
impl Default for BlueprintAssetsLoadState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
all_loaded: Default::default(),
|
||||
asset_infos: Default::default(),
|
||||
progress: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for preloading asset files
|
||||
#[derive(serde::Deserialize, bevy::asset::Asset, bevy::reflect::TypePath, Debug)]
|
||||
pub(crate) struct File{
|
||||
pub(crate) struct File {
|
||||
pub(crate) path: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, bevy::asset::Asset, bevy::reflect::TypePath, Debug)]
|
||||
pub(crate) struct BlueprintPreloadAssets{
|
||||
pub(crate) assets: Vec<(String, File)>
|
||||
pub(crate) struct BlueprintPreloadAssets {
|
||||
pub(crate) assets: Vec<(String, File)>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintMetaHandle(pub Handle<BlueprintPreloadAssets>);
|
||||
|
||||
/// flag component, usually added when a blueprint is loaded
|
||||
/// flag component, usually added when a blueprint meta file is loaded
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintMetaLoaded;
|
||||
|
||||
|
||||
#[derive(Component)]
|
||||
pub(crate) struct BlueprintMetaLoading;
|
|
@ -14,11 +14,12 @@ pub(crate) struct AssetToBlueprintInstancesMapper {
|
|||
pub(crate) untyped_id_to_blueprint_entity_ids: HashMap<String, Vec<Entity>>,
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn react_to_asset_changes(
|
||||
mut gltf_events: EventReader<AssetEvent<Gltf>>, // FIXME: Problem: we need to react to any asset change, not just gltf files !
|
||||
// mut untyped_events: EventReader<AssetEvent<LoadedUntypedAsset>>,
|
||||
blueprint_assets: Query<(Entity, Option<&Name>, &BlueprintInfo, Option<&Children>)>,
|
||||
blueprint_children_entities: Query<&FromBlueprint>, //=> can only be used if the entites are tagged
|
||||
_blueprint_children_entities: Query<&FromBlueprint>, //=> can only be used if the entites are tagged
|
||||
assets_to_blueprint_instances: Res<AssetToBlueprintInstancesMapper>,
|
||||
all_parents: Query<&Parent>,
|
||||
spawning_blueprints: Query<&BlueprintSpawning>,
|
||||
|
@ -30,34 +31,32 @@ pub(crate) fn react_to_asset_changes(
|
|||
|
||||
for event in gltf_events.read() {
|
||||
// LoadedUntypedAsset
|
||||
match event {
|
||||
AssetEvent::Modified { id } => {
|
||||
// React to the gltf file being modified
|
||||
// println!("Modified gltf {:?}", asset_server.get_path(*id));
|
||||
if let Some(asset_path) = asset_server.get_path(*id) {
|
||||
// let untyped = asset_server.get_handle_untyped(asset_path.clone());
|
||||
// println!("matching untyped handle {:?}", untyped);
|
||||
// let bla = untyped.unwrap().id();
|
||||
// asset_server.get
|
||||
// in order to avoid respawn both a parent & a child , which would crash Bevy, we do things in two steps
|
||||
if let Some(entities) = assets_to_blueprint_instances
|
||||
.untyped_id_to_blueprint_entity_ids
|
||||
.get(&asset_path.to_string())
|
||||
{
|
||||
for entity in entities.iter() {
|
||||
// println!("matching blueprint instance {}", entity);
|
||||
// disregard entities that are already (re) spawning
|
||||
if !respawn_candidates.contains(&entity)
|
||||
&& blueprint_assets.get(*entity).is_ok()
|
||||
&& spawning_blueprints.get(*entity).is_err()
|
||||
{
|
||||
respawn_candidates.push(entity);
|
||||
}
|
||||
|
||||
if let AssetEvent::Modified { id } = event {
|
||||
// React to the gltf file being modified
|
||||
// println!("Modified gltf {:?}", asset_server.get_path(*id));
|
||||
if let Some(asset_path) = asset_server.get_path(*id) {
|
||||
// let untyped = asset_server.get_handle_untyped(asset_path.clone());
|
||||
// println!("matching untyped handle {:?}", untyped);
|
||||
// let bla = untyped.unwrap().id();
|
||||
// asset_server.get
|
||||
// in order to avoid respawn both a parent & a child , which would crash Bevy, we do things in two steps
|
||||
if let Some(entities) = assets_to_blueprint_instances
|
||||
.untyped_id_to_blueprint_entity_ids
|
||||
.get(&asset_path.to_string())
|
||||
{
|
||||
for entity in entities.iter() {
|
||||
// println!("matching blueprint instance {}", entity);
|
||||
// disregard entities that are already (re) spawning
|
||||
if !respawn_candidates.contains(&entity)
|
||||
&& blueprint_assets.get(*entity).is_ok()
|
||||
&& spawning_blueprints.get(*entity).is_err()
|
||||
{
|
||||
respawn_candidates.push(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// we process all candidates here to deal with the case where multiple assets have changed in a single frame, which could cause respawn chaos
|
||||
|
|
|
@ -11,13 +11,13 @@ pub struct MaterialInfo {
|
|||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// component containing the full list of MaterialInfos for a given entity/object
|
||||
/// component containing the full list of `MaterialInfos` for a given entity/object
|
||||
pub struct MaterialInfos(Vec<MaterialInfo>);
|
||||
|
||||
#[derive(Component, Default, Debug)]
|
||||
pub struct MaterialProcessed;
|
||||
|
||||
/// system that injects / replaces materials from material library
|
||||
/// system that injects / replaces materials from materials library
|
||||
pub(crate) fn inject_materials(
|
||||
mut blenvy_config: ResMut<BlenvyConfig>,
|
||||
material_infos_query: Query<
|
||||
|
@ -58,9 +58,11 @@ pub(crate) fn inject_materials(
|
|||
} else {
|
||||
let model_handle: Handle<Gltf> = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now
|
||||
let Some(mat_gltf) = assets_gltf.get(model_handle.id()) else {
|
||||
warn!("materials file {} should have been preloaded skipping",material_info.path);
|
||||
warn!(
|
||||
"materials file {} should have been preloaded skipping",
|
||||
material_info.path
|
||||
);
|
||||
continue;
|
||||
|
||||
};
|
||||
/*let mat_gltf = assets_gltf.get(model_handle.id()).unwrap_or_else(|| {
|
||||
panic!(
|
||||
|
@ -86,25 +88,19 @@ pub(crate) fn inject_materials(
|
|||
if let Some(material) = material_found {
|
||||
info!("Step 6: injecting/replacing materials");
|
||||
for (child_index, child) in children.iter().enumerate() {
|
||||
if child_index == material_index {
|
||||
if with_materials_and_meshes.contains(*child) {
|
||||
info!(
|
||||
"injecting material {}, path: {:?}",
|
||||
material_info.name,
|
||||
material_info.path.clone()
|
||||
);
|
||||
if child_index == material_index && with_materials_and_meshes.contains(*child) {
|
||||
info!(
|
||||
"injecting material {}, path: {:?}",
|
||||
material_info.name,
|
||||
material_info.path.clone()
|
||||
);
|
||||
|
||||
commands.entity(*child).insert(material.clone());
|
||||
}
|
||||
commands.entity(*child).insert(material.clone());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
commands.entity(entity).insert(MaterialProcessed);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ pub(crate) use hot_reload::*;
|
|||
|
||||
use bevy::{prelude::*, utils::hashbrown::HashMap};
|
||||
|
||||
use crate::{BlenvyConfig, GltfComponentsSet};
|
||||
use crate::GltfComponentsSet;
|
||||
|
||||
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
||||
/// set for the two stages of blueprint based spawning :
|
||||
|
@ -48,16 +48,10 @@ impl Default for BluePrintBundle {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
/// Plugin for gltf blueprints
|
||||
pub struct BlueprintsPlugin {}
|
||||
|
||||
impl Default for BlueprintsPlugin {
|
||||
fn default() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
fn hot_reload(watching_for_changes: Res<WatchingForChanges>) -> bool {
|
||||
// println!("hot reload ? {}", watching_for_changes.0);
|
||||
watching_for_changes.0
|
||||
|
@ -93,7 +87,6 @@ impl Plugin for BlueprintsPlugin {
|
|||
.register_type::<BlueprintInfo>()
|
||||
.register_type::<MaterialInfo>()
|
||||
.register_type::<MaterialInfos>()
|
||||
|
||||
.register_type::<SpawnBlueprint>()
|
||||
.register_type::<BlueprintInstanceDisabled>()
|
||||
.register_type::<HideUntilReady>()
|
||||
|
@ -111,10 +104,7 @@ impl Plugin for BlueprintsPlugin {
|
|||
.register_type::<Vec<String>>()
|
||||
.register_type::<BlueprintAssets>()
|
||||
.register_type::<HashMap<String, Vec<String>>>()
|
||||
//.init_asset::<RawGltfAsset>()
|
||||
//.init_asset_loader::<RawGltfAssetLoader>()
|
||||
.add_plugins(RonAssetPlugin::<BlueprintPreloadAssets>::new(&["meta.ron"]),)
|
||||
|
||||
.add_plugins(RonAssetPlugin::<BlueprintPreloadAssets>::new(&["meta.ron"]))
|
||||
.configure_sets(
|
||||
Update,
|
||||
(GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
use std::path::Path;
|
||||
|
||||
use bevy::{
|
||||
gltf::Gltf,
|
||||
prelude::*,
|
||||
scene::SceneInstance,
|
||||
utils::{hashbrown::HashMap, warn},
|
||||
};
|
||||
use bevy::{gltf::Gltf, prelude::*, scene::SceneInstance, utils::hashbrown::HashMap};
|
||||
|
||||
use crate::{
|
||||
AnimationInfos, AssetLoadTracker, AssetToBlueprintInstancesMapper, BlueprintAnimationInfosLink, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintAssets, BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintMetaLoading, BlueprintAssetsNotLoaded, BlueprintPreloadAssets, InstanceAnimationInfosLink, InstanceAnimationPlayerLink, InstanceAnimations, WatchingForChanges
|
||||
AnimationInfos, AssetLoadTracker, AssetToBlueprintInstancesMapper, BlueprintAnimationInfosLink,
|
||||
BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintAssetsLoadState,
|
||||
BlueprintAssetsLoaded, BlueprintAssetsNotLoaded, BlueprintMetaLoaded, BlueprintMetaLoading,
|
||||
BlueprintPreloadAssets, InstanceAnimationInfosLink, InstanceAnimationPlayerLink,
|
||||
InstanceAnimations, WatchingForChanges,
|
||||
};
|
||||
|
||||
|
||||
/// this is a flag component for our levels/game world
|
||||
#[derive(Component)]
|
||||
pub struct GameWorldTag;
|
||||
|
@ -46,12 +44,6 @@ pub struct SpawnBlueprint;
|
|||
/// flag component marking any spawned child of blueprints
|
||||
pub struct FromBlueprint;
|
||||
|
||||
// TODO: move to save_load
|
||||
#[derive(Component, Reflect, Debug, Default)]
|
||||
#[reflect(Component)]
|
||||
/// component used to mark any entity as Dynamic: aka add this to make sure your entity is going to be saved
|
||||
pub struct DynamicBlueprintInstance;
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// flag component to force adding newly spawned entity as child of game world
|
||||
|
@ -73,8 +65,6 @@ pub struct HideUntilReady;
|
|||
/// Companion to the `HideUntilReady` component: this stores the visibility of the entity before the blueprint was inserted into it
|
||||
pub(crate) struct OriginalVisibility(Visibility);
|
||||
|
||||
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// marker component, gets added to all children of a currently spawning blueprint instance, can be usefull to avoid manipulating still in progress entities
|
||||
|
@ -123,25 +113,45 @@ Overview of the Blueprint Spawning process
|
|||
*/
|
||||
|
||||
pub(super) fn blueprints_prepare_metadata_file_for_spawn(
|
||||
blueprint_instances_to_spawn: Query<(
|
||||
Entity,
|
||||
&BlueprintInfo,
|
||||
Option<&Name>,
|
||||
Option<&Parent>,
|
||||
Option<&HideUntilReady>,
|
||||
Option<&Visibility>,
|
||||
Option<&AddToGameWorld>,
|
||||
|
||||
), (Without<BlueprintMetaLoading>, Without<BlueprintSpawning>, Without<BlueprintInstanceReady>)>,
|
||||
blueprint_instances_to_spawn: Query<
|
||||
(
|
||||
Entity,
|
||||
&BlueprintInfo,
|
||||
Option<&Name>,
|
||||
Option<&Parent>,
|
||||
Option<&HideUntilReady>,
|
||||
Option<&Visibility>,
|
||||
Option<&AddToGameWorld>,
|
||||
),
|
||||
(
|
||||
Without<BlueprintMetaLoading>,
|
||||
Without<BlueprintSpawning>,
|
||||
Without<BlueprintInstanceReady>,
|
||||
),
|
||||
>,
|
||||
mut game_world: Query<Entity, With<GameWorldTag>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, blueprint_info, entity_name, original_parent, hide_until_ready, original_visibility, add_to_world) in blueprint_instances_to_spawn.iter() {
|
||||
for (
|
||||
entity,
|
||||
blueprint_info,
|
||||
entity_name,
|
||||
original_parent,
|
||||
hide_until_ready,
|
||||
original_visibility,
|
||||
add_to_world,
|
||||
) in blueprint_instances_to_spawn.iter()
|
||||
{
|
||||
// get path to assets / metadata file
|
||||
info!("Step 1: spawn request detected: loading metadata file for {:?}", blueprint_info);
|
||||
info!(
|
||||
"Step 1: spawn request detected: loading metadata file for {:?}",
|
||||
blueprint_info
|
||||
);
|
||||
let blueprint_path = blueprint_info.path.clone();
|
||||
let metadata_path = blueprint_path.replace(".glb", ".meta.ron").replace(".gltf", ".meta.ron"); // FIXME: horrible
|
||||
let metadata_path = blueprint_path
|
||||
.replace(".glb", ".meta.ron")
|
||||
.replace(".gltf", ".meta.ron"); // FIXME: horrible
|
||||
let mut asset_infos: Vec<AssetLoadTracker> = vec![];
|
||||
//let foo_handle:Handle<BlueprintPreloadAssets> = asset_server.load(metadata_path);
|
||||
let untyped_handle = asset_server.load_untyped(metadata_path.clone());
|
||||
|
@ -163,11 +173,11 @@ pub(super) fn blueprints_prepare_metadata_file_for_spawn(
|
|||
..Default::default()
|
||||
},
|
||||
BlueprintMetaLoading,
|
||||
BlueprintSpawning
|
||||
BlueprintSpawning,
|
||||
));
|
||||
|
||||
// if the entity has no name, add one based on the blueprint's
|
||||
if entity_name.is_none(){
|
||||
if entity_name.is_none() {
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(bevy::prelude::Name::from(blueprint_info.name.clone()));
|
||||
|
@ -176,14 +186,14 @@ pub(super) fn blueprints_prepare_metadata_file_for_spawn(
|
|||
if original_parent.is_none() {
|
||||
// only allow hiding until ready when the entity does not have a parent (?)
|
||||
if hide_until_ready.is_some() {
|
||||
|
||||
// if there is already a set visibility, save it for later
|
||||
if let Some(original_visibility) = original_visibility {
|
||||
commands.entity(entity).insert(OriginalVisibility(*original_visibility));
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(OriginalVisibility(*original_visibility));
|
||||
}
|
||||
// & now hide the instance until it is ready
|
||||
commands.entity(entity)
|
||||
.insert(Visibility::Hidden);
|
||||
commands.entity(entity).insert(Visibility::Hidden);
|
||||
}
|
||||
|
||||
// only allow automatically adding a newly spawned blueprint instance to the "world", if the entity does not have a parent
|
||||
|
@ -206,9 +216,7 @@ pub(crate) fn blueprints_check_assets_metadata_files_loading(
|
|||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
|
||||
for (entity, blueprint_info, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||
|
||||
for (entity, _blueprint_info, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||
let mut all_loaded = true;
|
||||
let mut loaded_amount = 0;
|
||||
let total = assets_to_load.asset_infos.len();
|
||||
|
@ -218,7 +226,7 @@ pub(crate) fn blueprints_check_assets_metadata_files_loading(
|
|||
|
||||
let mut failed = false;
|
||||
if let bevy::asset::LoadState::Failed(_) = asset_server.load_state(asset_id) {
|
||||
failed = true
|
||||
failed = true;
|
||||
}
|
||||
tracker.loaded = loaded || failed;
|
||||
if loaded || failed {
|
||||
|
@ -227,10 +235,12 @@ pub(crate) fn blueprints_check_assets_metadata_files_loading(
|
|||
all_loaded = false;
|
||||
}
|
||||
if all_loaded {
|
||||
commands.entity(entity).insert(BlueprintMetaHandle(asset_server.load(tracker.path.clone()))).remove::<BlueprintAssetsLoadState>();
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BlueprintMetaHandle(asset_server.load(tracker.path.clone())))
|
||||
.remove::<BlueprintAssetsLoadState>();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
let progress: f32 = loaded_amount as f32 / total as f32;
|
||||
assets_to_load.progress = progress;
|
||||
|
@ -238,9 +248,11 @@ pub(crate) fn blueprints_check_assets_metadata_files_loading(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub(super) fn blueprints_prepare_spawn(
|
||||
blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo, &BlueprintMetaHandle, Option<&Name>), Added<BlueprintMetaHandle>>,
|
||||
blueprint_instances_to_spawn: Query<
|
||||
(Entity, &BlueprintInfo, &BlueprintMetaHandle),
|
||||
Added<BlueprintMetaHandle>,
|
||||
>,
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
// for hot reload
|
||||
|
@ -249,9 +261,8 @@ pub(super) fn blueprints_prepare_spawn(
|
|||
// for debug
|
||||
// all_names: Query<&Name>
|
||||
blueprint_metas: Res<Assets<BlueprintPreloadAssets>>,
|
||||
|
||||
) {
|
||||
for (entity, blueprint_info, blueprint_meta_handle, entity_name) in blueprint_instances_to_spawn.iter() {
|
||||
for (entity, blueprint_info, blueprint_meta_handle) in blueprint_instances_to_spawn.iter() {
|
||||
info!(
|
||||
"Step 2: metadata loaded: loading assets for {:?}",
|
||||
blueprint_info,
|
||||
|
@ -276,55 +287,54 @@ pub(super) fn blueprints_prepare_spawn(
|
|||
// and we also add all its assets
|
||||
/* prefetch attempt */
|
||||
if let Some(blenvy_metadata) = blueprint_metas.get(&blueprint_meta_handle.0) {
|
||||
for asset in blenvy_metadata.assets.iter() {
|
||||
let asset_path = asset.1.path.clone();
|
||||
let asset_name = asset.0.clone();
|
||||
for asset in blenvy_metadata.assets.iter() {
|
||||
let asset_path = asset.1.path.clone();
|
||||
let asset_name = asset.0.clone();
|
||||
|
||||
let untyped_handle = asset_server.load_untyped(&asset_path);
|
||||
let asset_id = untyped_handle.id();
|
||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||
if !loaded {
|
||||
asset_infos.push(AssetLoadTracker {
|
||||
name: asset_name.clone(),
|
||||
path: asset_path.clone(),
|
||||
id: asset_id,
|
||||
loaded: false,
|
||||
handle: untyped_handle.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
// FIXME: dang, too early, asset server has not yet started loading yet
|
||||
// let path_id = asset_server.get_path_id(&asset.path).expect("we should have alread checked for this asset");
|
||||
let path_id = asset_path.clone();
|
||||
|
||||
// Only do this if hot reload is enabled
|
||||
if watching_for_changes.0 {
|
||||
if !assets_to_blueprint_instances
|
||||
.untyped_id_to_blueprint_entity_ids
|
||||
.contains_key(&path_id)
|
||||
{
|
||||
assets_to_blueprint_instances
|
||||
.untyped_id_to_blueprint_entity_ids
|
||||
.insert(path_id.clone(), vec![]);
|
||||
let untyped_handle = asset_server.load_untyped(&asset_path);
|
||||
let asset_id = untyped_handle.id();
|
||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||
if !loaded {
|
||||
asset_infos.push(AssetLoadTracker {
|
||||
name: asset_name.clone(),
|
||||
path: asset_path.clone(),
|
||||
id: asset_id,
|
||||
loaded: false,
|
||||
handle: untyped_handle.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
// only insert if not already present in mapping
|
||||
if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids
|
||||
[&path_id]
|
||||
.contains(&entity)
|
||||
{
|
||||
// println!("adding mapping between {} and entity {:?}", path_id, all_names.get(entity));
|
||||
assets_to_blueprint_instances
|
||||
// FIXME: dang, too early, asset server has not yet started loading yet
|
||||
// let path_id = asset_server.get_path_id(&asset.path).expect("we should have alread checked for this asset");
|
||||
let path_id = asset_path.clone();
|
||||
|
||||
// Only do this if hot reload is enabled
|
||||
if watching_for_changes.0 {
|
||||
if !assets_to_blueprint_instances
|
||||
.untyped_id_to_blueprint_entity_ids
|
||||
.get_mut(&path_id)
|
||||
.unwrap()
|
||||
.push(entity);
|
||||
.contains_key(&path_id)
|
||||
{
|
||||
assets_to_blueprint_instances
|
||||
.untyped_id_to_blueprint_entity_ids
|
||||
.insert(path_id.clone(), vec![]);
|
||||
}
|
||||
|
||||
// only insert if not already present in mapping
|
||||
if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids[&path_id]
|
||||
.contains(&entity)
|
||||
{
|
||||
// println!("adding mapping between {} and entity {:?}", path_id, all_names.get(entity));
|
||||
assets_to_blueprint_instances
|
||||
.untyped_id_to_blueprint_entity_ids
|
||||
.get_mut(&path_id)
|
||||
.unwrap()
|
||||
.push(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("no asset metadata found for {}, please make sure to generate them using the Blender add-on, or preload your assets manually", blueprint_info.path);
|
||||
}
|
||||
}else {
|
||||
warn!("no asset metadata found for {}, please make sure to generate them using the Blender add-on, or preload your assets manually", blueprint_info.path);
|
||||
}
|
||||
|
||||
// Only do this if hot reload is enabled
|
||||
// TODO: should this be added to the list of "all assets" on the blender side instead
|
||||
|
@ -367,7 +377,9 @@ pub(super) fn blueprints_prepare_spawn(
|
|||
commands.entity(entity).insert(BlueprintAssetsLoaded);
|
||||
}
|
||||
|
||||
commands.entity(entity)
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(BlueprintMetaLoaded)
|
||||
.remove::<BlueprintMetaLoading>()
|
||||
.remove::<BlueprintMetaHandle>();
|
||||
}
|
||||
|
@ -376,14 +388,14 @@ pub(super) fn blueprints_prepare_spawn(
|
|||
/// This system tracks & updates the loading state of all blueprints assets
|
||||
pub(crate) fn blueprints_check_assets_loading(
|
||||
mut blueprint_assets_to_load: Query<
|
||||
(Entity, &BlueprintInfo, &mut BlueprintAssetsLoadState, Option<&Name>),
|
||||
(Entity, &BlueprintInfo, &mut BlueprintAssetsLoadState),
|
||||
With<BlueprintAssetsNotLoaded>,
|
||||
>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut commands: Commands,
|
||||
mut blueprint_events: EventWriter<BlueprintEvent>,
|
||||
) {
|
||||
for (entity, blueprint_info, mut assets_to_load, entity_name) in blueprint_assets_to_load.iter_mut() {
|
||||
for (entity, blueprint_info, mut assets_to_load) in blueprint_assets_to_load.iter_mut() {
|
||||
let mut all_loaded = true;
|
||||
let mut loaded_amount = 0;
|
||||
let total = assets_to_load.asset_infos.len();
|
||||
|
@ -396,7 +408,7 @@ pub(crate) fn blueprints_check_assets_loading(
|
|||
let mut failed = false;
|
||||
if let bevy::asset::LoadState::Failed(_) = asset_server.load_state(asset_id) {
|
||||
warn!("FAILED TO LOAD {}", tracker.path.clone());
|
||||
failed = true
|
||||
failed = true;
|
||||
}
|
||||
tracker.loaded = loaded || failed;
|
||||
if loaded || failed {
|
||||
|
@ -428,13 +440,7 @@ pub(crate) fn blueprints_check_assets_loading(
|
|||
|
||||
pub(crate) fn blueprints_assets_loaded(
|
||||
spawn_placeholders: Query<
|
||||
(
|
||||
Entity,
|
||||
&BlueprintInfo,
|
||||
Option<&Transform>,
|
||||
Option<&Name>,
|
||||
Option<&AnimationInfos>,
|
||||
),
|
||||
(Entity, &BlueprintInfo, Option<&Transform>, Option<&Name>),
|
||||
(
|
||||
Added<BlueprintAssetsLoaded>,
|
||||
Without<BlueprintAssetsNotLoaded>,
|
||||
|
@ -448,14 +454,7 @@ pub(crate) fn blueprints_assets_loaded(
|
|||
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (
|
||||
entity,
|
||||
blueprint_info,
|
||||
transform,
|
||||
name,
|
||||
animation_infos,
|
||||
) in spawn_placeholders.iter()
|
||||
{
|
||||
for (entity, blueprint_info, transform, name) in spawn_placeholders.iter() {
|
||||
/*info!(
|
||||
"BLUEPRINT: all assets loaded, attempting to spawn blueprint SCENE {:?} for entity {:?}, id: {:}, parent:{:?}",
|
||||
blueprint_info.name, name, entity, original_parent
|
||||
|
@ -529,8 +528,6 @@ pub(crate) fn blueprints_assets_loaded(
|
|||
graph,
|
||||
},
|
||||
));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -652,7 +649,7 @@ pub(crate) fn blueprints_scenes_spawned(
|
|||
use crate::CopyComponents;
|
||||
use std::any::TypeId;
|
||||
|
||||
use super::{BlueprintMetaHandle, BlueprintMetaLoaded};
|
||||
use super::BlueprintMetaHandle;
|
||||
|
||||
#[derive(Component, Reflect, Debug)]
|
||||
#[reflect(Component)]
|
||||
|
@ -663,6 +660,7 @@ pub struct BlueprintReadyForPostProcess;
|
|||
/// - it copies the blueprint's root components to the entity it was spawned on (original entity)
|
||||
/// - it copies the children of the blueprint scene into the original entity
|
||||
/// - it adds an `AnimationLink` component containing the entity that has the `AnimationPlayer` so that animations can be controlled from the original entity
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn blueprints_cleanup_spawned_scene(
|
||||
blueprint_scenes: Query<
|
||||
(
|
||||
|
@ -840,6 +838,7 @@ pub(crate) fn blueprints_finalize_instances(
|
|||
info!("Step 8: Finalizing blueprint instance {:?}", name);
|
||||
commands
|
||||
.entity(entity)
|
||||
.remove::<BlueprintMetaLoaded>()
|
||||
.remove::<BlueprintReadyForFinalizing>()
|
||||
.remove::<BlueprintReadyForPostProcess>()
|
||||
.remove::<BlueprintSpawning>()
|
||||
|
@ -881,8 +880,9 @@ pub(crate) fn blueprints_finalize_instances(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
commands.entity(entity).remove::<BlueprintInstanceDisabled>();
|
||||
commands
|
||||
.entity(entity)
|
||||
.remove::<BlueprintInstanceDisabled>();
|
||||
for child in all_children.iter_descendants(entity) {
|
||||
commands.entity(child).remove::<BlueprintInstanceDisabled>();
|
||||
}
|
||||
|
@ -890,7 +890,7 @@ pub(crate) fn blueprints_finalize_instances(
|
|||
if hide_until_ready.is_some() {
|
||||
if let Some(original_visibility) = original_visibility {
|
||||
commands.entity(entity).insert(original_visibility.0);
|
||||
}else {
|
||||
} else {
|
||||
commands.entity(entity).insert(Visibility::Inherited);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,8 +173,6 @@ fn process_colorgrading(
|
|||
gamma: blender_colorgrading.gamma,
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
..Default::default()
|
||||
});
|
||||
commands.entity(scene_id).remove::<ColorGrading>();
|
||||
}
|
||||
|
|
|
@ -70,13 +70,13 @@ fn components_string_to_components(
|
|||
.expect("deserialzer should have been generated from string");
|
||||
let reflect_deserializer = ReflectDeserializer::new(type_registry);
|
||||
/*let component = reflect_deserializer
|
||||
.deserialize(&mut deserializer)
|
||||
.unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"failed to deserialize component {} with value: {:?}",
|
||||
name, value
|
||||
)
|
||||
});*/
|
||||
.deserialize(&mut deserializer)
|
||||
.unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"failed to deserialize component {} with value: {:?}",
|
||||
name, value
|
||||
)
|
||||
});*/
|
||||
let Ok(component) = reflect_deserializer.deserialize(&mut deserializer) else {
|
||||
warn!(
|
||||
"failed to deserialize component {} with value: {:?}",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bevy::{prelude::*, render::primitives::Aabb, utils::HashMap};
|
||||
use bevy::{render::primitives::Aabb, utils::HashMap};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub mod components;
|
||||
|
@ -29,8 +29,8 @@ pub struct BlenvyConfig {
|
|||
// save & load
|
||||
pub(crate) save_component_filter: SceneFilter,
|
||||
pub(crate) save_resource_filter: SceneFilter,
|
||||
//pub(crate) save_path: PathBuf,
|
||||
// save_path: PathBuf::from("saves"),
|
||||
#[allow(dead_code)]
|
||||
pub(crate) save_path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -45,6 +45,7 @@ pub struct BlenvyPlugin {
|
|||
// for save & load
|
||||
pub save_component_filter: SceneFilter,
|
||||
pub save_resource_filter: SceneFilter,
|
||||
pub save_path: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for BlenvyPlugin {
|
||||
|
@ -57,6 +58,7 @@ impl Default for BlenvyPlugin {
|
|||
|
||||
save_component_filter: SceneFilter::default(),
|
||||
save_resource_filter: SceneFilter::default(),
|
||||
save_path: PathBuf::from("blenvy_saves"), // TODO: use https://docs.rs/dirs/latest/dirs/ to default to the correct user directory
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +71,7 @@ impl Plugin for BlenvyPlugin {
|
|||
ExportRegistryPlugin::default(),
|
||||
BlueprintsPlugin::default(),
|
||||
#[cfg(not(target_arch = "wasm32"))] // save & load is only for non wasm platforms
|
||||
SaveLoadPlugin::default()
|
||||
SaveLoadPlugin::default(),
|
||||
))
|
||||
.insert_resource(BlenvyConfig {
|
||||
export_registry: self.export_registry,
|
||||
|
@ -83,6 +85,7 @@ impl Plugin for BlenvyPlugin {
|
|||
|
||||
save_component_filter: self.save_component_filter.clone(),
|
||||
save_resource_filter: self.save_resource_filter.clone(),
|
||||
save_path: self.save_path.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,8 +229,7 @@ fn add_min_max(
|
|||
field_index: usize,
|
||||
variant_index: Option<usize>,
|
||||
) -> Value {
|
||||
#[cfg(feature = "support-inspector")]
|
||||
fn get_min_max(
|
||||
/*fn get_min_max(
|
||||
reg: &TypeRegistration,
|
||||
field_index: usize,
|
||||
variant_index: Option<usize>,
|
||||
|
@ -252,9 +251,8 @@ fn add_min_max(
|
|||
})
|
||||
.and_then(|o| o.downcast_ref::<NumberOptions<f32>>())
|
||||
.map(|num| (num.min, num.max))
|
||||
}
|
||||
}*/
|
||||
|
||||
#[cfg(not(feature = "support-inspector"))]
|
||||
fn get_min_max(
|
||||
_reg: &TypeRegistration,
|
||||
_field_index: usize,
|
||||
|
|
|
@ -35,7 +35,8 @@ fn export_registry(blenvy_config: Res<BlenvyConfig>) -> bool {
|
|||
|
||||
impl Plugin for ExportRegistryPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_asset_root().add_systems(Startup, export_types.run_if(export_registry));
|
||||
app.register_asset_root()
|
||||
.add_systems(Startup, export_types.run_if(export_registry));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,36 +2,47 @@ pub use bevy::prelude::*;
|
|||
|
||||
use crate::{BlueprintInfo, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
||||
|
||||
use super::{BlueprintWorld, Dynamic};
|
||||
use super::BlueprintWorld;
|
||||
|
||||
pub(crate) fn spawn_from_blueprintworld(
|
||||
added_blueprint_worlds: Query<(Entity, &BlueprintWorld), Added<BlueprintWorld> >,
|
||||
added_blueprint_worlds: Query<(Entity, &BlueprintWorld), Added<BlueprintWorld>>,
|
||||
mut commands: Commands,
|
||||
){
|
||||
for (entity, blueprint_world) in added_blueprint_worlds.iter(){
|
||||
) {
|
||||
for (__entity, blueprint_world) in added_blueprint_worlds.iter() {
|
||||
println!("added blueprintWorld {:?}", blueprint_world);
|
||||
|
||||
// here we spawn the static part our game world/level, which is also a blueprint !
|
||||
let static_world = commands.spawn((
|
||||
BlueprintInfo::from_path(blueprint_world.path.as_str()), // all we need is a Blueprint info...
|
||||
SpawnBlueprint, // and spawnblueprint to tell blenvy to spawn the blueprint now
|
||||
HideUntilReady, // only reveal the level once it is ready
|
||||
GameWorldTag,
|
||||
)).id();
|
||||
let __static_world = commands
|
||||
.spawn((
|
||||
BlueprintInfo::from_path(blueprint_world.path.as_str()), // all we need is a Blueprint info...
|
||||
SpawnBlueprint, // and spawnblueprint to tell blenvy to spawn the blueprint now
|
||||
HideUntilReady, // only reveal the level once it is ready
|
||||
GameWorldTag,
|
||||
))
|
||||
.id();
|
||||
|
||||
// here we spawn the dynamic entities part of our game world/level, which is also a blueprint !
|
||||
let dynamic_world = commands.spawn((
|
||||
BlueprintInfo::from_path(blueprint_world.path.replace(".glb", "_dynamic.glb").replace(".gltf", "_dynamic.gltf").as_str()), // all we need is a Blueprint info...
|
||||
SpawnBlueprint, // and spawnblueprint to tell blenvy to spawn the blueprint now
|
||||
HideUntilReady, // only reveal the level once it is ready
|
||||
GameWorldTag
|
||||
)).id();
|
||||
let __dynamic_world = commands
|
||||
.spawn((
|
||||
BlueprintInfo::from_path(
|
||||
blueprint_world
|
||||
.path
|
||||
.replace(".glb", "_dynamic.glb")
|
||||
.replace(".gltf", "_dynamic.gltf")
|
||||
.as_str(),
|
||||
), // all we need is a Blueprint info...
|
||||
SpawnBlueprint, // and spawnblueprint to tell blenvy to spawn the blueprint now
|
||||
HideUntilReady, // only reveal the level once it is ready
|
||||
GameWorldTag,
|
||||
))
|
||||
.id();
|
||||
|
||||
// commands.entity(entity).add_child(static_world);
|
||||
// commands.entity(entity).add_child(dynamic_world);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub(crate) fn inject_dynamic_into_children(
|
||||
added_dynamic: Query<Entity, Added<Dynamic> >,
|
||||
all_children: Query<&Children>,
|
||||
|
@ -42,4 +53,4 @@ pub(crate) fn inject_dynamic_into_children(
|
|||
commands.entity(child).insert(Dynamic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
use std::path::Path;
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::{BlenvyConfig, BlueprintInfo, DynamicEntitiesRoot, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
||||
|
||||
use crate::{BlueprintInfo, DynamicEntitiesRoot, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
||||
|
||||
#[derive(Event)]
|
||||
pub struct LoadingRequest {
|
||||
|
@ -19,7 +16,6 @@ pub struct LoadingRequested {
|
|||
pub path: String,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
- Loading
|
||||
- load request recieved
|
||||
|
@ -35,7 +31,7 @@ General:
|
|||
*/
|
||||
pub fn process_load_requests(
|
||||
mut load_requests: EventReader<LoadingRequest>,
|
||||
mut commands: Commands
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let mut save_path: String = "".into();
|
||||
for load_request in load_requests.read() {
|
||||
|
@ -49,14 +45,13 @@ pub fn process_load_requests(
|
|||
}
|
||||
|
||||
pub fn should_load(loading_requests: Option<Res<LoadingRequested>>) -> bool {
|
||||
return resource_exists::<LoadingRequested>(loading_requests)
|
||||
resource_exists::<LoadingRequested>(loading_requests)
|
||||
}
|
||||
|
||||
// TODO: replace with generic despawner ?
|
||||
pub(crate) fn prepare_loading(
|
||||
mut commands: Commands,
|
||||
gameworlds: Query<Entity, With<GameWorldTag>>,
|
||||
|
||||
) {
|
||||
for e in gameworlds.iter() {
|
||||
info!("--loading: despawn old world/level");
|
||||
|
@ -64,9 +59,6 @@ pub(crate) fn prepare_loading(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
pub(crate) fn load_game(
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
|
@ -79,17 +71,17 @@ pub(crate) fn load_game(
|
|||
info!("LOADING FROM {:?}", load_request.path.clone());
|
||||
|
||||
/*let world_root = commands
|
||||
.spawn((
|
||||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag,
|
||||
TransformBundle::default(),
|
||||
InheritedVisibility::default(),
|
||||
))
|
||||
.id();*/
|
||||
.spawn((
|
||||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag,
|
||||
TransformBundle::default(),
|
||||
InheritedVisibility::default(),
|
||||
))
|
||||
.id();*/
|
||||
|
||||
// and we fill it with dynamic data
|
||||
// let input = std::fs::read(&path)?;
|
||||
let dynamic_data = commands
|
||||
let _dynamic_data = commands
|
||||
.spawn((
|
||||
DynamicSceneBundle {
|
||||
scene: asset_server.load(load_request.path.clone()),
|
||||
|
@ -97,16 +89,18 @@ pub(crate) fn load_game(
|
|||
},
|
||||
bevy::prelude::Name::from("World_dynamic"),
|
||||
DynamicEntitiesRoot,
|
||||
GameWorldTag
|
||||
GameWorldTag,
|
||||
))
|
||||
.id();
|
||||
|
||||
let static_data = commands.spawn((
|
||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||
SpawnBlueprint,
|
||||
HideUntilReady,
|
||||
GameWorldTag,
|
||||
)).id();
|
||||
let _static_data = commands
|
||||
.spawn((
|
||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||
SpawnBlueprint,
|
||||
HideUntilReady,
|
||||
GameWorldTag,
|
||||
))
|
||||
.id();
|
||||
|
||||
//commands.entity(world_root).add_child(static_data);
|
||||
//commands.entity(world_root).add_child(dynamic_data);
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
use std::path::Path;
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub mod common;
|
||||
pub use common::*;
|
||||
|
||||
|
@ -24,7 +21,6 @@ pub(crate) struct RootEntity;
|
|||
/// internal helper component to store parents before resetting them
|
||||
pub(crate) struct OriginalParent(pub(crate) Entity);
|
||||
|
||||
|
||||
/// Marker component to Flag the root entity of all static entities (immutables)
|
||||
#[derive(Component, Reflect, Debug, Default)]
|
||||
#[reflect(Component)]
|
||||
|
@ -35,7 +31,6 @@ pub struct StaticEntitiesRoot;
|
|||
#[reflect(Component)]
|
||||
pub struct DynamicEntitiesRoot;
|
||||
|
||||
|
||||
#[derive(Resource, Clone, Debug, Default, Reflect)]
|
||||
#[reflect(Resource)]
|
||||
pub struct StaticEntitiesBlueprintInfo {
|
||||
|
@ -43,24 +38,20 @@ pub struct StaticEntitiesBlueprintInfo {
|
|||
pub path: String,
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct BlueprintWorld{
|
||||
pub struct BlueprintWorld {
|
||||
pub path: String,
|
||||
}
|
||||
impl BlueprintWorld {
|
||||
pub fn from_path(path: &str) -> BlueprintWorld {
|
||||
let p = Path::new(&path);
|
||||
return BlueprintWorld {
|
||||
// let p = Path::new(&path);
|
||||
BlueprintWorld {
|
||||
// name: p.file_stem().unwrap().to_os_string().into_string().unwrap(), // seriously ? , also unwraps !!
|
||||
path: path.into(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
/// Plugin for saving & loading
|
||||
pub struct SaveLoadPlugin {}
|
||||
|
@ -69,13 +60,10 @@ impl Plugin for SaveLoadPlugin {
|
|||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<Dynamic>()
|
||||
.register_type::<StaticEntitiesRoot>()
|
||||
|
||||
.add_event::<SavingRequest>()
|
||||
.add_event::<SaveFinished>()
|
||||
|
||||
// common
|
||||
.add_systems(Update, (spawn_from_blueprintworld, )) // inject_dynamic_into_children
|
||||
|
||||
.add_systems(Update, (spawn_from_blueprintworld,)) // inject_dynamic_into_children
|
||||
// saving
|
||||
.add_systems(Update, process_save_requests)
|
||||
.add_systems(
|
||||
|
@ -83,9 +71,7 @@ impl Plugin for SaveLoadPlugin {
|
|||
(prepare_save_game, apply_deferred, save_game, cleanup_save)
|
||||
.chain()
|
||||
.run_if(should_save),
|
||||
|
||||
)
|
||||
|
||||
.add_event::<LoadingRequest>()
|
||||
.add_event::<LoadingFinished>()
|
||||
//loading
|
||||
|
@ -95,9 +81,8 @@ impl Plugin for SaveLoadPlugin {
|
|||
(prepare_loading, apply_deferred, load_game)
|
||||
.chain()
|
||||
.run_if(should_load),
|
||||
//.run_if(not(resource_exists::<LoadFirstStageDone>))
|
||||
// .in_set(LoadingSet::Load),
|
||||
)
|
||||
;
|
||||
//.run_if(not(resource_exists::<LoadFirstStageDone>))
|
||||
// .in_set(LoadingSet::Load),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,8 @@ use std::fs::File;
|
|||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use bevy::render::camera::{CameraMainTextureUsages, CameraRenderGraph};
|
||||
use bevy::{prelude::*, tasks::IoTaskPool};
|
||||
use bevy::prelude::World;
|
||||
use bevy::{prelude::*, tasks::IoTaskPool};
|
||||
|
||||
use crate::{BlenvyConfig, BlueprintInfo, Dynamic, FromBlueprint, RootEntity, SpawnBlueprint};
|
||||
|
||||
|
@ -17,17 +16,15 @@ pub struct SavingRequest {
|
|||
#[derive(Event)]
|
||||
pub struct SaveFinished; // TODO: merge the the events above
|
||||
|
||||
|
||||
/// resource that keeps track of the current save request
|
||||
#[derive(Resource, Default)]
|
||||
pub struct SavingRequested {
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
|
||||
pub fn process_save_requests(
|
||||
mut saving_requests: EventReader<SavingRequest>,
|
||||
mut commands: Commands
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let mut save_path: String = "".into();
|
||||
for saving_request in saving_requests.read() {
|
||||
|
@ -40,22 +37,21 @@ pub fn process_save_requests(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn should_save(saving_requests: Option<Res<SavingRequested>>) -> bool {
|
||||
return resource_exists::<SavingRequested>(saving_requests)
|
||||
resource_exists::<SavingRequested>(saving_requests)
|
||||
}
|
||||
|
||||
|
||||
// any child of dynamic/ saveable entities that is not saveable itself should be removed from the list of children
|
||||
pub(crate) fn prepare_save_game(
|
||||
saveables: Query<Entity, (With<Dynamic>, With<BlueprintInfo>)>,
|
||||
root_entities: Query<Entity, Or<(With<DynamicEntitiesRoot>, Without<Parent>)>>, // With<DynamicEntitiesRoot>
|
||||
dynamic_entities: Query<(Entity, &Parent, Option<&Children>), With<Dynamic>>,
|
||||
static_entities: Query<(Entity, &BlueprintInfo), With<StaticEntitiesRoot>>,
|
||||
_static_entities: Query<(Entity, &BlueprintInfo), With<StaticEntitiesRoot>>,
|
||||
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for entity in saveables.iter() { // FIXME : not sure about this one
|
||||
for entity in saveables.iter() {
|
||||
// FIXME : not sure about this one
|
||||
commands.entity(entity).insert(SpawnBlueprint);
|
||||
}
|
||||
|
||||
|
@ -84,8 +80,6 @@ pub(crate) fn prepare_save_game(
|
|||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub(crate) fn save_game(world: &mut World) {
|
||||
info!("saving");
|
||||
|
||||
|
@ -126,7 +120,6 @@ pub(crate) fn save_game(world: &mut World) {
|
|||
.allow::<BlueprintInfo>()
|
||||
.allow::<SpawnBlueprint>()
|
||||
.allow::<Dynamic>()
|
||||
|
||||
/*.deny::<CameraRenderGraph>()
|
||||
.deny::<CameraMainTextureUsages>()
|
||||
.deny::<Handle<Mesh>>()
|
||||
|
@ -136,18 +129,19 @@ pub(crate) fn save_game(world: &mut World) {
|
|||
// for root entities, it is the same EXCEPT we make sure parents are not included
|
||||
let filter_root = filter.clone().deny::<Parent>();
|
||||
|
||||
let filter_resources = config.clone()
|
||||
let filter_resources = config
|
||||
.clone()
|
||||
.save_resource_filter
|
||||
.deny::<Time<Real>>()
|
||||
.clone();
|
||||
//.allow::<StaticEntitiesStorage>();
|
||||
//.allow::<StaticEntitiesStorage>();
|
||||
|
||||
// for default stuff
|
||||
let scene_builder = DynamicSceneBuilder::from_world(world)
|
||||
.with_filter(filter.clone())
|
||||
.with_resource_filter(filter_resources.clone());
|
||||
|
||||
let mut dyn_scene = scene_builder
|
||||
let dyn_scene = scene_builder
|
||||
.extract_resources()
|
||||
.extract_entities(saveable_entities.clone().into_iter())
|
||||
.remove_empty_entities()
|
||||
|
@ -158,7 +152,7 @@ pub(crate) fn save_game(world: &mut World) {
|
|||
.with_filter(filter_root.clone())
|
||||
.with_resource_filter(filter_resources.clone());
|
||||
|
||||
let mut dyn_scene_root = scene_builder_root
|
||||
let mut __dyn_scene_root = scene_builder_root
|
||||
.extract_resources()
|
||||
.extract_entities(
|
||||
saveable_root_entities.clone().into_iter(), // .chain(static_world_markers.into_iter()),
|
||||
|
@ -191,7 +185,6 @@ pub(crate) fn save_game(world: &mut World) {
|
|||
})
|
||||
.detach();
|
||||
|
||||
|
||||
let static_world_path = "levels/world.glb";
|
||||
let fake_foo = format!("(dynamic: {bla}, static: {static_world_path})");
|
||||
let real_save_path = format!("{bla}.save.ron");
|
||||
|
@ -218,5 +211,4 @@ pub(crate) fn cleanup_save(
|
|||
saving_finished.send(SaveFinished);
|
||||
|
||||
commands.remove_resource::<SavingRequested>();
|
||||
|
||||
}
|
|
@ -203,6 +203,19 @@
|
|||
"type": "array",
|
||||
"typeInfo": "List"
|
||||
},
|
||||
"alloc::vec::Vec<blenvy::blueprints::materials::MaterialInfo>": {
|
||||
"isComponent": false,
|
||||
"isResource": false,
|
||||
"items": {
|
||||
"type": {
|
||||
"$ref": "#/$defs/blenvy::blueprints::materials::MaterialInfo"
|
||||
}
|
||||
},
|
||||
"long_name": "alloc::vec::Vec<blenvy::blueprints::materials::MaterialInfo>",
|
||||
"short_name": "Vec<MaterialInfo>",
|
||||
"type": "array",
|
||||
"typeInfo": "List"
|
||||
},
|
||||
"alloc::vec::Vec<f32>": {
|
||||
"isComponent": false,
|
||||
"isResource": false,
|
||||
|
@ -1410,6 +1423,44 @@
|
|||
"type": "object",
|
||||
"typeInfo": "Enum"
|
||||
},
|
||||
"bevy_asset::handle::Handle<blenvy::blueprints::assets::BlueprintPreloadAssets>": {
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"long_name": "bevy_asset::handle::Handle<blenvy::blueprints::assets::BlueprintPreloadAssets>",
|
||||
"oneOf": [
|
||||
{
|
||||
"items": false,
|
||||
"long_name": "Strong",
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": {
|
||||
"$ref": "#/$defs/std::sync::Arc<bevy_asset::handle::StrongHandle>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"short_name": "Strong",
|
||||
"type": "array",
|
||||
"typeInfo": "Tuple"
|
||||
},
|
||||
{
|
||||
"items": false,
|
||||
"long_name": "Weak",
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": {
|
||||
"$ref": "#/$defs/bevy_asset::id::AssetId<blenvy::blueprints::assets::BlueprintPreloadAssets>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"short_name": "Weak",
|
||||
"type": "array",
|
||||
"typeInfo": "Tuple"
|
||||
}
|
||||
],
|
||||
"short_name": "Handle<BlueprintPreloadAssets>",
|
||||
"type": "object",
|
||||
"typeInfo": "Enum"
|
||||
},
|
||||
"bevy_asset::id::AssetId<()>": {
|
||||
"isComponent": false,
|
||||
"isResource": false,
|
||||
|
@ -2422,6 +2473,52 @@
|
|||
"type": "object",
|
||||
"typeInfo": "Enum"
|
||||
},
|
||||
"bevy_asset::id::AssetId<blenvy::blueprints::assets::BlueprintPreloadAssets>": {
|
||||
"isComponent": false,
|
||||
"isResource": false,
|
||||
"long_name": "bevy_asset::id::AssetId<blenvy::blueprints::assets::BlueprintPreloadAssets>",
|
||||
"oneOf": [
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"long_name": "Index",
|
||||
"properties": {
|
||||
"index": {
|
||||
"long_name": "index",
|
||||
"type": {
|
||||
"$ref": "#/$defs/bevy_asset::assets::AssetIndex"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"index"
|
||||
],
|
||||
"short_name": "Index",
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"long_name": "Uuid",
|
||||
"properties": {
|
||||
"uuid": {
|
||||
"long_name": "uuid",
|
||||
"type": {
|
||||
"$ref": "#/$defs/uuid::Uuid"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"uuid"
|
||||
],
|
||||
"short_name": "Uuid",
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
}
|
||||
],
|
||||
"short_name": "AssetId<BlueprintPreloadAssets>",
|
||||
"type": "object",
|
||||
"typeInfo": "Enum"
|
||||
},
|
||||
"bevy_asset::path::AssetPath": {
|
||||
"isComponent": false,
|
||||
"isResource": false,
|
||||
|
@ -12353,7 +12450,7 @@
|
|||
},
|
||||
"blenvy::blueprints::materials::MaterialInfo": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
"isComponent": false,
|
||||
"isResource": false,
|
||||
"long_name": "blenvy::blueprints::materials::MaterialInfo",
|
||||
"properties": {
|
||||
|
@ -12376,6 +12473,22 @@
|
|||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::blueprints::materials::MaterialInfos": {
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"items": false,
|
||||
"long_name": "blenvy::blueprints::materials::MaterialInfos",
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": {
|
||||
"$ref": "#/$defs/alloc::vec::Vec<blenvy::blueprints::materials::MaterialInfo>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"short_name": "MaterialInfos",
|
||||
"type": "array",
|
||||
"typeInfo": "TupleStruct"
|
||||
},
|
||||
"blenvy::blueprints::spawn_from_blueprints::BlueprintInfo": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
|
@ -12401,6 +12514,17 @@
|
|||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::blueprints::spawn_from_blueprints::BlueprintInstanceDisabled": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"long_name": "blenvy::blueprints::spawn_from_blueprints::BlueprintInstanceDisabled",
|
||||
"properties": {},
|
||||
"required": [],
|
||||
"short_name": "BlueprintInstanceDisabled",
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::blueprints::spawn_from_blueprints::HideUntilReady": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
|
@ -12541,6 +12665,28 @@
|
|||
"type": "string",
|
||||
"typeInfo": "Enum"
|
||||
},
|
||||
"blenvy::save_load::Dynamic": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"long_name": "blenvy::save_load::Dynamic",
|
||||
"properties": {},
|
||||
"required": [],
|
||||
"short_name": "Dynamic",
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy::save_load::StaticEntitiesRoot": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
"isResource": false,
|
||||
"long_name": "blenvy::save_load::StaticEntitiesRoot",
|
||||
"properties": {},
|
||||
"required": [],
|
||||
"short_name": "StaticEntitiesRoot",
|
||||
"type": "object",
|
||||
"typeInfo": "Struct"
|
||||
},
|
||||
"blenvy_animation_example::Fox": {
|
||||
"additionalProperties": false,
|
||||
"isComponent": true,
|
||||
|
|
|
@ -2,11 +2,9 @@ use std::time::Duration;
|
|||
|
||||
use bevy::prelude::*;
|
||||
use blenvy::{
|
||||
AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintAnimationPlayerLink,
|
||||
BlueprintAnimations, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag, HideUntilReady,
|
||||
SpawnBlueprint,
|
||||
BlenvyPlugin, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintInfo, GameWorldTag,
|
||||
HideUntilReady, SpawnBlueprint,
|
||||
};
|
||||
use rand::Rng;
|
||||
|
||||
mod component_examples;
|
||||
use component_examples::*;
|
||||
|
@ -75,11 +73,10 @@ pub fn animation_control(
|
|||
animation_transitions
|
||||
.play(
|
||||
&mut animation_player,
|
||||
animations
|
||||
*animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
.expect("animation name should be in the list"),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
|
@ -96,11 +93,10 @@ pub fn animation_control(
|
|||
animation_transitions
|
||||
.play(
|
||||
&mut animation_player,
|
||||
animations
|
||||
*animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
.expect("animation name should be in the list"),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
|
@ -116,11 +112,10 @@ pub fn animation_control(
|
|||
animation_transitions
|
||||
.play(
|
||||
&mut animation_player,
|
||||
animations
|
||||
*animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
.expect("animation name should be in the list"),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
|
@ -136,11 +131,10 @@ pub fn animation_control(
|
|||
animation_transitions
|
||||
.play(
|
||||
&mut animation_player,
|
||||
animations
|
||||
*animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
.expect("animation name should be in the list"),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use bevy::prelude::*;
|
||||
use blenvy::{
|
||||
AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintInfo, DynamicBlueprintInstance,
|
||||
GameWorldTag, HideUntilReady, SpawnBlueprint,
|
||||
AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintInfo, Dynamic, GameWorldTag,
|
||||
HideUntilReady, SpawnBlueprint,
|
||||
};
|
||||
use rand::Rng;
|
||||
|
||||
|
@ -33,16 +33,8 @@ fn setup_game(mut commands: Commands) {
|
|||
}
|
||||
|
||||
// you can also spawn blueprint instances at runtime
|
||||
pub fn spawn_blueprint_instance(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
pub fn spawn_blueprint_instance(keycode: Res<ButtonInput<KeyCode>>, mut commands: Commands) {
|
||||
if keycode.just_pressed(KeyCode::KeyS) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
|
@ -50,7 +42,7 @@ pub fn spawn_blueprint_instance(
|
|||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
let __new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintInfo {
|
||||
|
@ -59,7 +51,7 @@ pub fn spawn_blueprint_instance(
|
|||
}, // FIXME
|
||||
..Default::default()
|
||||
},
|
||||
DynamicBlueprintInstance,
|
||||
Dynamic,
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
HideUntilReady,
|
||||
AddToGameWorld,
|
||||
|
|
|
@ -7,5 +7,5 @@ license = "MIT OR Apache-2.0"
|
|||
[dependencies]
|
||||
bevy = { version = "0.14", features = ["dynamic_linking"] }
|
||||
blenvy = { path = "../../crates/blenvy" }
|
||||
bevy_rapier3d = { version = "0.25.0", features = ["serde-serialize", "debug-render-3d", "enhanced-determinism"] }
|
||||
rand = "0.8.5"
|
||||
avian3d = "0.1.2"
|
|
@ -1,83 +0,0 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{assets::GameAssets, GameState, InAppRunning};
|
||||
use blenvy::{BluePrintBundle, BlueprintName, GameWorldTag};
|
||||
|
||||
use bevy_rapier3d::prelude::Velocity;
|
||||
use rand::Rng;
|
||||
|
||||
pub fn setup_game(
|
||||
mut commands: Commands,
|
||||
game_assets: Res<GameAssets>,
|
||||
models: Res<Assets<bevy::gltf::Gltf>>,
|
||||
mut next_game_state: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
commands.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 0.2,
|
||||
});
|
||||
// here we actually spawn our game world/level
|
||||
|
||||
commands.spawn((
|
||||
SceneBundle {
|
||||
// note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene
|
||||
scene: models
|
||||
.get(game_assets.world.clone().unwrap().id())
|
||||
.expect("main level should have been loaded")
|
||||
.scenes[0]
|
||||
.clone(),
|
||||
..default()
|
||||
},
|
||||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag,
|
||||
InAppRunning,
|
||||
));
|
||||
|
||||
next_game_state.set(GameState::InGame)
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
struct UnregisteredComponent;
|
||||
|
||||
pub fn spawn_test(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::KeyT) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 0.8;
|
||||
let vel_x: f32 = rng.gen_range(-range..range);
|
||||
let vel_y: f32 = rng.gen_range(2.0..2.5);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("Health_Pickup".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
// BlueprintName("Health_Pickup".to_string()),
|
||||
// SpawnHere,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
Velocity {
|
||||
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||
},
|
||||
))
|
||||
.id();
|
||||
commands.entity(world).add_child(new_entity);
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{AppState, InMainMenu};
|
||||
|
||||
pub fn setup_main_menu(mut commands: Commands) {
|
||||
commands.spawn((
|
||||
Camera2dBundle {
|
||||
camera: Camera {
|
||||
order: 102, // needed because of this: https://github.com/jakobhellermann/bevy_editor_pls/blob/crates/bevy_editor_pls_default_windows/src/cameras/mod.rs#L213C9-L213C28
|
||||
..default()
|
||||
},
|
||||
..Default::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,8 +1,4 @@
|
|||
use bevy::{gltf::Gltf, prelude::*};
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{
|
||||
assets::GameAssets, GameState, InAppRunning, Player,
|
||||
};
|
||||
use bevy_rapier3d::prelude::*;
|
||||
use blenvy::GameWorldTag;
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
|
|
|
@ -1,23 +1,11 @@
|
|||
pub mod in_game;
|
||||
pub use in_game::*;
|
||||
|
||||
pub mod in_main_menu;
|
||||
pub use in_main_menu::*;
|
||||
|
||||
pub mod level_transitions;
|
||||
pub use level_transitions::*;
|
||||
// pub mod level_transitions;
|
||||
// pub use level_transitions::*;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{AppState, GameState};
|
||||
|
||||
pub struct GamePlugin;
|
||||
impl Plugin for GamePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins(LevelsPlugin)
|
||||
.add_systems(Update, (spawn_test).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);
|
||||
fn build(&self, __app: &mut App) {
|
||||
//app.add_plugins(LevelsPlugin);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
use avian3d::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
|
||||
mod core;
|
||||
use crate::core::*;
|
||||
use blenvy::{
|
||||
AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintInfo, Dynamic, GameWorldTag,
|
||||
HideUntilReady, SpawnBlueprint,
|
||||
};
|
||||
|
||||
mod game;
|
||||
use game::*;
|
||||
|
||||
mod test_components;
|
||||
use rand::Rng;
|
||||
use test_components::*;
|
||||
|
||||
fn main() {
|
||||
|
@ -14,9 +17,56 @@ fn main() {
|
|||
.add_plugins((
|
||||
DefaultPlugins.set(AssetPlugin::default()),
|
||||
// our custom plugins
|
||||
CorePlugin, // reusable plugins
|
||||
GamePlugin, // specific to our game
|
||||
ComponentsTestPlugin, // Showcases different type of components /structs
|
||||
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
||||
BlenvyPlugin::default(),
|
||||
GamePlugin,
|
||||
))
|
||||
.add_systems(Startup, setup_game)
|
||||
.add_systems(Update, spawn_blueprint_instance)
|
||||
.run();
|
||||
}
|
||||
|
||||
// this is how you setup & spawn a level from a blueprint
|
||||
fn setup_game(mut commands: Commands) {
|
||||
// here we actually spawn our game world/level
|
||||
commands.spawn((
|
||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||
SpawnBlueprint, // and spawnblueprint to tell blenvy to spawn the blueprint now
|
||||
HideUntilReady, // only reveal the level once it is ready
|
||||
GameWorldTag,
|
||||
));
|
||||
}
|
||||
|
||||
// you can also spawn blueprint instances at runtime
|
||||
pub fn spawn_blueprint_instance(keycode: Res<ButtonInput<KeyCode>>, mut commands: Commands) {
|
||||
if keycode.just_pressed(KeyCode::KeyS) {
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 0.8;
|
||||
let vel_x: f32 = rng.gen_range(-range..range);
|
||||
let vel_y: f32 = rng.gen_range(2.0..2.5);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let __new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintInfo::from_path("blueprints/Health_Pickup.glb"),
|
||||
..Default::default()
|
||||
},
|
||||
Dynamic,
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
HideUntilReady,
|
||||
AddToGameWorld,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
LinearVelocity(Vec3::new(vel_x, vel_y, vel_z)),
|
||||
))
|
||||
.id();
|
||||
// commands.entity(world).add_child(new_entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,8 +60,8 @@ pub enum EnumTest {
|
|||
None,
|
||||
}
|
||||
|
||||
pub struct ComponentsTestPlugin;
|
||||
impl Plugin for ComponentsTestPlugin {
|
||||
pub struct ComponentsExamplesPlugin;
|
||||
impl Plugin for ComponentsExamplesPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<BasicTest>()
|
||||
.register_type::<UnitTest>()
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
use std::any::TypeId;
|
||||
|
||||
use bevy::{prelude::*, utils::hashbrown::HashSet};
|
||||
use blenvy::{AddToGameWorld, BlenvyPlugin, BlueprintInfo, BlueprintWorld, Dynamic, DynamicBlueprintInstance, GameWorldTag, HideUntilReady, LoadingRequest, SavingRequest, SpawnBlueprint};
|
||||
use blenvy::{
|
||||
AddToGameWorld, BlenvyPlugin, BlueprintInfo, BlueprintWorld, Dynamic, HideUntilReady,
|
||||
LoadingRequest, SavingRequest, SpawnBlueprint,
|
||||
};
|
||||
use rand::Rng;
|
||||
|
||||
// mod game;
|
||||
// use game::*;
|
||||
|
||||
mod component_examples;
|
||||
use component_examples::*;
|
||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
||||
use component_examples::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
|
@ -39,19 +42,16 @@ fn main() {
|
|||
// GamePlugin, // specific to our game
|
||||
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
||||
))
|
||||
|
||||
.add_systems(Startup, setup_game)
|
||||
.add_systems(Update, (spawn_blueprint_instance, move_movers, save_game, load_game))
|
||||
|
||||
.add_systems(
|
||||
Update,
|
||||
(spawn_blueprint_instance, move_movers, save_game, load_game),
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
// this is how you setup & spawn a level from a blueprint
|
||||
fn setup_game(
|
||||
mut commands: Commands,
|
||||
) {
|
||||
|
||||
|
||||
fn setup_game(mut commands: Commands) {
|
||||
// would be nice: contains both static & dynamic stuff
|
||||
commands.spawn((
|
||||
BlueprintWorld::from_path("levels/World.glb"), // will take care of loading both static & dynamic data
|
||||
|
@ -59,10 +59,7 @@ fn setup_game(
|
|||
}
|
||||
|
||||
// you can also spawn blueprint instances at runtime
|
||||
fn spawn_blueprint_instance(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
fn spawn_blueprint_instance(keycode: Res<ButtonInput<KeyCode>>, mut commands: Commands) {
|
||||
if keycode.just_pressed(KeyCode::KeyT) {
|
||||
// random position
|
||||
let mut rng = rand::thread_rng();
|
||||
|
@ -73,32 +70,26 @@ fn spawn_blueprint_instance(
|
|||
// random name
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
BlueprintInfo::from_path("blueprints/test.glb"),
|
||||
SpawnBlueprint,
|
||||
DynamicBlueprintInstance,
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
HideUntilReady,
|
||||
AddToGameWorld,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
));
|
||||
commands.spawn((
|
||||
BlueprintInfo::from_path("blueprints/test.glb"),
|
||||
SpawnBlueprint,
|
||||
Dynamic,
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
HideUntilReady,
|
||||
AddToGameWorld,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn move_movers(
|
||||
mut movers: Query<(&mut Transform), With<Dynamic>>
|
||||
) {
|
||||
for mut transform in movers.iter_mut(){
|
||||
fn move_movers(mut movers: Query<&mut Transform, With<Dynamic>>) {
|
||||
for mut transform in movers.iter_mut() {
|
||||
// println!("moving dynamic entity");
|
||||
transform.translation.x += 0.005;
|
||||
}
|
||||
}
|
||||
|
||||
fn save_game(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut save_requests: EventWriter<SavingRequest>,
|
||||
) {
|
||||
fn save_game(keycode: Res<ButtonInput<KeyCode>>, mut save_requests: EventWriter<SavingRequest>) {
|
||||
if keycode.just_pressed(KeyCode::KeyS) {
|
||||
save_requests.send(SavingRequest {
|
||||
path: "scenes/save.scn.ron".into(),
|
||||
|
@ -106,11 +97,7 @@ fn save_game(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn load_game(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut load_requests: EventWriter<LoadingRequest>,
|
||||
) {
|
||||
fn load_game(keycode: Res<ButtonInput<KeyCode>>, mut load_requests: EventWriter<LoadingRequest>) {
|
||||
if keycode.just_pressed(KeyCode::KeyL) {
|
||||
load_requests.send(LoadingRequest {
|
||||
path: "scenes/save.scn.ron".into(),
|
||||
|
|
|
@ -5,11 +5,11 @@ use std::time::Duration;
|
|||
InstanceAnimationPlayerLink, InstanceAnimations,
|
||||
};*/
|
||||
|
||||
use bevy::{animation::RepeatAnimation, gltf::Gltf, prelude::*};
|
||||
use bevy::prelude::*;
|
||||
|
||||
use blenvy::{
|
||||
AnimationInfos, AnimationMarkerReached, BlueprintAnimationPlayerLink, BlueprintAnimations,
|
||||
BlueprintInstanceDisabled, InstanceAnimationPlayerLink, InstanceAnimations,
|
||||
InstanceAnimationPlayerLink, InstanceAnimations,
|
||||
};
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
|
@ -79,68 +79,6 @@ pub fn animations(
|
|||
}
|
||||
}*/
|
||||
|
||||
pub fn check_animations(
|
||||
// (&BlueprintAnimationPlayerLink, &BlueprintAnimations)
|
||||
foxes: Query<
|
||||
(
|
||||
Entity,
|
||||
Option<&BlueprintAnimationPlayerLink>,
|
||||
Option<&InstanceAnimationPlayerLink>,
|
||||
),
|
||||
(With<MarkerAllFoxes>, Without<BlueprintInstanceDisabled>),
|
||||
>,
|
||||
|
||||
foo: Query<
|
||||
(
|
||||
Entity,
|
||||
Option<&BlueprintAnimationPlayerLink>,
|
||||
Option<&InstanceAnimationPlayerLink>,
|
||||
),
|
||||
(With<Marker1>, Without<BlueprintInstanceDisabled>),
|
||||
>,
|
||||
bar: Query<
|
||||
(
|
||||
Entity,
|
||||
Option<&BlueprintAnimationPlayerLink>,
|
||||
Option<&InstanceAnimationPlayerLink>,
|
||||
),
|
||||
(With<Marker2>, Without<BlueprintInstanceDisabled>),
|
||||
>,
|
||||
baz: Query<
|
||||
(
|
||||
Entity,
|
||||
Option<&BlueprintAnimationPlayerLink>,
|
||||
Option<&InstanceAnimationPlayerLink>,
|
||||
),
|
||||
(With<Marker3>, Without<BlueprintInstanceDisabled>),
|
||||
>,
|
||||
|
||||
bli: Query<(Entity, &AnimationInfos)>,
|
||||
anim_players: Query<(Entity, &AnimationPlayer)>,
|
||||
all_names: Query<&Name>,
|
||||
) {
|
||||
/*for bla in foxes.iter() {
|
||||
println!("MarkerAllFoxes {:?} {:?} {:?}", all_names.get(bla.0), bla.1, bla.2)
|
||||
}
|
||||
for bla in foo.iter() {
|
||||
println!("Marker1 {:?} {:?} {:?}", all_names.get(bla.0), bla.1, bla.2)
|
||||
}
|
||||
|
||||
for bla in bar.iter() {
|
||||
println!("Marker2 {:?} {:?} {:?}", all_names.get(bla.0), bla.1, bla.2)
|
||||
}
|
||||
for bla in baz.iter() {
|
||||
println!("Marker3 {:?} {:?} {:?}", all_names.get(bla.0), bla.1, bla.2)
|
||||
}
|
||||
println!(""); */
|
||||
/*for blo in bli.iter() {
|
||||
println!("YOOOOO {:?}", all_names.get(blo.0))
|
||||
}
|
||||
for anim in anim_players.iter() {
|
||||
println!("Players {:?}", all_names.get(anim.0))
|
||||
}*/
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn play_animations(
|
||||
animated_foxes: Query<
|
||||
|
@ -183,11 +121,10 @@ pub fn play_animations(
|
|||
let (mut animation_player, mut animation_transitions) =
|
||||
animation_players.get_mut(link.0).unwrap();
|
||||
let anim_name = "Survey";
|
||||
let animation_index = animations
|
||||
let animation_index = *animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone();
|
||||
.expect("animation name should be in the list");
|
||||
|
||||
animation_transitions
|
||||
.play(
|
||||
|
@ -204,23 +141,19 @@ pub fn play_animations(
|
|||
println!("Playing animation {:?}", playing_animation);
|
||||
playing_animation.set_repeat(RepeatAnimation::Forever);*/
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
|
||||
if keycode.just_pressed(KeyCode::KeyP) {
|
||||
println!("playing fox blueprint animation requested");
|
||||
for (link, animations) in animated_foxes.iter() {
|
||||
println!("FOO");
|
||||
|
||||
// println!("animations {:?}", animations.named_animations);
|
||||
let (mut animation_player, mut animation_transitions) =
|
||||
animation_players.get_mut(link.0).unwrap();
|
||||
let anim_name = "Run";
|
||||
let animation_index = animations
|
||||
let animation_index = *animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone();
|
||||
.expect("animation name should be in the list");
|
||||
|
||||
animation_transitions
|
||||
.play(
|
||||
|
@ -237,7 +170,7 @@ pub fn play_animations(
|
|||
println!("Playing animation {:?}", playing_animation);
|
||||
playing_animation.set_repeat(RepeatAnimation::Forever);*/
|
||||
}
|
||||
println!("");
|
||||
println!(" ");
|
||||
}
|
||||
|
||||
if keycode.just_pressed(KeyCode::KeyO) {
|
||||
|
@ -248,11 +181,10 @@ pub fn play_animations(
|
|||
let (mut animation_player, mut animation_transitions) =
|
||||
animation_players.get_mut(link.0).unwrap();
|
||||
let anim_name = "Walk";
|
||||
let animation_index = animations
|
||||
let animation_index = *animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone();
|
||||
.expect("animation name should be in the list");
|
||||
|
||||
animation_transitions
|
||||
.play(
|
||||
|
@ -271,11 +203,10 @@ pub fn play_animations(
|
|||
let (mut animation_player, mut animation_transitions) =
|
||||
animation_players.get_mut(link.0).unwrap();
|
||||
let anim_name = "Blueprint8_move";
|
||||
let animation_index = animations
|
||||
let animation_index = *animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone();
|
||||
.expect("animation name should be in the list");
|
||||
|
||||
animation_transitions
|
||||
.play(
|
||||
|
@ -294,11 +225,10 @@ pub fn play_animations(
|
|||
animation_players.get_mut(link.0).unwrap();
|
||||
|
||||
let anim_name = "Blueprint1_move";
|
||||
let animation_index = animations
|
||||
let animation_index = *animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone();
|
||||
.expect("animation name should be in the list");
|
||||
|
||||
animation_transitions
|
||||
.play(
|
||||
|
@ -316,11 +246,10 @@ pub fn play_animations(
|
|||
animation_players.get_mut(link.0).unwrap();
|
||||
|
||||
let anim_name = "Blueprint1_jump";
|
||||
let animation_index = animations
|
||||
let animation_index = *animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone();
|
||||
.expect("animation name should be in the list");
|
||||
|
||||
animation_transitions
|
||||
.play(
|
||||
|
@ -338,11 +267,10 @@ pub fn play_animations(
|
|||
animation_players.get_mut(link.0).unwrap();
|
||||
|
||||
let anim_name = "Blueprint1_move";
|
||||
let animation_index = animations
|
||||
let animation_index = *animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone();
|
||||
.expect("animation name should be in the list");
|
||||
|
||||
animation_transitions
|
||||
.play(
|
||||
|
@ -355,7 +283,7 @@ pub fn play_animations(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn react_to_animation_markers(
|
||||
pub fn __react_to_animation_markers(
|
||||
mut animation_marker_events: EventReader<AnimationMarkerReached>,
|
||||
) {
|
||||
for event in animation_marker_events.read() {
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
use crate::{GameState, InAppRunning};
|
||||
use bevy::prelude::*;
|
||||
use blenvy::{
|
||||
AddToGameWorld, BluePrintBundle, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag,
|
||||
HideUntilReady, SpawnBlueprint,
|
||||
AddToGameWorld, BluePrintBundle, BlueprintInfo, Dynamic, GameWorldTag, HideUntilReady,
|
||||
SpawnBlueprint,
|
||||
};
|
||||
|
||||
//use bevy_rapier3d::prelude::Velocity;
|
||||
use rand::Rng;
|
||||
|
||||
pub fn setup_game(
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut next_game_state: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
pub fn setup_game(mut commands: Commands, mut next_game_state: ResMut<NextState<GameState>>) {
|
||||
// here we actually spawn our game world/level
|
||||
commands.spawn((
|
||||
BlueprintInfo::from_path("levels/World.glb"),
|
||||
|
@ -29,30 +25,22 @@ pub fn setup_game(
|
|||
#[reflect(Component)]
|
||||
struct UnregisteredComponent;
|
||||
|
||||
pub fn spawn_test(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
pub fn spawn_test(keycode: Res<ButtonInput<KeyCode>>, mut commands: Commands) {
|
||||
if keycode.just_pressed(KeyCode::KeyS) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
/*let mut rng = rand::thread_rng();
|
||||
let range = 0.8;
|
||||
let vel_x: f32 = rng.gen_range(-range..range);
|
||||
let vel_y: f32 = rng.gen_range(2.0..2.5);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);*/
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
let __new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintInfo {
|
||||
|
@ -61,7 +49,7 @@ pub fn spawn_test(
|
|||
}, // FIXME
|
||||
..Default::default()
|
||||
},
|
||||
DynamicBlueprintInstance,
|
||||
Dynamic,
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
HideUntilReady,
|
||||
AddToGameWorld,
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::{collections::HashMap, fs, time::Duration};
|
|||
|
||||
use blenvy::{
|
||||
BlueprintAnimationPlayerLink, BlueprintAssets, BlueprintEvent, BlueprintInfo,
|
||||
GltfBlueprintsSet, InstanceAnimations,
|
||||
InstanceAnimations,
|
||||
};
|
||||
|
||||
use crate::{AppState, GameState};
|
||||
|
@ -136,8 +136,8 @@ fn check_for_gltf_events(
|
|||
match event {
|
||||
BlueprintEvent::InstanceReady {
|
||||
entity,
|
||||
blueprint_name,
|
||||
blueprint_path,
|
||||
blueprint_name: _,
|
||||
blueprint_path: _,
|
||||
} => {
|
||||
info!(
|
||||
"BLUEPRINT EVENT: {:?} for {:?}",
|
||||
|
@ -147,8 +147,8 @@ fn check_for_gltf_events(
|
|||
}
|
||||
BlueprintEvent::AssetsLoaded {
|
||||
entity,
|
||||
blueprint_name,
|
||||
blueprint_path,
|
||||
blueprint_name: _,
|
||||
blueprint_path: _,
|
||||
} => {
|
||||
info!(
|
||||
"BLUEPRINT EVENT: {:?} for {:?}",
|
||||
|
@ -156,9 +156,6 @@ fn check_for_gltf_events(
|
|||
all_names.get(*entity)
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
info!("BLUEPRINT EVENT: {:?}", event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,14 +180,14 @@ impl Plugin for GamePlugin {
|
|||
.run_if(in_state(AppState::AppRunning))
|
||||
.after(GltfBlueprintsSet::AfterSpawn)
|
||||
)*/
|
||||
.add_systems(Update, (play_animations, check_animations))
|
||||
.add_systems(Update, play_animations) // check_animations
|
||||
//.add_systems(Update, react_to_animation_markers)
|
||||
|
||||
/*.add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once
|
||||
.add_systems(Update, generate_screenshot.run_if(on_timer(Duration::from_secs_f32(0.2)))) // TODO: run once
|
||||
.add_systems(
|
||||
Update,
|
||||
exit_game.run_if(on_timer(Duration::from_secs_f32(0.5))),
|
||||
) // shut down the app after this time*/
|
||||
) // shut down the app after this time
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,13 @@ use bevy::{
|
|||
gltf::{GltfMaterialExtras, GltfMeshExtras, GltfSceneExtras},
|
||||
prelude::*,
|
||||
};
|
||||
use blenvy::{BlueprintAssets, BlueprintInstanceReady};
|
||||
|
||||
use crate::{BasicTest, EnumComplex, EnumTest, RedirectPropHitImpulse};
|
||||
use crate::{EnumTest, RedirectPropHitImpulse};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct HiearchyDebugTag;
|
||||
|
||||
pub fn setup_hierarchy_debug(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
pub fn setup_hierarchy_debug(mut commands: Commands) {
|
||||
// a place to display the extras on screen
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
|
@ -40,25 +39,25 @@ pub fn get_descendants(
|
|||
all_children: &Query<&Children>,
|
||||
all_names: &Query<&Name>,
|
||||
root: &Entity,
|
||||
all_transforms: &Query<&Transform>,
|
||||
all_global_transforms: &Query<&GlobalTransform>,
|
||||
__all_transforms: &Query<&Transform>,
|
||||
__all_global_transforms: &Query<&GlobalTransform>,
|
||||
nesting: usize,
|
||||
to_check: &Query<&EnumTest>, //&Query<(&BlueprintInstanceReady, &BlueprintAssets)>,
|
||||
) -> String {
|
||||
let mut hierarchy_display: Vec<String> = vec![];
|
||||
let root_name = all_names.get(*root);
|
||||
let name;
|
||||
if root_name.is_ok() {
|
||||
name = root_name.unwrap().to_string();
|
||||
if let Ok(root_name) = root_name {
|
||||
name = root_name.to_string();
|
||||
} else {
|
||||
name = "no_name".to_string()
|
||||
name = "no_name".to_string();
|
||||
}
|
||||
|
||||
let mut component_display: String = "".into();
|
||||
let components_to_check = to_check.get(*root);
|
||||
let __components_to_check = to_check.get(*root);
|
||||
|
||||
if let Ok(compo) = to_check.get(*root) {
|
||||
component_display = format!("{:?}", compo).clone();
|
||||
component_display = format!("{:?}", compo);
|
||||
}
|
||||
|
||||
hierarchy_display.push(format!(
|
||||
|
@ -72,22 +71,22 @@ pub fn get_descendants(
|
|||
if let Ok(children) = all_children.get(*root) {
|
||||
for child in children.iter() {
|
||||
let child_descendants_display = get_descendants(
|
||||
&all_children,
|
||||
&all_names,
|
||||
&child,
|
||||
&all_transforms,
|
||||
&all_global_transforms,
|
||||
all_children,
|
||||
all_names,
|
||||
child,
|
||||
__all_transforms,
|
||||
__all_global_transforms,
|
||||
nesting + 4,
|
||||
&to_check,
|
||||
to_check,
|
||||
);
|
||||
hierarchy_display.push(child_descendants_display);
|
||||
}
|
||||
}
|
||||
return hierarchy_display.join("\n");
|
||||
hierarchy_display.join("\n")
|
||||
}
|
||||
|
||||
pub fn draw_hierarchy_debug(
|
||||
root: Query<(Entity, Option<&Name>, &Children), (Without<Parent>)>,
|
||||
root: Query<Entity, Without<Parent>>,
|
||||
all_children: Query<&Children>,
|
||||
all_names: Query<&Name>,
|
||||
all_transforms: Query<&Transform>,
|
||||
|
@ -98,7 +97,7 @@ pub fn draw_hierarchy_debug(
|
|||
) {
|
||||
let mut hierarchy_display: Vec<String> = vec![];
|
||||
|
||||
for (root_entity, name, children) in root.iter() {
|
||||
for root_entity in root.iter() {
|
||||
// hierarchy_display.push( format!("Hierarchy root{:?}", name) );
|
||||
|
||||
hierarchy_display.push(get_descendants(
|
||||
|
@ -124,7 +123,8 @@ pub fn draw_hierarchy_debug(
|
|||
}
|
||||
|
||||
////////:just some testing for gltf extras
|
||||
fn check_for_gltf_extras(
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn __check_for_gltf_extras(
|
||||
gltf_extras_per_entity: Query<(
|
||||
Entity,
|
||||
Option<&Name>,
|
||||
|
@ -137,7 +137,7 @@ fn check_for_gltf_extras(
|
|||
) {
|
||||
let mut gltf_extra_infos_lines: Vec<String> = vec![];
|
||||
|
||||
for (id, name, scene_extras, extras, mesh_extras, material_extras) in
|
||||
for (id, name, scene_extras, __extras, mesh_extras, material_extras) in
|
||||
gltf_extras_per_entity.iter()
|
||||
{
|
||||
if scene_extras.is_some()
|
||||
|
@ -165,12 +165,12 @@ fn check_for_gltf_extras(
|
|||
}
|
||||
}
|
||||
|
||||
fn check_for_component(
|
||||
foo: Query<(Entity, Option<&Name>, &RedirectPropHitImpulse)>,
|
||||
fn __check_for_component(
|
||||
specific_components: Query<(Entity, Option<&Name>, &RedirectPropHitImpulse)>,
|
||||
mut display: Query<&mut Text, With<HiearchyDebugTag>>,
|
||||
) {
|
||||
let mut info_lines: Vec<String> = vec![];
|
||||
for (entiity, name, enum_complex) in foo.iter() {
|
||||
for (__entiity, name, enum_complex) in specific_components.iter() {
|
||||
let data = format!(
|
||||
" We have a matching component: {:?} (on {:?})",
|
||||
enum_complex, name
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use bevy::prelude::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
||||
pub enum AppState {
|
||||
CoreLoading,
|
||||
|
@ -10,6 +11,7 @@ pub enum AppState {
|
|||
AppEnding,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
||||
pub enum GameState {
|
||||
#[default]
|
||||
|
@ -25,8 +27,6 @@ pub enum GameState {
|
|||
}
|
||||
|
||||
// tag components for all entities within a certain state (for despawning them if needed) , FIXME: seems kinda hack-ish
|
||||
#[derive(Component)]
|
||||
pub struct InCoreLoading;
|
||||
#[derive(Component, Default)]
|
||||
pub struct InMenuRunning;
|
||||
#[derive(Component)]
|
||||
|
|
|
@ -78,7 +78,7 @@ class AutoExportSettings(PropertyGroup):
|
|||
) # type: ignore
|
||||
|
||||
split_out_animations: BoolProperty(
|
||||
name='Split out animations',
|
||||
name='Split out animations (not functional yet)',
|
||||
description='removes animations/armatures from blueprints and exports them separately ',
|
||||
default=False,
|
||||
update=save_settings
|
||||
|
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 12 KiB |