From 1417d5f3897b1329f03a786909a981bbd5ec9b01 Mon Sep 17 00:00:00 2001 From: Mark Moissette Date: Wed, 2 Aug 2023 01:45:57 +0200 Subject: [PATCH] refactor(): restructured code to turn the process_gltf (core) part into a crate (#1) * refactor(): restructured code to turn the process_gltf (core) part into a crate * changed process_gltf into a lib/crate basics * changed current demo setup into an example that is importing the new crate * updated imports in the crate side * updated dependencies * cleanups * added more clear information about preUpdate vs setup * improved README/ added use as crate examples --- Cargo.lock | 22 +- Cargo.toml | 22 +- README.md | 190 +++++++++++++++++- .../core/camera/camera_replace_proxies.rs | 0 .../general}/core/camera/camera_tracking.rs | 0 {src => examples/general}/core/camera/mod.rs | 0 .../core/lighting/lighting_replace_proxies.rs | 0 .../general}/core/lighting/mod.rs | 0 {src => examples/general}/core/mod.rs | 4 - .../general}/core/physics/controls.rs | 0 {src => examples/general}/core/physics/mod.rs | 0 .../core/physics/physics_replace_proxies.rs | 0 .../general}/core/physics/utils.rs | 0 .../general}/core/physics/utils_old.rs | 0 .../general}/core/relationships/mod.rs | 0 ...lationships_insert_dependant_components.rs | 0 {src => examples/general}/game.rs | 0 {src => examples/general}/main.rs | 13 +- {src => examples/general}/test_components.rs | 0 src/core/process_gltf/mod.rs | 34 ---- .../process_gltf => }/gltf_to_components.rs | 11 +- src/lib.rs | 57 ++++++ src/{core/process_gltf => }/process_gltfs.rs | 2 +- src/{core/process_gltf => }/utils.rs | 0 24 files changed, 284 insertions(+), 71 deletions(-) rename {src => examples/general}/core/camera/camera_replace_proxies.rs (100%) rename {src => examples/general}/core/camera/camera_tracking.rs (100%) rename {src => examples/general}/core/camera/mod.rs (100%) rename {src => examples/general}/core/lighting/lighting_replace_proxies.rs (100%) rename {src => examples/general}/core/lighting/mod.rs (100%) rename {src => examples/general}/core/mod.rs (83%) rename {src => examples/general}/core/physics/controls.rs (100%) rename {src => examples/general}/core/physics/mod.rs (100%) rename {src => examples/general}/core/physics/physics_replace_proxies.rs (100%) rename {src => examples/general}/core/physics/utils.rs (100%) rename {src => examples/general}/core/physics/utils_old.rs (100%) rename {src => examples/general}/core/relationships/mod.rs (100%) rename {src => examples/general}/core/relationships/relationships_insert_dependant_components.rs (100%) rename {src => examples/general}/game.rs (100%) rename {src => examples/general}/main.rs (90%) rename {src => examples/general}/test_components.rs (100%) delete mode 100644 src/core/process_gltf/mod.rs rename src/{core/process_gltf => }/gltf_to_components.rs (97%) create mode 100644 src/lib.rs rename src/{core/process_gltf => }/process_gltfs.rs (98%) rename src/{core/process_gltf => }/utils.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 1b3e638..adc92ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -675,6 +675,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "bevy_gltf_components" +version = "0.2.0" +dependencies = [ + "bevy", + "bevy_editor_pls", + "bevy_rapier3d", + "ron", + "serde", +] + [[package]] name = "bevy_hierarchy" version = "0.11.0" @@ -1208,17 +1219,6 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" -[[package]] -name = "blender-worklfow" -version = "0.1.0" -dependencies = [ - "bevy", - "bevy_editor_pls", - "bevy_rapier3d", - "ron", - "serde", -] - [[package]] name = "block" version = "0.1.6" diff --git a/Cargo.toml b/Cargo.toml index f537f4a..2f3c0e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,17 +1,23 @@ [package] -name = "blender-worklfow" -version = "0.1.0" +name = "bevy_gltf_components" +version = "0.2.0" edition = "2021" +license = "MIT OR Apache-2.0" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -bevy="0.11.0" -serde = "*" -ron="*" +[dev-dependencies] +bevy="0.11" bevy_rapier3d = { version = "0.22.0", features = [ "serde-serialize", "debug-render-3d", "enhanced-determinism"] } bevy_editor_pls = { git="https://github.com/jakobhellermann/bevy_editor_pls.git" } +[dependencies] +bevy = { version = "0.11", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] } +serde = "*" +ron="*" + +[[example]] +name = "general" +path = "examples/general/main.rs" + #### --------------------Dev/ debug------------------------------- # Enable high optimizations for dependencies (incl. Bevy), but not for our code: [profile.dev.package."*"] diff --git a/README.md b/README.md index d476a66..b40b9fc 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,190 @@ -# Blender_bevy_components_worklflow +# bevy_gltf_components ![demo](./docs/blender_gltf_components.png) +A plugin & tools for adding components from gltf files in the [bevy](https://bevyengine.org/) game engine. + +It enables minimalistic [Blender](https://www.blender.org/) (gltf) centric workflow for Bevy, ie defining entites & their components +inside Blender using Blender's objects **custom properties**. +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 . + +## Features + +* Useful if you want to use Blender (or any editor allowing to export gltf with configurable gltf_extras) as your Editor +* define Bevy components as custom properties in Blender (RON, though an older JSON version is also available) +* no plugin or extra tools needed in Blender (but I provide a little Blender plugin to auto-export to gltf on save if you want !) +* define components in Blender Collections & override any of them in your collection instances if you want +* minimal setup & code, you can have something basic running fast + +## Usage + +1. Add the crate to your dependencies +```toml +[dependencies] +bevy_gltf_components = { git="https://github.com/kaosat-dev/Blender_bevy_components_worklflow.git" } + +``` +(not on crates.io yet !) + +2. Import + +```rust +use bevy_gltf_components::ComponentsFromGltfPlugin; +``` + +3. Add the plugin +```rust +.add_plugin(ComponentsFromGltfPlugin) +``` + +### Example (without bevy_asset_loader) + +See [here](./examples/general/main.rs) for more details + + ```rust +use bevy::prelude::*; +use bevy_gltf_components::ComponentsFromGltfPlugin; + + +#[derive(Component, Reflect, Default, Debug, Deref, DerefMut)] +#[reflect(Component)] +struct TuppleTestF32(f32); + +#[derive(Component, Reflect, Default, Debug, )] +#[reflect(Component)] +/// helper marker component, for demo only +pub struct LoadedMarker; + + +#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] +enum AppState { + #[default] + Loading, + Running, +} + +fn main(){ + App::new() + .add_plugins(( + DefaultPlugins, + ComponentsFromGltfPlugin, + )) + + .add_state::() + .add_systems(Startup, setup) + .add_systems(Update, ( + spawn_level.run_if(in_state(AppState::Loading)), + )) + .run(); +} + +#[derive(Resource)] +struct AssetLoadHelper(Handle); +// we preload the data here, but this is for DEMO PURPOSES ONLY !! Please use https://github.com/NiklasEi/bevy_asset_loader or a similar logic to seperate loading / pre processing +// of assets from the spawning +// AssetLoadHelper is also just for the same purpose, you do not need it in a real scenario +// the states here are also for demo purposes only, +fn setup( + mut commands: Commands, + asset_server: Res, +) { + + let tmp: Handle = asset_server.load("models/level1.glb#Scene0"); + commands.insert_resource(AssetLoadHelper(tmp)); +} + +fn spawn_level( + mut commands: Commands, + scene_markers: Query<&LoadedMarker>, + preloaded_scene: Res, + + mut asset_event_reader: EventReader>, + mut next_state: ResMut>, +){ + + if let Some(asset_event) = asset_event_reader.iter().next() { + match asset_event { + AssetEvent::Created { handle: _ } => { + info!("GLTF loaded"); + if scene_markers.is_empty() { + info!("spawning scene"); + commands.spawn( + ( + SceneBundle { + scene: preloaded_scene.0.clone(), + ..default() + }, + LoadedMarker, + Name::new("Level1") + ) + ); + next_state.set(AppState::Running); + } + } + _ => () + } + } +} + + +``` + + +### Example (with bevy_asset_loader, recommended for ease of use) + +- follow [bevy_asset_loader's](https://github.com/NiklasEi/bevy_asset_loader) docs to setup your gltf asset loading +- also add this plugin + + ```rust +use bevy::prelude::*; +use bevy_gltf_components::ComponentsFromGltfPlugin; + +// replace this with your actual states ! +#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] +enum AppState { + #[default] + Loading, + Running, +} + + +fn main(){ + App::new() + .add_plugins(( + DefaultPlugins, + ComponentsFromGltfPlugin, + )) + // do the setup for bevy_asset_loader + .add_system(setup_game.in_schedule(OnEnter(AppState::Running))) + + .run(); +} + + +pub fn setup_game( + mut commands: Commands, + game_assets: Res, // assets with your "world" or "level" gltf for example +) { + + + // more fast approach, load the game seperatly + commands.spawn(( + SceneBundle { + scene: game_assets.world.clone(), + ..default() + }, + bevy::prelude::Name::from("world"), + )); + +} + + +``` + +# Workflow with blender This example, is actually closer to a boilerplate + tooling showcases how to use a minimalistic [Blender](https://www.blender.org/) (gltf) centric workflow for [Bevy](https://bevyengine.org/), ie defining entites & their components inside Blender using Blender's objects **custom properties**. @@ -12,7 +194,7 @@ It also allows you to setup 'blueprints' in Blender by using collections (the re ## Features -* Useful if you want to use Blender as your Editor +* Useful if you want to use Blender (or any editor allowing to export gltf with configurable gltf_extras) as your Editor * define Bevy components as custom properties in Blender (RON, though an older JSON version is also available) * no plugin or extra tools needed in Blender (but I provide a little Blender plugin to auto-export to gltf on save if you want !) * define components in Blender Collections & override any of them in your collection instances if you want @@ -22,6 +204,10 @@ It also allows you to setup 'blueprints' in Blender by using collections (the re There is a [video tutorial/explanation](https://youtu.be/-lcScjQCA3c) if you want, or you can skip to the text version ahead + +important : the plugin for processing gltf files runs in *preUpdate* , 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 included example or use bevy_asset_loader for a reliable workflow + ## Workflow The workflow goes as follows (once you got your Bevy code setup) diff --git a/src/core/camera/camera_replace_proxies.rs b/examples/general/core/camera/camera_replace_proxies.rs similarity index 100% rename from src/core/camera/camera_replace_proxies.rs rename to examples/general/core/camera/camera_replace_proxies.rs diff --git a/src/core/camera/camera_tracking.rs b/examples/general/core/camera/camera_tracking.rs similarity index 100% rename from src/core/camera/camera_tracking.rs rename to examples/general/core/camera/camera_tracking.rs diff --git a/src/core/camera/mod.rs b/examples/general/core/camera/mod.rs similarity index 100% rename from src/core/camera/mod.rs rename to examples/general/core/camera/mod.rs diff --git a/src/core/lighting/lighting_replace_proxies.rs b/examples/general/core/lighting/lighting_replace_proxies.rs similarity index 100% rename from src/core/lighting/lighting_replace_proxies.rs rename to examples/general/core/lighting/lighting_replace_proxies.rs diff --git a/src/core/lighting/mod.rs b/examples/general/core/lighting/mod.rs similarity index 100% rename from src/core/lighting/mod.rs rename to examples/general/core/lighting/mod.rs diff --git a/src/core/mod.rs b/examples/general/core/mod.rs similarity index 83% rename from src/core/mod.rs rename to examples/general/core/mod.rs index b816c25..478f449 100644 --- a/src/core/mod.rs +++ b/examples/general/core/mod.rs @@ -1,6 +1,3 @@ -pub mod process_gltf; -pub use process_gltf::*; - pub mod camera; pub use camera::*; @@ -19,7 +16,6 @@ impl Plugin for CorePlugin { fn build(&self, app: &mut App) { app .add_plugins(( - ProcessGltfPlugin, LightingPlugin, CameraPlugin, PhysicsPlugin diff --git a/src/core/physics/controls.rs b/examples/general/core/physics/controls.rs similarity index 100% rename from src/core/physics/controls.rs rename to examples/general/core/physics/controls.rs diff --git a/src/core/physics/mod.rs b/examples/general/core/physics/mod.rs similarity index 100% rename from src/core/physics/mod.rs rename to examples/general/core/physics/mod.rs diff --git a/src/core/physics/physics_replace_proxies.rs b/examples/general/core/physics/physics_replace_proxies.rs similarity index 100% rename from src/core/physics/physics_replace_proxies.rs rename to examples/general/core/physics/physics_replace_proxies.rs diff --git a/src/core/physics/utils.rs b/examples/general/core/physics/utils.rs similarity index 100% rename from src/core/physics/utils.rs rename to examples/general/core/physics/utils.rs diff --git a/src/core/physics/utils_old.rs b/examples/general/core/physics/utils_old.rs similarity index 100% rename from src/core/physics/utils_old.rs rename to examples/general/core/physics/utils_old.rs diff --git a/src/core/relationships/mod.rs b/examples/general/core/relationships/mod.rs similarity index 100% rename from src/core/relationships/mod.rs rename to examples/general/core/relationships/mod.rs diff --git a/src/core/relationships/relationships_insert_dependant_components.rs b/examples/general/core/relationships/relationships_insert_dependant_components.rs similarity index 100% rename from src/core/relationships/relationships_insert_dependant_components.rs rename to examples/general/core/relationships/relationships_insert_dependant_components.rs diff --git a/src/game.rs b/examples/general/game.rs similarity index 100% rename from src/game.rs rename to examples/general/game.rs diff --git a/src/main.rs b/examples/general/main.rs similarity index 90% rename from src/main.rs rename to examples/general/main.rs index 701e5d7..333f167 100644 --- a/src/main.rs +++ b/examples/general/main.rs @@ -2,6 +2,7 @@ use std::time::Duration; use bevy::{prelude::*, asset::ChangeWatcher, gltf::Gltf}; use bevy_editor_pls::prelude::*; use bevy_rapier3d::prelude::*; +use bevy_gltf_components::ComponentsFromGltfPlugin; mod core; use crate::core::*; @@ -45,6 +46,7 @@ fn main(){ RapierPhysicsPlugin::::default(), RapierDebugRenderPlugin::default(), // our custom plugins + ComponentsFromGltfPlugin, CorePlugin, // reusable plugins DemoPlugin, // specific to our game ComponentsTestPlugin // Showcases different type of components /structs @@ -61,10 +63,10 @@ fn main(){ #[derive(Resource)] -struct AssetLoadHack(Handle); +struct AssetLoadHelper(Handle); // we preload the data here, but this is for DEMO PURPOSES ONLY !! Please use https://github.com/NiklasEi/bevy_asset_loader or a similar logic to seperate loading / pre processing // of assets from the spawning -// AssetLoadHack is also just for the same purpose, you do not need it in a real scenario +// AssetLoadHelper is also just for the same purpose, you do not need it in a real scenario // the states here are also for demo purposes only, fn setup( mut commands: Commands, @@ -72,13 +74,13 @@ fn setup( ) { let tmp: Handle = asset_server.load("models/level1.glb#Scene0"); - commands.insert_resource(AssetLoadHack(tmp)); + commands.insert_resource(AssetLoadHelper(tmp)); } fn spawn_level( mut commands: Commands, scene_markers: Query<&LoadedMarker>, - preloaded_scene: Res, + preloaded_scene: Res, mut asset_event_reader: EventReader>, mut next_state: ResMut>, @@ -106,7 +108,4 @@ fn spawn_level( _ => () } } - - - } diff --git a/src/test_components.rs b/examples/general/test_components.rs similarity index 100% rename from src/test_components.rs rename to examples/general/test_components.rs diff --git a/src/core/process_gltf/mod.rs b/src/core/process_gltf/mod.rs deleted file mode 100644 index eeed514..0000000 --- a/src/core/process_gltf/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -pub mod utils; -pub use utils::*; - -pub mod gltf_to_components; -pub use gltf_to_components::*; - -pub mod process_gltfs; -pub use process_gltfs::*; - -// pub mod models_replace_proxies; -// pub use models_replace_proxies::*; - -use bevy::prelude::*; - -// use crate::state::{AppState}; - -pub struct ProcessGltfPlugin; -impl Plugin for ProcessGltfPlugin { - fn build(&self, app: &mut App) { - app - .insert_resource(GltfLoadingTracker::new()) - - .add_systems(PreUpdate, ( - track_new_gltf, - process_loaded_scenes, - )) - - // .add_systems((models_replace_proxies,).in_set(OnUpdate(AppState::GameRunning))) - - // compute the aabbs of a whole hierarchy - //.add_systems((compute_compound_aabb,).in_set(OnUpdate(AppState::GameRunning))) - ; - } -} \ No newline at end of file diff --git a/src/core/process_gltf/gltf_to_components.rs b/src/gltf_to_components.rs similarity index 97% rename from src/core/process_gltf/gltf_to_components.rs rename to src/gltf_to_components.rs index fab219d..2822bee 100644 --- a/src/core/process_gltf/gltf_to_components.rs +++ b/src/gltf_to_components.rs @@ -1,12 +1,15 @@ -use std::collections::HashMap; use core::ops::Deref; + use ron::Value; use serde::de::DeserializeSeed; -use bevy::prelude::*; -use bevy::reflect::serde::{UntypedReflectDeserializer, ReflectSerializer}; -use bevy::reflect::{TypeRegistryInternal, TypeInfo}; +use bevy::prelude::{ResMut, Assets, info, debug, Name, Parent, warn}; +use bevy::ecs::{entity::Entity, reflect::ReflectComponent}; +use bevy::scene::Scene; +use bevy::utils::HashMap; +use bevy::reflect::serde::UntypedReflectDeserializer; +use bevy::reflect::{TypeRegistryInternal, TypeInfo, Reflect}; use bevy::gltf::{Gltf, GltfExtras}; use super::capitalize_first_letter; diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..45cf1fc --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,57 @@ +pub mod utils; +pub use utils::*; + +pub mod gltf_to_components; +pub use gltf_to_components::*; + +pub mod process_gltfs; +pub use process_gltfs::*; + +use bevy::prelude::{ + App,Plugin, PreUpdate +}; + + +/// A Bevy plugin for extracting components from gltf files and automatically adding them to the relevant entities +/// It will automatically run every time you load a gltf file +/// Add this plugin to your Bevy app to get access to this feature +/// ``` +/// # use bevy::prelude::*; +/// # use bevy_gltf_components::ComponentsFromGltfPlugin::*; +/// +/// +/// fn main() { +/// App::new() +/// .add_plugins(DefaultPlugins) +/// .add_plugin(GltfComponentsPlugin) +/// .add_startup_system(setup) +/// .add_system(spawn_level) +/// .run(); +/// } +/// +/// fn setup( +/// mut state: ResMut, +/// asset_server: Res, +/// mut commands: bevy::prelude::Commands +/// ){ +/// asset_server.load("models/level1.glb#Scene0") +/// } +/// +/// fn spawn_level(){ +/// +///} +/// ``` +#[derive(Default)] +pub struct ComponentsFromGltfPlugin; +impl Plugin for ComponentsFromGltfPlugin { + fn build(&self, app: &mut App) { + app + .insert_resource(GltfLoadingTracker::new()) + + .add_systems(PreUpdate, ( + track_new_gltf, + process_loaded_scenes, + )) + ; + } +} diff --git a/src/core/process_gltf/process_gltfs.rs b/src/process_gltfs.rs similarity index 98% rename from src/core/process_gltf/process_gltfs.rs rename to src/process_gltfs.rs index fb0d2f1..66cf9b9 100644 --- a/src/core/process_gltf/process_gltfs.rs +++ b/src/process_gltfs.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use bevy::utils::HashSet; use bevy::{prelude::*, asset::LoadState}; use bevy::gltf::Gltf; diff --git a/src/core/process_gltf/utils.rs b/src/utils.rs similarity index 100% rename from src/core/process_gltf/utils.rs rename to src/utils.rs