diff --git a/Cargo.toml b/Cargo.toml index 06d67d6..c4d07cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ "crates/*", - "examples/common*", "examples/blenvy/*", "testing/bevy_example/", ] diff --git a/Migration_guide.md b/Migration_guide.md index d53eb26..d8e5ca1 100644 --- a/Migration_guide.md +++ b/Migration_guide.md @@ -1,6 +1,6 @@ # Blender add-ons -- gltf_auto_export and bevy_components have been replaced with a single add-on for simplicity +- gltf_auto_export and bevy_components have been replaced with a single Blenvy add-on for simplicity ## Components: @@ -111,7 +111,7 @@ Blenvy will take care of loading all needed blueprints & other assets for you ``` -## BlueprintDisabled +## BlueprintInstanceDisabled you can now query for this component diff --git a/TODO.md b/TODO.md index ee1ed84..10d9a3d 100644 --- a/TODO.md +++ b/TODO.md @@ -58,7 +58,7 @@ Components: - [x] BLENVY_OT_component_rename_component - [x] BLENVY_OT_component_fix - [x] add handling for core::ops::Range & other ranges - - [x] fix is_component_valid that is used in gltf_auto_export + - [x] fix is_component_valid that is used in blenvy - [x] Hashmap Support - [x] fix parsing of keys's type either on Bevy side (prefered) or on the Blender side - [x] fix weird issue with missing "0" property when adding new entry in empty hashmap => happens only if the values for the "setter" have never been set @@ -286,7 +286,7 @@ Bevy Side: - [ ] invalidate despawned entity & parent entities AABB - [ ] add unloading/cache removal of materials - +- [ ] add back and upgrade save-load - [x] review & change general component insertion & spawning ordering & logic - GltfComponentsSet::Injection => GltfBlueprintsSet::Spawn => GltfBlueprintsSet::AfterSpawn @@ -299,8 +299,13 @@ Bevy Side: - [x] how to deal with animation graphs ? -- [ ] remove "Library" component & co -- [ ] BlueprintDisabled => BlueprintInstanceDisabled +- [x] remove "Library" component & co +- [x] make "InBlueprint" non optional, +- [ ] and perhaps rename it to "FromBlueprint(BlueprintInfo)" + +- [x] BlueprintInstanceDisabled => BlueprintInstanceDisabled +- [x] fix "remove component" operator from the rename/fix/update components panel +- [ ] replace string in BlueprintInfo path with PathBuf ? - [ ] update main docs - [ ] rename project to Blenvy diff --git a/crates/blenvy/README.md b/crates/blenvy/README.md index c5371c1..dcffd1b 100644 --- a/crates/blenvy/README.md +++ b/crates/blenvy/README.md @@ -33,7 +33,7 @@ Its main use case is as a backbone for the [```blenvy``` Blender add-on](https:/ * 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/Blender_bevy_components_workflow/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) +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/Blender_bevy_components_workflow/tree/main/tools/blenvy) that does a lot of the work for you (including spliting generating seperate gltf files for your static vs dynamic assets) ## Usage @@ -290,37 +290,25 @@ particularly from https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy ## Materials -You have the option of using "material libraries" to share common textures/materials between blueprints, in order to avoid asset & memory bloat: - +Ff you enable it on the blender side, Blenvy will be 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 -``` - -> Important! you must take care of preloading your material librairy gltf files in advance, using for example ```bevy_asset_loader```since -```blenvy``` currently does NOT take care of loading those at runtime - - -see https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/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) +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/blenvy) ## Examples -https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/basic +https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/components -https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/basic_xpbd_physics +https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/blueprints https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/animation -https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/materials +https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/save_load -https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/multiple_levels_multiple_blendfiles +https://github.com/kaosat-dev/Blenvy/tree/main/examples/blenvy/demo (a full fledged demo) ## Compatible Bevy versions diff --git a/crates/blenvy/src/blueprints/animation.rs b/crates/blenvy/src/blueprints/animation.rs index 7d10889..6f381b5 100644 --- a/crates/blenvy/src/blueprints/animation.rs +++ b/crates/blenvy/src/blueprints/animation.rs @@ -45,7 +45,7 @@ pub struct AnimationInfo { } /// Stores information about animations, to make things a bit easier api wise: -/// these components are automatically inserted by `gltf_auto_export` on entities that have animations +/// these components are automatically inserted by the `blenvy` Blender add-on on entities that have animations #[derive(Component, Reflect, Default, Debug)] #[reflect(Component)] pub struct AnimationInfos { diff --git a/examples/blenvy/blueprints/README.md b/examples/blenvy/blueprints/README.md index 2ec70cf..6de5350 100644 --- a/examples/blenvy/blueprints/README.md +++ b/examples/blenvy/blueprints/README.md @@ -2,7 +2,7 @@ # Materials example/demo Example of materials use & reuse (including textures) to avoid redundant materials in blueprints gltfs that lead to asset & memory bloat -- to be used together with ```gltf_auto_export``` version >0.6 with the "materials library" option for exports +- to be used together with ```blenvy``` version >0.6 with the "materials library" option for exports - It shows you how ou can configure```Bevy_gltf_blueprints``` to support material libraries - material library is [here](./assets/materials/) diff --git a/examples/blenvy/components/Cargo.toml b/examples/blenvy/components/Cargo.toml index 5f25820..01ffd42 100644 --- a/examples/blenvy/components/Cargo.toml +++ b/examples/blenvy/components/Cargo.toml @@ -7,4 +7,3 @@ license = "MIT OR Apache-2.0" [dependencies] bevy = { version = "0.14", features = ["dynamic_linking"] } blenvy = { path = "../../../crates/blenvy" } -#bevy_gltf_worlflow_examples_common_rapier = { path = "../../common_rapier" } diff --git a/examples/blenvy/save_load/Cargo.toml b/examples/blenvy/save_load/Cargo.toml index e1afba2..ad3bb60 100644 --- a/examples/blenvy/save_load/Cargo.toml +++ b/examples/blenvy/save_load/Cargo.toml @@ -5,12 +5,9 @@ edition = "2021" license = "MIT OR Apache-2.0" [dependencies] -bevy = { version = "0.13", features = ["dynamic_linking"] } -bevy_gltf_blueprints = { path = "../../../crates/bevy_gltf_blueprints" } -bevy_gltf_save_load = { path = "../../../crates/bevy_gltf_save_load" } -bevy_gltf_worlflow_examples_common_rapier = { path = "../../common_rapier" } +bevy = { version = "0.14", features = ["dynamic_linking"] } +blenvy = { path = "../../../crates/blenvy" } serde_json = "1.0.108" serde = "1.0.193" -bevy_rapier3d = { version = "0.25.0", features = ["serde-serialize", "debug-render-3d", "enhanced-determinism"] } rand = "0.8.5" \ No newline at end of file diff --git a/examples/blenvy/save_load/src/test_components.rs b/examples/blenvy/save_load/src/component_examples.rs similarity index 96% rename from examples/blenvy/save_load/src/test_components.rs rename to examples/blenvy/save_load/src/component_examples.rs index b5384e2..e5d7cef 100644 --- a/examples/blenvy/save_load/src/test_components.rs +++ b/examples/blenvy/save_load/src/component_examples.rs @@ -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::() .register_type::() diff --git a/examples/blenvy/save_load/src/core/mod.rs b/examples/blenvy/save_load/src/core/mod.rs deleted file mode 100644 index 59bbda1..0000000 --- a/examples/blenvy/save_load/src/core/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -use bevy::{ - core_pipeline::tonemapping::Tonemapping, - prelude::*, - render::{camera::CameraRenderGraph, primitives::Frustum, view::VisibleEntities}, - utils::HashSet, -}; -use bevy_gltf_blueprints::*; -use bevy_gltf_save_load::*; -use bevy_gltf_worlflow_examples_common_rapier::{CameraTrackingOffset, Pickable}; -use bevy_rapier3d::dynamics::Velocity; -use std::any::TypeId; - -pub struct CorePlugin; -impl Plugin for CorePlugin { - fn build(&self, app: &mut App) { - app.add_plugins(( - SaveLoadPlugin { - save_path: "scenes".into(), - component_filter: SceneFilter::Allowlist(HashSet::from([ - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - TypeId::of::(), - ])), - ..Default::default() - }, - BlueprintsPlugin { - aabbs: true, - ..Default::default() - }, - )); - } -} diff --git a/examples/blenvy/save_load/src/main.rs b/examples/blenvy/save_load/src/main.rs index 3c95987..fd64b90 100644 --- a/examples/blenvy/save_load/src/main.rs +++ b/examples/blenvy/save_load/src/main.rs @@ -1,5 +1,8 @@ -use bevy::prelude::*; -use bevy_gltf_worlflow_examples_common_rapier::CommonPlugin; +use std::any::TypeId; + +use bevy::{prelude::*, utils::hashbrown::HashSet}; +use blenvy::{AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag, HideUntilReady, SpawnBlueprint}; +use rand::Rng; mod core; use crate::core::*; @@ -7,18 +10,99 @@ use crate::core::*; mod game; use game::*; -mod test_components; -use test_components::*; +mod component_examples; +use component_examples::*; fn main() { App::new() .add_plugins(( DefaultPlugins.set(AssetPlugin::default()), + BlenvyPlugin { + save_component_filter: SceneFilter::Allowlist(HashSet::from([ + TypeId::of::(), + TypeId::of::(), + //TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + //TypeId::of::(), + //TypeId::of::(), + TypeId::of::(), + //TypeId::of::(), + //TypeId::of::(), + TypeId::of::(), + //TypeId::of::(), + //TypeId::of::(), + ])), + ..Default::default() + }, // our custom plugins - CommonPlugin, CorePlugin, // reusable plugins GamePlugin, // specific to our game - ComponentsTestPlugin, // Showcases different type of components /structs + ComponentsExamplesPlugin, // Showcases different type of components /structs )) + + .add_systems(Startup, setup_game) + .add_systems(Update, (spawn_blueprint_instance, save_game, load_game)) + .run(); } + +// this is how you setup & spawn a level from a blueprint +fn setup_game( + mut commands: Commands, +) { + + // here we spawn our game world/level, which is also a blueprint ! + 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 +fn spawn_blueprint_instance( + keycode: Res>, + mut commands: Commands, +) { + if keycode.just_pressed(KeyCode::KeyT) { + // random position + 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); + + // 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)), + )); + } +} + +fn save_game( + keycode: Res>, + +) { + if keycode.just_pressed(KeyCode::KeyS) { + + } +} + +fn load_game( + keycode: Res>, +) { + if keycode.just_pressed(KeyCode::KeyL) { + + } +} diff --git a/examples/demo/Cargo.toml b/examples/demo/Cargo.toml index bea96b6..b26b54a 100644 --- a/examples/demo/Cargo.toml +++ b/examples/demo/Cargo.toml @@ -1,12 +1,11 @@ [package] -name = "bevy_gltf_blueprints_multiple_levels_multiple_blendfiles" +name = "blenvy_demo" version = "0.3.0" edition = "2021" license = "MIT OR Apache-2.0" [dependencies] -bevy = { version = "0.13", features = ["dynamic_linking"] } -bevy_gltf_blueprints = { path = "../../../crates/bevy_gltf_blueprints" } -bevy_gltf_worlflow_examples_common_rapier = { path = "../../common_rapier" } +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" \ No newline at end of file diff --git a/testing/bevy_example/Cargo.toml b/testing/bevy_example/Cargo.toml index 80f6e33..90b258c 100644 --- a/testing/bevy_example/Cargo.toml +++ b/testing/bevy_example/Cargo.toml @@ -7,13 +7,6 @@ license = "MIT OR Apache-2.0" [dependencies] bevy = { version = "0.14", features = ["dynamic_linking"] } blenvy = { path = "../../crates/blenvy" } -# bevy_gltf_blueprints = { path = "../../crates/bevy_gltf_blueprints" } -# bevy_registry_export = { path = "../../crates/bevy_registry_export" } -# bevy_gltf_worlflow_examples_common_rapier = { path = "../../examples/common_rapier" } -#bevy_gltf_worlflow_examples_common = { path = "../../examples/common" } - -#evy_rapier3d = { version = "0.25.0", features = ["serde-serialize", "debug-render-3d", "enhanced-determinism"] } -#bevy_asset_loader = { version = "0.20", features = ["standard_dynamic_assets"] } #bevy_editor_pls = { version = "0.8" } rand = "0.8.5" json-writer ="0.3" \ No newline at end of file diff --git a/testing/bevy_example/src/game/animation.rs b/testing/bevy_example/src/game/animation.rs index 109fc33..225c0f9 100644 --- a/testing/bevy_example/src/game/animation.rs +++ b/testing/bevy_example/src/game/animation.rs @@ -9,7 +9,7 @@ use bevy::{animation::RepeatAnimation, gltf::Gltf, prelude::*}; use blenvy::{ AnimationInfos, AnimationMarkerReached, BlueprintAnimationPlayerLink, BlueprintAnimations, - BlueprintDisabled, SceneAnimationPlayerLink, SceneAnimations, + BlueprintInstanceDisabled, SceneAnimationPlayerLink, SceneAnimations, }; #[derive(Component, Reflect, Default, Debug)] @@ -87,7 +87,7 @@ pub fn check_animations( Option<&BlueprintAnimationPlayerLink>, Option<&SceneAnimationPlayerLink>, ), - (With, Without), + (With, Without), >, foo: Query< @@ -96,7 +96,7 @@ pub fn check_animations( Option<&BlueprintAnimationPlayerLink>, Option<&SceneAnimationPlayerLink>, ), - (With, Without), + (With, Without), >, bar: Query< ( @@ -104,7 +104,7 @@ pub fn check_animations( Option<&BlueprintAnimationPlayerLink>, Option<&SceneAnimationPlayerLink>, ), - (With, Without), + (With, Without), >, baz: Query< ( @@ -112,7 +112,7 @@ pub fn check_animations( Option<&BlueprintAnimationPlayerLink>, Option<&SceneAnimationPlayerLink>, ), - (With, Without), + (With, Without), >, bli: Query<(Entity, &AnimationInfos)>, diff --git a/tools/blenvy/TODO_components.md b/tools/blenvy/TODO_components.md deleted file mode 100644 index 786b29a..0000000 --- a/tools/blenvy/TODO_components.md +++ /dev/null @@ -1,229 +0,0 @@ -Basics -- [x] add panel -- [x] add a "create blueprint" button - - [x] when clicked: - - [x] create collection - - [x] add an empty inside collection and name it _components - - [x] add a **AutoExport** Boolean property to collection - - [x] add name imput(popup for name input ?) - -- [x] add a list of existing components/custom properties -- [x] add an "edit blueprint" section - - [x] only filled when there is ONE selection, and that selection is a collection - - [x] add a dropdown of possible components - - [x] add a checkbox for enabling disabling a component (enabled by default) - - [x] add a button for copying a component - - [x] add a button for pasting a component - - -UI: - - [x] filterable list of components to DISPLAY for selection : ComponentDefinitionsList - -- Filter out invalid objects for components that have no _components suffix ? (that is too limiting I think) -- -[x] How to deal with pre-existing custom properties that have NO metadata - * if there is one without metadata: find if there is an available component with the same name & type ? - * if there is , insert metadata - * otherwise, mark it in some way visually ? - -- [x] for OBJECT enums: add two ui pieces - - [x] one for selecting the TYPE to choose (ie normal enum) - - [x] one for setting the VALUE inside that - - -- [x] vecs => (not vec2, vec3 etc) more complex UI to add items in a list - - [x] generate contained CollectionGroup - - [x] CollectionProperty => type = the above -- [x] find ways to "collapse" the different levels of nested data of structs/tupples into a single custom property (ideally on the fly, but we can do without) - -- [x] for single tupple components that represent a single unit type, re_use the base type's UIPropertyGroup instead of creating specific ones (ie TuppleTestF32_ui...) => will not work, would cause overriden "update callback" -- [x] pre_generate default values/values for each main type - -- [x] fix issues with vec2 etc not having the correct number of items -- [x] fix bad defaults in ui group -- [x] fix object enums handling on updates (??) -- [x] fix issues with lambads in loops - -- [x] object enum should be (params) - ie *Collider: - * Cuboid(Vec3) - * Sphere(radius) -- [x] deal with enums variants that do not have any data: ex { - "long_name": "Mesh" - } - -- [x] remove / change use of ComponentDefinitionsList - - when filling the list, use the long_name as index ie items.append((str(index), item.name, item.long_name)) => items.append((item.long_name, item.name, item.long_name)) -- [x] when removing a component, reset the value of the attribute in the property group (or not ? could be a feature) -- [x] deal correctly with fields of types that are NOT in the schema.json (for ex PlayingAnimation in AnimationPlayer) -- [ ] deal correctly with complex types - CascadeShadowConfig: has an array/list - ClusterConfig: one of the enum variants is an object -- [ ] possibly allow Color to be an enum as it should be ? -- [x] for sub items , the update functions "Name" should be the one of the root object -- [x] fix copy & pasting - - it actually works, but the value of the custom property are not copied back to the UI, need to implement property_group_value_from_custom_property_value -- [ ] we need a notion of "root propertyGroup" =? -- [x] notify user of missing entries in schema (ie , unregistered data types) -- [x] clarify propgroup_ui vs named nested fields -- [x] fix basic enums handling -- [x] add a list of not found components to the registry, add to them on the fly -- [x] add configuration panel (open the first time, closed on further user once configured) - -- [x] add limits to ixxx types vs utypes -- [x] only display the "generate components xx" when relevant ie: - - go through list of custom properties in current object - - if one does not have metadata and / or propgroup: - break - -- [x] remove custom property of disabled component ? => NOpe, as we need custom properties to iterate over -- [x] what to do with components with n/a fields ? perhaps disable the component ? add a "invalid" field to meta ? -- [x] format output as correct RON - - [x] fix issue with empty strings -- [x] change custom property => propGroup to convert RON => Json first => obsolete -- [x] cleanup process_lists - -- [x] fix issues with enum variants with only a long_name - -- [x] display single item enums inline, others in a seperate row - -- [x] add button to "apply all" (in configuration), to apply/update all custom properties to ALL objects where relevant -- [x] add button to "apply to current" to do the same with current -- [x] add warning sign to the above - -- [x] what about metadata ? -- [x] only upgrade custom properties to metadata when asked/relevant -- [x] implement move list up/down -- [ ] change property_group_value_from_custom_property_value => just disregard it for now, its point is very limited (helping people with old custom properties by attempting to generate real values) - and give the change to a real ron format, it is too limiting -- [x] fix reload registry clearing list of missing types -- [x] clean up metadata module, a lot of repeated code -- [x] some fields when original is 0 or 0.0 are not copyable ? (seems like a bad boolean check ) -- [x] fix issues with object variants in enums (see clusterconfig) - - -- perhaps directly export default values within the schema.json ? - - for most types , it is straighforward, but others, not so much: like the default color in Bevy , etc - -- [x] change default schema.json to registry.json -- [x] pasted components do not get updated value in custom_property -- [x] finish documentation -- [x] add storage of registry path - - [x] save after setting the data (browse for) - - [x] load after each reload ? - -# Additional - - [x] check if output "string" in custom properties are correct - - - gltf_auto_export - - [x] add support for "enabled" flag - - [ ] add special components - - "AutoExport" => Needed - - "Dynamic" ? naah wait that should be exported by the Bevy side - - [x] filter out Components_meta ?? - - [x] add legacy mode to the persisted parameters - - - bevy_gltf_components: - - [x] first release patch for current issues - - [x] make configurable - - [x] add "compatibility mode" and deprecation warnings for the current hack-ish conversion of fake ron - - [x] update docs to show we need to use ComponentsFromGltfPlugin::default - - - bevy_gltf_blueprints - - [x] update dependency - - [x] update version - - [x] add ability to set legacy mode for bevy_gltf_components ? - - - [x] release all versions - - [x] update main documentation, add compatibility version grid - - -## Phase 2 - -- [x] fix handling of long component names - - [x] fix nesting level handling issue for new system : ie basic component DOES NOT work, but nestedLevel2 does - - add goddam tests ! - - [ ] verify some weird prop => custom property values (Calculated Clip for example) - -- [x] fix "reload registry" not clearing all previous data (reloading registry does not seem to account for added/removed components in the registry ) -- add file watcher for registry - - [x] have the watcher work as expected - - [ ] add handling of removed registry file - - [ ] clear & reset handler when the file browser for the registry is used -- [ ] re-enable watcher - -- tests - clear && pytest -svv --blender-executable /blender/blender-4.0.2-linux-x64/blender - - - [x] load registry - - just check list of components vs lists in registry - - [x] try adding all components - - [x] select an object - - [x] call the add_component operator - - - [x] change params - - use field names + component definitions to set values - - [x] find a way to shuffle params of ALL components based on a reliable, repeatable seed - - - [x] test propgroup values => custom property values - - [x] test custom property value => propgroup value - - - check if all went well - - - [x] fix issues with incorect custom_property generation - - [x] fix issue with object variants for enums - - - [ ] add handling for core::ops::Range & other ranges - - [x] add handling for alloc::borrow::Cow - - [x] add handling of isize - - - [x] indirection level - - currently - - short_name +_"ui => direct lookup - - problem : max 64 chars for propertyGroupNames - - possible solution - - propertyGroupName storage: simple , incremented INT (call it propGroupId for ex) - - lookup shortName => propGroupId - - - do a first pass, by replacing manual propGroupNames creation with a function - - in a second pass, replace the innards - -- add button to regenerate cutom prop values from custom properties (allows us to sidestep any future issues with internals changing) - - [x] fix lists - - [x] fix enums (see Clusterconfig) - - [x] need an example with one tupple one struct - - [x] projection - - [x] additionalmassproperties - - [x] fix tupleStructs (see TupleVecF32F32) => always the same problem of having us pre-parse data without knowing what we have inside - - find a way to only split by level 0 (highest level) nesting "," seperators, ignoring any level of nesting until we dig one level deeper - - solve nesting level use issues - -- [x] remove metadata when deleting components -- [x] add try catch around custom_prop => propGroup -- [x] enhance the BLENVY_OT_component_from_custom_property to use the new system to actually generate the stuff - -- coherence in operators: - - component_name vs component_type - - [x] delete => remove - -- [x] clean up reloading of registry settings -- [x] clean up file watcher - - -========================================= -Restructuring of storage of components -- [x] marking of invalid root propgroups/components should be based on long name -- [x] overhaul & check each prop group type's use of short names => long names - - [x] lists -- [x] property_name = short_name in process enum: will likely require to use another indirection helper to keep the propery names short - -- [x] in conversions from propgroups - component_name = definition["short_name"] -- [ ] fix is_component_valid that is used in gltf_auto_export -- [x] update all tests - -- Hashmap Support - - [x] fix parsing of keys's type either on Bevy side (prefered) or on the Blender side - - [x] fix weird issue with missing "0" property when adding new entry in empty hashmap => happens only if the values for the "setter" have never been set - - [ ] handle missing types in registry for keys & values - -- [ ] Add correct upgrade handling from individual component to bevy_components \ No newline at end of file diff --git a/tools/blenvy/add_ons/auto_export/__init__.py b/tools/blenvy/add_ons/auto_export/__init__.py index 96f0824..6cf2318 100644 --- a/tools/blenvy/add_ons/auto_export/__init__.py +++ b/tools/blenvy/add_ons/auto_export/__init__.py @@ -28,7 +28,7 @@ def gltf_post_export_callback(data): gltf_settings_backup = tracker.gltf_settings_backup gltf_filepath = data["gltf_filepath"] gltf_export_id = data['gltf_export_id'] - if gltf_export_id == "gltf_auto_export": + if gltf_export_id == "blenvy": # some more absurdity: apparently the file is not QUITE done when the export callback is called, so we have to introduce this timer to remove the temporary file correctly tracker.dummy_file_path = gltf_filepath try: diff --git a/tools/blenvy/add_ons/auto_export/common/to_remove_later.py b/tools/blenvy/add_ons/auto_export/common/to_remove_later.py deleted file mode 100644 index 4357aae..0000000 --- a/tools/blenvy/add_ons/auto_export/common/to_remove_later.py +++ /dev/null @@ -1,402 +0,0 @@ -bl_info = { - "name": "gltf_auto_export", - "author": "kaosigh", - "version": (0, 10, 0), - "blender": (3, 4, 0), - "location": "File > Import-Export", - "description": "glTF/glb auto-export", - "warning": "", - "wiki_url": "https://github.com/kaosat-dev/Blender_bevy_components_workflow", - "tracker_url": "https://github.com/kaosat-dev/Blender_bevy_components_workflow/issues/new", - "category": "Import-Export" -} - -import bpy -from bpy.props import (BoolProperty, - IntProperty, - StringProperty, - EnumProperty, - CollectionProperty - ) - - -# glTF extensions are named following a convention with known prefixes. -# See: https://github.com/KhronosGroup/glTF/tree/main/extensions#about-gltf-extensions -# also: https://github.com/KhronosGroup/glTF/blob/main/extensions/Prefixes.md -glTF_extension_name = "EXT_auto_export" - -# Support for an extension is "required" if a typical glTF viewer cannot be expected -# to load a given model without understanding the contents of the extension. -# For example, a compression scheme or new image format (with no fallback included) -# would be "required", but physics metadata or app-specific settings could be optional. -extension_is_required = False -from io_scene_gltf2 import (GLTF_PT_export_main, GLTF_PT_export_include) - -class ExampleExtensionProperties(bpy.types.PropertyGroup): - enabled: bpy.props.BoolProperty( - name=bl_info["name"], - description='Include this extension in the exported glTF file.', - default=True - ) - - auto_export_main_scene_name: StringProperty( - name='Main scene', - description='The name of the main scene/level/world to auto export', - default='Scene' - ) - auto_export_output_folder: StringProperty( - name='Export folder (relative)', - description='The root folder for all exports(relative to current file) Defaults to current folder', - default='' - ) - auto_export_library_scene_name: StringProperty( - name='Library scene', - description='The name of the library scene to auto export', - default='Library' - ) - # scene components - auto_export_scene_settings: BoolProperty( - name='Export scene settings', - description='Export scene settings ie AmbientLighting, Bloom, AO etc', - default=False - ) - - # blueprint settings - auto_export_blueprints: BoolProperty( - name='Export Blueprints', - description='Replaces collection instances with an Empty with a BlueprintInfo custom property', - default=True - ) - auto_export_blueprints_path: StringProperty( - name='Blueprints path', - description='path to export the blueprints to (relative to the Export folder)', - default='library' - ) - - auto_export_materials_library: BoolProperty( - name='Export materials library', - description='remove materials from blueprints and use the material library instead', - default=False - ) - auto_export_materials_path: StringProperty( - name='Materials path', - description='path to export the materials libraries to (relative to the root folder)', - default='materials' - ) - -def register(): - bpy.utils.register_class(ExampleExtensionProperties) - bpy.types.Scene.ExampleExtensionProperties = bpy.props.PointerProperty(type=ExampleExtensionProperties) - -def register_panel(): - # Register the panel on demand, we need to be sure to only register it once - # This is necessary because the panel is a child of the extensions panel, - # which may not be registered when we try to register this extension - try: - bpy.utils.register_class(GLTF_PT_UserExtensionPanel) - except Exception: - pass - - # If the glTF exporter is disabled, we need to unregister the extension panel - # Just return a function to the exporter so it can unregister the panel - return unregister_panel - - -def unregister_panel(): - # Since panel is registered on demand, it is possible it is not registered - try: - bpy.utils.unregister_class(GLTF_PT_UserExtensionPanel) - except Exception: - pass - - -def unregister(): - unregister_panel() - bpy.utils.unregister_class(ExampleExtensionProperties) - del bpy.types.Scene.ExampleExtensionProperties - -class GLTF_PT_UserExtensionPanel(bpy.types.Panel): - - bl_space_type = 'FILE_BROWSER' - bl_region_type = 'TOOL_PROPS' - bl_label = "Enabled" - bl_parent_id = "GLTF_PT_export_user_extensions" - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, context): - sfile = context.space_data - operator = sfile.active_operator - return operator.bl_idname == "EXPORT_SCENE_OT_gltf" - - def draw_header(self, context): - props = bpy.context.scene.ExampleExtensionProperties - self.layout.prop(props, 'enabled') - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False # No animation. - - props = bpy.context.scene.ExampleExtensionProperties - layout.active = props.enabled - - props = bpy.context.scene.ExampleExtensionProperties - for bla in props.__annotations__: - layout.prop(props, bla) - - -class glTF2ExportUserExtension: - - def __init__(self): - # We need to wait until we create the gltf2UserExtension to import the gltf2 modules - # Otherwise, it may fail because the gltf2 may not be loaded yet - from io_scene_gltf2.io.com.gltf2_io_extensions import Extension - self.Extension = Extension - self.properties = bpy.context.scene.ExampleExtensionProperties - - def gather_node_hook(self, gltf2_object, blender_object, gltf_export_settings): - if self.properties.enabled: - if gltf2_object.extensions is None: - gltf2_object.extensions = {} - print("bla bla") - gltf2_object.extensions[glTF_extension_name] = self.Extension( - name=glTF_extension_name, - extension={"auto_export_blueprints": self.properties.auto_export_blueprints}, - required=extension_is_required - ) - - -def did_export_parameters_change(current_params, previous_params): - set1 = set(previous_params.items()) - set2 = set(current_params.items()) - difference = dict(set1 ^ set2) - - changed_param_names = list(set(difference.keys())- set(AutoExportGltfPreferenceNames)) - changed_parameters = len(changed_param_names) > 0 - return changed_parameters - -# original in export_blueprints => export_collections - # The part below is not necessary NORMALLY , but blender crashes in the "normal" case when using bpy.context.temp_override, - #if relevant we replace sub collections instances with placeholders too - # this is not needed if a collection/blueprint does not have sub blueprints or sub collections - collection_in_blueprint_hierarchy = collection_name in blueprint_hierarchy and len(blueprint_hierarchy[collection_name]) > 0 - collection_has_child_collections = len(bpy.data.collections[collection_name].children) > 0 - #if collection_in_blueprint_hierarchy or collection_has_child_collections: - - - - """else: - print("standard export") - # set active scene to be the library scene - original_scene = bpy.context.window.scene - bpy.context.window.scene = library_scene - with bpy.context.temp_override(scene=library_scene): - print("active scene", bpy.context.scene) - export_gltf(gltf_output_path, gltf_export_settings) - bpy.context.window.scene = original_scene""" - -""" - blueprint_template = object['Template'] if 'Template' in object else False - if blueprint_template and parent_empty is None: # ONLY WORKS AT ROOT LEVEL - print("BLUEPRINT TEMPLATE", blueprint_template, destination_collection, parent_empty) - for object in source_collection.objects: - if object.type == 'EMPTY' and object.name.endswith("components"): - original_collection = bpy.data.collections[collection_name] - components_holder = object - print("WE CAN INJECT into", object, "data from", original_collection) - - # now we look for components inside the collection - components = {} - for object in original_collection.objects: - if object.type == 'EMPTY' and object.name.endswith("components"): - for component_name in object.keys(): - if component_name not in '_RNA_UI': - print( component_name , "-" , object[component_name] ) - components[component_name] = object[component_name] - - # copy template components into target object - for key in components: - print("copying ", key,"to", components_holder) - if not key in components_holder: - components_holder[key] = components[key] - """ - -# potentially useful alternative -def duplicate_object2(object, original_name): - print("copy object", object) - - with bpy.context.temp_override(object=object, active_object = object): - bpy.ops.object.duplicate(linked=False) - new_obj = bpy.context.active_object - - print("new obj", new_obj, "bpy.context.view_layer", bpy.context.view_layer.objects) - for obj in bpy.context.view_layer.objects: - print("obj", obj) - bpy.context.view_layer.update() - new_obj.name = original_name - - if object.animation_data: - print("OJECT ANIMATION") - new_obj.animation_data.action = object.animation_data.action.copy() - - return new_obj - - - - - - if active_operator: - # print("Operator", active_operator.bl_label, active_operator.bl_idname, "bla", bpy.context.window_manager.gltf_exporter_running) - if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf" : #and not bpy.context.window_manager.gltf_exporter_running: - # we force saving params - active_operator.will_save_settings = True - if active_operator.bl_idname == "EXPORT_SCENES_OT_auto_gltf": - # we force saving params - active_operator.will_save_settings = True - - - """ - print("matching") - try: - bpy.app.timers.unregister(cls.gltf_exporter_handler) - except:pass - bpy.app.timers.register(cls.gltf_exporter_handler, first_interval=3) - # we backup any existing gltf export settings, if there where any - scene = bpy.context.scene - if "glTF2ExportSettings" in scene: - existing_setting = scene["glTF2ExportSettings"] - cls.existing_gltf_settings = existing_setting - bpy.context.window_manager.gltf_exporter_running = True - - - else: - if bpy.context.window_manager.gltf_exporter_running: - bpy.context.window_manager.gltf_exporter_running = False""" - - - """@classmethod - def gltf_exporter_handler(cls): - # FOr some reason, the active operator here is always None, so using a workaround - # active_operator = bpy.context.active_operator - print("here", bpy.context.window_manager.gltf_exporter_running) - - if bpy.context.window_manager.gltf_exporter_running: - try: - dummy_file_path = "/home/ckaos/projects/bevy/Blender_bevy_components_worklflow/testing/bevy_example/assets/dummy.glb" - - import os - if os.path.exists(dummy_file_path): - print("dummy file exists, assuming it worked") - os.unlink(dummy_file_path) - - # get the parameters - scene = bpy.context.scene - if "glTF2ExportSettings" in scene: - settings = scene["glTF2ExportSettings"] - formatted_settings = dict(settings) - - gltf_export_settings = bpy.data.texts[".blenvy_gltf_settings"] if ".blenvy_gltf_settings" in bpy.data.texts else bpy.data.texts.new(".blenvy_gltf_settings") - - #check if params have changed - bpy.context.window_manager.gltf_settings_changed = sorted(json.loads(gltf_export_settings.as_string()).items()) != sorted(formatted_settings.items()) - - print("gltf NEW settings", formatted_settings, "OLD settings", gltf_export_settings, "CHANGED ?", bpy.context.window_manager.gltf_settings_changed) - - # now write new settings - gltf_export_settings.clear() - gltf_export_settings.write(json.dumps(formatted_settings)) - - - # now reset the original gltf_settings - if getattr(cls, "existing_gltf_settings", None) is not None: - print("resetting original gltf settings") - scene["glTF2ExportSettings"] = cls.existing_gltf_settings - else: - print("no pre_existing settings") - if "glTF2ExportSettings" in scene: - del scene["glTF2ExportSettings"] - cls.existing_gltf_settings = None - except:pass - bpy.context.window_manager.gltf_exporter_running = False - return None - - - else: - try: - bpy.app.timers.unregister(cls.gltf_exporter_handler) - except:pass - return None - return 1""" - - -def invoke_override(self, context, event): - settings = context.scene.get(self.scene_key) - self.will_save_settings = False - if settings: - try: - for (k, v) in settings.items(): - setattr(self, k, v) - self.will_save_settings = True - - # Update filter if user saved settings - if hasattr(self, 'export_format'): - self.filter_glob = '*.glb' if self.export_format == 'GLB' else '*.gltf' - - except (AttributeError, TypeError): - self.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings") - del context.scene[self.scene_key] - - import sys - preferences = bpy.context.preferences - for addon_name in preferences.addons.keys(): - try: - if hasattr(sys.modules[addon_name], 'glTF2ExportUserExtension') or hasattr(sys.modules[addon_name], 'glTF2ExportUserExtensions'): - pass #exporter_extension_panel_unregister_functors.append(sys.modules[addon_name].register_panel()) - except Exception: - pass - - # self.has_active_exporter_extensions = len(exporter_extension_panel_unregister_functors) > 0 - print("ovverride") - wm = context.window_manager - wm.fileselect_add(self) - return {'RUNNING_MODAL'} - - - -from io_scene_gltf2 import (ExportGLTF2, GLTF_PT_export_main, GLTF_PT_export_include) - - -from io_scene_gltf2 import (ExportGLTF2, GLTF_PT_export_main,ExportGLTF2_Base, GLTF_PT_export_include) -import io_scene_gltf2 as gltf_exporter_original -#import io_scene_gltf2.GLTF_PT_export_data_scene as GLTF_PT_export_data_scene_original -""" -class GLTF_PT_export_data(gltf_exporter_original.GLTF_PT_export_data): - bl_space_type = 'FILE_BROWSER' - bl_region_type = 'TOOL_PROPS' - bl_label = "Data" - bl_parent_id = "GLTF_PT_auto_export_gltf" - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, context): - sfile = context.space_data - operator = sfile.active_operator - - return operator.bl_idname == "EXPORT_SCENES_OT_auto_gltf" - -class GLTF_PT_export_data_scene(gltf_exporter_original.GLTF_PT_export_data_scene): - bl_space_type = 'FILE_BROWSER' - bl_region_type = 'TOOL_PROPS' - bl_label = "Scene Graph" - bl_parent_id = "GLTF_PT_export_data" - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, context): - sfile = context.space_data - operator = sfile.active_operator - return operator.bl_idname == "EXPORT_SCENES_OT_auto_gltf" - - def draw(self, context): - return super().draw(context)""" \ No newline at end of file diff --git a/tools/blenvy/add_ons/auto_export/common/tracker.py b/tools/blenvy/add_ons/auto_export/common/tracker.py index 66964eb..aa5cf20 100644 --- a/tools/blenvy/add_ons/auto_export/common/tracker.py +++ b/tools/blenvy/add_ons/auto_export/common/tracker.py @@ -86,7 +86,7 @@ class AutoExportTracker(PropertyGroup): active_operator = getattr(bpy.context, 'active_operator' , None) if active_operator is not None: #print("Operator", active_operator.bl_label, active_operator.bl_idname) - if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf" and active_operator.gltf_export_id == "gltf_auto_export": + if active_operator.bl_idname == "EXPORT_SCENE_OT_gltf" and active_operator.gltf_export_id == "blenvy": # we backup any existing gltf export settings, if there were any scene = bpy.context.scene if "glTF2ExportSettings" in scene: diff --git a/tools/blenvy/add_ons/auto_export/ui.py b/tools/blenvy/add_ons/auto_export/ui.py index 8ab01ba..34f0585 100644 --- a/tools/blenvy/add_ons/auto_export/ui.py +++ b/tools/blenvy/add_ons/auto_export/ui.py @@ -21,7 +21,7 @@ def draw_settings_ui(layout, auto_export_settings): op.use_active_collection_with_nested=True op.use_active_scene = True op.filepath="____dummy____" - op.gltf_export_id = "gltf_auto_export" # we specify that we are in a special case + op.gltf_export_id = "blenvy" # we specify that we are in a special case section.prop(auto_export_settings, "export_scene_settings") diff --git a/tools/blenvy/add_ons/bevy_components/components/helpers.py b/tools/blenvy/add_ons/bevy_components/components/helpers.py deleted file mode 100644 index 4a45b62..0000000 --- a/tools/blenvy/add_ons/bevy_components/components/helpers.py +++ /dev/null @@ -1,6 +0,0 @@ -import rna_prop_ui - -# fake way to make our operator's changes be visible to the change/depsgraph update handler in gltf_auto_export -def ping_depsgraph_update(object): - rna_prop_ui.rna_idprop_ui_create(object, "________temp", default=0) - rna_prop_ui.rna_idprop_ui_prop_clear(object, "________temp") \ No newline at end of file diff --git a/tools/blenvy/core/ping_depsgraph_update.py b/tools/blenvy/core/ping_depsgraph_update.py deleted file mode 100644 index 55527b2..0000000 --- a/tools/blenvy/core/ping_depsgraph_update.py +++ /dev/null @@ -1,10 +0,0 @@ -import bpy -import rna_prop_ui - -# fake way to make our operator's changes be visible to the change/depsgraph update handler in gltf_auto_export -def ping_depsgraph_update(object=None): - if object == None: - object = bpy.data.scenes[0] - rna_prop_ui.rna_idprop_ui_create(object, "________temp", default=0) - rna_prop_ui.rna_idprop_ui_prop_clear(object, "________temp") - return None \ No newline at end of file diff --git a/tools/blenvy/core/ui/ui.py b/tools/blenvy/core/ui/ui.py index f50d73b..ac72cf3 100644 --- a/tools/blenvy/core/ui/ui.py +++ b/tools/blenvy/core/ui/ui.py @@ -26,7 +26,7 @@ class BLENVY_PT_SidePanel(bpy.types.Panel): bl_label = "" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' - bl_category = "Bevy" + bl_category = "Blenvy" #bl_context = "objectmode" def draw_header(self, context):