diff --git a/crates/blenvy/Cargo.toml b/crates/blenvy/Cargo.toml index adb59db..626589e 100644 --- a/crates/blenvy/Cargo.toml +++ b/crates/blenvy/Cargo.toml @@ -18,6 +18,19 @@ bevy = { version = "0.14.0-rc.3", default-features = false, features = ["bevy_as serde = "1.0.188" ron = "0.8.1" serde_json = "1.0.108" +gltf = { version = "1.4.0", default-features = false, features = [ + "KHR_lights_punctual", + "KHR_materials_transmission", + "KHR_materials_ior", + "KHR_materials_volume", + "KHR_materials_unlit", + "KHR_materials_emissive_strength", + "KHR_texture_transform", + "extras", + "extensions", + "names", + "utils", +] } [dev-dependencies] diff --git a/crates/blenvy/src/components/blender_settings/lighting.rs b/crates/blenvy/src/components/blender_settings/lighting.rs index 622c0e1..bfd9f0c 100644 --- a/crates/blenvy/src/components/blender_settings/lighting.rs +++ b/crates/blenvy/src/components/blender_settings/lighting.rs @@ -1,5 +1,7 @@ +use bevy::core_pipeline::tonemapping::Tonemapping; use bevy::pbr::DirectionalLightShadowMap; use bevy::prelude::*; +use bevy::render::view::{ColorGrading, ColorGradingGlobal, ColorGradingSection}; use crate::GltfComponentsSet; @@ -7,9 +9,12 @@ pub(crate) fn plugin(app: &mut App) { app.register_type::() .register_type::() .register_type::() + .register_type::() + .register_type::() + .add_systems( Update, - (process_lights, process_shadowmap, process_background_shader) + (process_lights, process_shadowmap, process_background_shader, process_tonemapping, process_colorgrading) .after(GltfComponentsSet::Injection), ); } @@ -40,6 +45,26 @@ pub struct BlenderShadowSettings { pub cascade_size: usize, } +/// Not all possible Blender ToneMappings are available in Bevy & vice versa +#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)] +#[reflect(Component)] +#[non_exhaustive] +pub enum BlenderToneMapping { + #[default] + None, + AgX, + Filmic +} + +#[derive(Component, Reflect, Default, Debug, PartialEq, Clone)] +#[reflect(Component)] +#[non_exhaustive] +pub struct BlenderColorGrading { + exposure: f32, + gamma: f32, +} + + fn process_lights( mut directional_lights: Query< (&mut DirectionalLight, Option<&BlenderLightShadows>), @@ -51,23 +76,17 @@ fn process_lights( for (mut light, blender_light_shadows) in directional_lights.iter_mut() { if let Some(blender_light_shadows) = blender_light_shadows { light.shadows_enabled = blender_light_shadows.enabled; - } else { - light.shadows_enabled = true; - } + } } for (mut light, blender_light_shadows) in spot_lights.iter_mut() { if let Some(blender_light_shadows) = blender_light_shadows { light.shadows_enabled = blender_light_shadows.enabled; - } else { - light.shadows_enabled = true; - } + } } for (mut light, blender_light_shadows) in point_lights.iter_mut() { if let Some(blender_light_shadows) = blender_light_shadows { light.shadows_enabled = blender_light_shadows.enabled; - } else { - light.shadows_enabled = true; } } } @@ -88,10 +107,76 @@ fn process_background_shader( mut commands: Commands, ) { for background_shader in background_shaders.iter() { + println!("HEYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY {:?}", background_shader.color); commands.insert_resource(AmbientLight { color: background_shader.color, // Just a guess, see brightness: background_shader.strength * 400.0, }); + commands.insert_resource(ClearColor(background_shader.color)); + } } + +// FIXME: this logic should not depend on if toneMapping or Cameras where added first +fn process_tonemapping( + tonemappings: Query<&BlenderToneMapping , Added>, + cameras: Query>, + mut commands: Commands, +){ + + for entity in cameras.iter(){ + for tone_mapping in tonemappings.iter(){ + match tone_mapping { + BlenderToneMapping::None => { + println!("TONEMAPPING NONE"); + commands.entity(entity).remove::(); + } + BlenderToneMapping::AgX => { + println!("TONEMAPPING Agx"); + commands.entity(entity).insert(Tonemapping::AgX); + } + BlenderToneMapping::Filmic => { + println!("TONEMAPPING Filmic"); + commands.entity(entity).insert(Tonemapping::BlenderFilmic); + } + } + } + } +} + +// FIXME: this logic should not depend on if toneMapping or Cameras where added first +fn process_colorgrading( + blender_colorgradings: Query<&BlenderColorGrading , Added>, + cameras: Query>, + mut commands: Commands, +){ + + for entity in cameras.iter(){ + for blender_colorgrading in blender_colorgradings.iter(){ + println!("COLOR GRADING"); + commands.entity(entity).insert( + ColorGrading{ + global: ColorGradingGlobal{ + exposure: blender_colorgrading.exposure, + ..Default::default() + }, + shadows: ColorGradingSection{ + gamma: blender_colorgrading.gamma, + ..Default::default() + }, + midtones: ColorGradingSection{ + gamma: blender_colorgrading.gamma, + ..Default::default() + }, + highlights: ColorGradingSection{ + gamma: blender_colorgrading.gamma, + ..Default::default() + }, + + ..Default::default() + } + ); + } + } +} \ No newline at end of file diff --git a/crates/blenvy/src/components/process_gltfs.rs b/crates/blenvy/src/components/process_gltfs.rs index 73bd6be..a566859 100644 --- a/crates/blenvy/src/components/process_gltfs.rs +++ b/crates/blenvy/src/components/process_gltfs.rs @@ -16,14 +16,14 @@ use bevy::{ use crate::{ronstring_to_reflect_component, GltfProcessed}; // , mut entity_components: HashMap, TypeRegistration)>> -fn find_entity_components(entity: Entity, name: &Name, parent: &Parent, reflect_components: Vec<(Box, TypeRegistration)>, entity_components: &HashMap, TypeRegistration)>>) -> (Entity, Vec<(Box, TypeRegistration)>){ +fn find_entity_components(entity: Entity, name: &Name, parent: Option<&Parent>, reflect_components: Vec<(Box, TypeRegistration)>, entity_components: &HashMap, TypeRegistration)>>) -> (Entity, Vec<(Box, TypeRegistration)>){ // we assign the components specified /xxx_components objects to their parent node let mut target_entity = entity; // if the node contains "components" or ends with "_pa" (ie add to parent), the components will not be added to the entity itself but to its parent // this is mostly used for Blender collections - if name.as_str().contains("components") || name.as_str().ends_with("_pa") { + if parent.is_some() && (name.as_str().contains("components") || name.as_str().ends_with("_pa")) { debug!("adding components to parent"); - target_entity = parent.get(); + target_entity = parent.expect("the target entity had a parent ").get(); } debug!("adding to {:?}", target_entity); @@ -50,12 +50,10 @@ fn find_entity_components(entity: Entity, name: &Name, parent: &Parent, reflect_ /// main function: injects components into each entity in gltf files that have `gltf_extras`, using reflection pub fn add_components_from_gltf_extras(world: &mut World) { - let mut extras = - world.query_filtered::<(Entity, &Name, &GltfExtras, &Parent), (Added, Without)>(); - - let mut scene_extras = world.query_filtered::<(Entity, &Name, &GltfSceneExtras, &Parent), (Added, Without)>(); - let mut mesh_extras = world.query_filtered::<(Entity, &Name, &GltfMeshExtras, &Parent), (Added, Without)>(); - let mut material_extras = world.query_filtered::<(Entity, &Name, &GltfMaterialExtras, &Parent), (Added, Without)>(); + let mut extras = world.query_filtered::<(Entity, &Name, &GltfExtras, Option<&Parent>), (Added, Without)>(); + let mut scene_extras = world.query_filtered::<(Entity, &Name, &GltfSceneExtras, Option<&Parent>), (Added, Without)>(); + let mut mesh_extras = world.query_filtered::<(Entity, &Name, &GltfMeshExtras, Option<&Parent>), (Added, Without)>(); + let mut material_extras = world.query_filtered::<(Entity, &Name, &GltfMaterialExtras, Option<&Parent>), (Added, Without)>(); let mut entity_components: HashMap, TypeRegistration)>> = HashMap::new(); @@ -63,6 +61,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) { // let gltf_components_config = world.resource::(); for (entity, name, extra, parent) in extras.iter(world) { + println!("GLTF EXTRA !!!!"); debug!( "Name: {}, entity {:?}, parent: {:?}, extras {:?}", name, entity, parent, extra @@ -78,6 +77,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) { for (entity, name, extra, parent) in scene_extras.iter(world) { + println!("GLTF SCENE EXTRA !!!!"); + debug!( "Name: {}, entity {:?}, parent: {:?}, scene_extras {:?}", name, entity, parent, extra @@ -92,6 +93,8 @@ pub fn add_components_from_gltf_extras(world: &mut World) { } for (entity, name, extra, parent) in mesh_extras.iter(world) { + println!("GLTF MESH EXTRA !!!!"); + debug!( "Name: {}, entity {:?}, parent: {:?}, mesh_extras {:?}", name, entity, parent, extra diff --git a/crates/blenvy/src/components/ronstring_to_reflect_component.rs b/crates/blenvy/src/components/ronstring_to_reflect_component.rs index 5221431..eb1ef32 100644 --- a/crates/blenvy/src/components/ronstring_to_reflect_component.rs +++ b/crates/blenvy/src/components/ronstring_to_reflect_component.rs @@ -1,5 +1,5 @@ use bevy::log::{debug, warn}; -use bevy::reflect::serde::ReflectDeserializer; +use bevy::reflect::serde::{ReflectDeserializer, ReflectSerializer}; use bevy::reflect::{Reflect, TypeRegistration, TypeRegistry}; use bevy::utils::HashMap; use ron::Value; @@ -58,12 +58,16 @@ fn components_string_to_components( parsed_value ); + /* // usefull to determine what an entity looks like Serialized - /*let test_struct = CameraRenderGraph::new("name"); + let test_struct = Color::Srgba(Srgba { red: 0.2, green: 0.2, blue: 0.2, alpha: 0.2 }); + //CameraRenderGraph::new("name"); let serializer = ReflectSerializer::new(&test_struct, &type_registry); let serialized = ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap(); - println!("serialized Component {}", serialized);*/ + println!("serialized Component {}", serialized); + */ + debug!("component data ron string {}", ron_string); let mut deserializer = ron::Deserializer::from_str(ron_string.as_str()) diff --git a/tools/blenvy/TODO.md b/tools/blenvy/TODO.md index bd6750b..8617551 100644 --- a/tools/blenvy/TODO.md +++ b/tools/blenvy/TODO.md @@ -15,7 +15,7 @@ Auto export - [x] main/ library scene names - [x] paths -- [ ] Data storage for custom properties: +- [x] Data storage for custom properties: - for scenes (main scenes) - at scene level - for blueprints @@ -59,12 +59,11 @@ Components: - [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 - - Hashmap Support + - [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 - [ ] handle missing types in registry for keys & values - [x] adding a hashmap nukes every existing component ?? - - [x] Add correct upgrade handling from individual component to bevy_components - [x] Settings handling: - [x] move saveable settings out to a settings file @@ -77,8 +76,6 @@ Components: - perhaps just add a display list of all NON component custom properties, so the user can find them easilly ? - [x] status "unregistered" is often false and misleading -> see in registry ui "for custom_property in object.keys():" - - - [x] overhaul / improve the component selector (with built in searching, etc) - [x] remove select_component_name_to_replace - [x] display of invalid components is not working ? @@ -87,7 +84,6 @@ Components: - BLENVY_OT_component_list_add_item - BLENVY_OT_component_list_remove_item - BLENVY_OT_component_list_select_item: merge it into the rest of the actions - - [x] clearing invalid flag after a registry change does not work correctly (ie the ui still says the component is invalid) - [x] should reset ALL "invalid" flags IF they have the matching data - [x] registry auto reload not working ? @@ -96,7 +92,6 @@ Components: - now switched to tiger_hash - [x] add warning about hash colision (not much we can/ could do if it is the case ?) - [x] double check weird collisions AND/OR reuse existing if applicable - - [x] annoying default path for registry, should be relative to the assets path @@ -127,54 +122,55 @@ General issues: - [ ] add handling of errors when trying to load settings -- [ ] force overwrite of settings files instead of partial updates ? -- [ ] add tests for disabled components - [x] fix auto export workflow -- [ ] should we write the previous _xxx data only AFTER a sucessfull export only ? - [x] add hashing of modifiers/ geometry nodes in serialize scene - [x] add ability to FORCE export specific blueprints & levels -- [ ] undo after a save removes any saved "serialized scene" data ? DIG into this -- [ ] handle scene renames between saves (breaks diffing) - [x] change scene selector to work on actual scenes aka to deal with renamed scenes - [x] remove get_main_and_library_scenes as it should not be needed anymore - [x] fix asset file selection - [x] change "assets" tab to "levels"/worlds tab & modify UI accordingly -- [ ] add option to 'split out' meshes from blueprints ? - - [ ] ie considering meshletts etc , it would make sense to keep blueprints seperate from purely mesh gltfs -- [ ] remove local assets, useless - +- [x] remove local assets, useless - [x] remove 'export_marked_assets' it should be a default setting - [x] disable/ hide asset editing ui for external assets -- [ ] inject_export_path_into_internal_blueprints should be called on every asset/blueprint scan !! Not just on export - [x] fix level asets UI +- [x] remove BlueprintsList & replace is with assets list +- [x] switch to bevy 0.14 rc2 +- [x] trigger events when assets are loaded, blueprints are spawned & co +- [x] overall cleanup + - [x] object.add_bevy_component => blenvy.component_add + + +- [ ] inject_export_path_into_internal_blueprints should be called on every asset/blueprint scan !! Not just on export +- [ ] undo after a save removes any saved "serialized scene" data ? DIG into this +- [ ] handle scene renames between saves (breaks diffing) => very hard to achieve +- [ ] force overwrite of settings files instead of partial updates ? +- [ ] add tests for disabled components +- [ ] should we write the previous _xxx data only AFTER a sucessfull export only ? +- [ ] add option to 'split out' meshes from blueprints ? + - [ ] ie considering meshletts etc , it would make sense to keep blueprints seperate from purely mesh gltfs - [ ] persist exported materials path in blueprints so that it can be read from library file users - [ ] just like "export_path" write it into each blueprint's collection - [ ] scan for used materials per blueprint ! - [ ] for scenes, scan for used materials of all non instance objects (TODO: what about overrides ?) - -- [x] remove BlueprintsList & replace is with assets list -- [ ] update main docs - - [ ] rename project to Blenvy - - [ ] replace all references to the old 2 add-ons with those to Blenvy -- [ ] rename repo to "Blenvy" -- [x] switch to bevy 0.14 rc2 - [ ] find a solution for the new color handling - [ ] add back lighting_components - [ ] check if scene components are being deleted through our scene re-orgs in the spawn post process -- [x] trigger events when assets are loaded, blueprints are spawned & co - [ ] should "blueprint spawned" only be triggered after all its sub blueprints have spawned ? - [ ] simplify testing example: - [x] remove use of rapier physics (or even the whole common boilerplate ?) - [ ] remove/replace bevy editor pls with some native ui to display hierarchies -- [ ] do a deprecation release of all bevy_gltf_xxx crates to point at the new Blenvy crate +- [ ] try out hot reloading - [ ] simplify examples: - [ ] a full fledged demo (including physics & co) - [ ] other examples without interactions or physics +- [ ] update main docs + - [ ] rename project to Blenvy + - [ ] replace all references to the old 2 add-ons with those to Blenvy +- [ ] rename repo to "Blenvy" +- [ ] do a deprecation release of all bevy_gltf_xxx crates to point at the new Blenvy crate +- [ ] hidden objects/collections not respected at export !!! -- [x] overall cleanup - - [x] object.add_bevy_component => blenvy.component_add - 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 \ No newline at end of file diff --git a/tools/blenvy/add_ons/auto_export/blueprints/export_blueprints.py b/tools/blenvy/add_ons/auto_export/blueprints/export_blueprints.py index 5ffa267..ca876ea 100644 --- a/tools/blenvy/add_ons/auto_export/blueprints/export_blueprints.py +++ b/tools/blenvy/add_ons/auto_export/blueprints/export_blueprints.py @@ -1,5 +1,7 @@ import os import bpy +from blenvy.assets.assets_scan import get_blueprint_asset_tree +from blenvy.assets.generate_asset_file import write_ron_assets_file from ..constants import TEMPSCENE_PREFIX from ..common.generate_temporary_scene_and_export import generate_temporary_scene_and_export, copy_hollowed_collection_into, clear_hollow_scene from ..common.export_gltf import generate_gltf_export_settings @@ -51,6 +53,9 @@ def export_blueprints(blueprints, settings, blueprints_data): tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=collection, temp_scene=temp_scene, **params) ) + #blueprint_asset_tree = get_blueprint_asset_tree(blueprint=blueprint, blueprints_data=blueprints_data, settings=settings) + #write_ron_assets_file(blueprint.name, blueprint_asset_tree, output_path_full = blueprints_path_full) + # reset active collection to the one we save before bpy.context.view_layer.active_layer_collection = active_collection diff --git a/tools/blenvy/add_ons/auto_export/common/generate_temporary_scene_and_export.py b/tools/blenvy/add_ons/auto_export/common/generate_temporary_scene_and_export.py index c33325a..df6a449 100644 --- a/tools/blenvy/add_ons/auto_export/common/generate_temporary_scene_and_export.py +++ b/tools/blenvy/add_ons/auto_export/common/generate_temporary_scene_and_export.py @@ -20,7 +20,7 @@ def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_out temp_root_collection = temp_scene.collection print("additional_dataAAAAAAAAAAAAAAAH", additional_data) - properties_black_list = ['user_assets', 'components_meta'] + properties_black_list = ['glTF2ExportSettings', 'user_assets', 'components_meta'] if additional_data is not None: # FIXME not a fan of having this here for entry in dict(additional_data): # we copy everything over except those on the black list diff --git a/tools/blenvy/add_ons/auto_export/levels/bevy_scene_components.py b/tools/blenvy/add_ons/auto_export/levels/bevy_scene_components.py index 9c7dfa8..8cced91 100644 --- a/tools/blenvy/add_ons/auto_export/levels/bevy_scene_components.py +++ b/tools/blenvy/add_ons/auto_export/levels/bevy_scene_components.py @@ -5,14 +5,12 @@ from blenvy.core.object_makers import make_empty # TODO: replace this with placing scene level custom properties once support for that has been added to bevy_gltf def upsert_scene_components(main_scenes): for scene in main_scenes: - """lighting_components_name = f"lighting_components_{scene.name}" - lighting_components = bpy.data.objects.get(lighting_components_name, None) - if not lighting_components: - root_collection = scene.collection - lighting_components = make_empty('lighting_components_'+scene.name, [0,0,0], [0,0,0], [0,0,0], root_collection)""" - - """if scene.world is not None: - lighting_components['BlenderBackgroundShader'] = ambient_color_to_component(scene.world)""" # FIXME add back + if scene.world is not None: + scene['BlenderBackgroundShader'] = ambient_color_to_component(scene.world) + print("FOOOOO WORLD", dir(scene.world)) + print("FOOOO scene", dir(scene)) + print("foooo", dir(scene.view_settings)) + print("GNAAA", scene.view_settings.view_transform) scene['BlenderShadowSettings'] = scene_shadows_to_component(scene) if scene.eevee.use_bloom: @@ -25,13 +23,24 @@ def upsert_scene_components(main_scenes): elif 'SSAOSettings' in scene: del scene['SSAOSettings'] + scene['BlenderToneMapping'] = scene_tonemapping_to_component(scene) + scene['BlenderColorGrading'] = scene_colorgrading_to_component(scene) + def remove_scene_components(main_scenes): pass - """for scene in main_scenes: - lighting_components_name = f"lighting_components_{scene.name}" - lighting_components = bpy.data.objects.get(lighting_components_name, None) - if lighting_components: - bpy.data.objects.remove(lighting_components, do_unlink=True)""" + +def scene_tonemapping_to_component(scene): + tone_mapping = scene.view_settings.view_transform + blender_to_bevy = { + 'NONE': '', + 'AgX': 'AgX', + 'Filmic': 'Filmic', + } + bevy_tone_mapping = blender_to_bevy[tone_mapping] if tone_mapping in blender_to_bevy else None + return bevy_tone_mapping + +def scene_colorgrading_to_component(scene): + return f"(exposure: {scene.view_settings.exposure}, gamma: {scene.view_settings.gamma})" def ambient_color_to_component(world): @@ -43,9 +52,8 @@ def ambient_color_to_component(world): except Exception as ex: print("failed to parse ambient color: Only background is supported") - if color is not None and strength is not None: - colorRgba = f"LinearRgba(red: {color[0]}, green: {color[1]}, blue: {color[2]}, alpha: {color[3]})" + colorRgba = f"LinearRgba((red: {color[0]}, green: {color[1]}, blue: {color[2]}, alpha: {color[3]}))" component = f"( color: {colorRgba}, strength: {strength})" return component return None @@ -62,4 +70,4 @@ def scene_bloom_to_component(scene): def scene_ao_to_component(scene): ssao = scene.eevee.use_gtao component= "SSAOSettings()" - return component \ No newline at end of file + return component diff --git a/tools/blenvy/add_ons/auto_export/levels/export_main_scenes.py b/tools/blenvy/add_ons/auto_export/levels/export_main_scenes.py index c76d74b..1308830 100644 --- a/tools/blenvy/add_ons/auto_export/levels/export_main_scenes.py +++ b/tools/blenvy/add_ons/auto_export/levels/export_main_scenes.py @@ -78,7 +78,7 @@ def export_main_scene(scene, settings, blueprints_data): materials_exported_path = os.path.join(materials_path, f"{materials_library_name}{export_gltf_extension}") material_assets = [{"name": materials_library_name, "path": materials_exported_path}] # we also add the material library as an asset - scene["BlenvyAssets"] = assets_to_fake_ron(all_assets + [{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + auto_assets + material_assets) + #scene["BlenvyAssets"] = assets_to_fake_ron(all_assets + [{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + auto_assets + material_assets) if export_separate_dynamic_and_static_objects: @@ -87,6 +87,7 @@ def export_main_scene(scene, settings, blueprints_data): generate_temporary_scene_and_export( settings, temp_scene_name=TEMPSCENE_PREFIX, + additional_data = scene, gltf_export_settings=gltf_export_settings, gltf_output_path=gltf_output_path, tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_static, settings=settings), @@ -98,6 +99,7 @@ def export_main_scene(scene, settings, blueprints_data): generate_temporary_scene_and_export( settings, temp_scene_name=TEMPSCENE_PREFIX, + additional_data = scene, gltf_export_settings=gltf_export_settings, gltf_output_path=gltf_output_path, tempScene_filler= lambda temp_collection: copy_hollowed_collection_into(scene.collection, temp_collection, blueprints_data=blueprints_data, filter=is_object_dynamic, settings=settings), diff --git a/tools/blenvy/add_ons/bevy_components/utils.py b/tools/blenvy/add_ons/bevy_components/utils.py index a4efbae..89b3688 100644 --- a/tools/blenvy/add_ons/bevy_components/utils.py +++ b/tools/blenvy/add_ons/bevy_components/utils.py @@ -75,7 +75,8 @@ def get_selected_item(context): for obj in bpy.context.selected_ids: pass#print(f"Selected: {obj.name} - {type(obj)}") selection = bpy.context.selected_ids[len(bpy.context.selected_ids) - 1] if len(bpy.context.selected_ids)>0 else None #next(iter(bpy.context.selected_ids), None) - print("selection", f"Selected: {selection.name} - {type(selection)}") + """if selection is not None: + print("selection", f"Selected: {selection.name} - {type(selection)}")""" #print("SELECTIONS", context.selected_objects) return selection diff --git a/tools/blenvy/assets/assets_scan.py b/tools/blenvy/assets/assets_scan.py index 0016656..9f41885 100644 --- a/tools/blenvy/assets/assets_scan.py +++ b/tools/blenvy/assets/assets_scan.py @@ -121,3 +121,26 @@ def get_main_scene_assets_tree(main_scene, blueprints_data, settings): added_asset.name = asset["name"] added_asset.path = asset["path"] return assets_list + +def get_blueprint_asset_tree(blueprint, blueprints_data, settings): + blueprints_path = getattr(settings, "blueprints_path") + export_gltf_extension = getattr(settings.auto_export, "export_gltf_extension", ".glb") + + assets_list = get_user_assets_as_list(blueprint.collection) + + for blueprint_name in blueprint.nested_blueprints: + sub_blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None) + if sub_blueprint is not None: + sub_blueprint_exported_path = None + if sub_blueprint.local: + sub_blueprint_exported_path = os.path.join(blueprints_path, f"{sub_blueprint.name}{export_gltf_extension}") + else: + # get the injected path of the external blueprints + sub_blueprint_exported_path = sub_blueprint.collection['export_path'] if 'export_path' in sub_blueprint.collection else None + + if sub_blueprint_exported_path is not None and not does_asset_exist(assets_list, sub_blueprint_exported_path): + assets_list.append({"name": sub_blueprint.name, "path": sub_blueprint_exported_path, "type": "MODEL", "generated": True, "internal": sub_blueprint.local, "parent": None}) + + assets_list += get_blueprint_assets_tree(sub_blueprint, blueprints_data, parent=sub_blueprint.name, settings=settings) + + return assets_list diff --git a/tools/blenvy/assets/generate_asset_file.py b/tools/blenvy/assets/generate_asset_file.py new file mode 100644 index 0000000..26e95b6 --- /dev/null +++ b/tools/blenvy/assets/generate_asset_file.py @@ -0,0 +1,28 @@ + + +def write_ron_assets_file(name, assets_hierarchy, internal_only=False, output_path_full="."): + # just for testing, this uses the format of bevy_asset_loader's asset files + ''' + ({ + "world":File (path: "models/StartLevel.glb"), + "level1":File (path: "models/Level1.glb"), + "level2":File (path: "models/Level2.glb"), + + "models": Folder ( + path: "models/library", + ), + "materials": Folder ( + path: "materials", + ), + }) + ''' + formated_assets = [] + for asset in assets_hierarchy: + if asset["internal"] or not internal_only: + formated_asset = f'\n "{asset["name"]}": File ( path: "{asset["path"]}" ),' + formated_assets.append(formated_asset) + + with open(f"{output_path_full}/{name}.assets.ron", "w") as assets_file: + assets_file.write("({") + assets_file.writelines(formated_assets) + assets_file.write("\n})") \ No newline at end of file diff --git a/tools/blenvy/assets/operators.py b/tools/blenvy/assets/operators.py index f0ecd50..2d1cc94 100644 --- a/tools/blenvy/assets/operators.py +++ b/tools/blenvy/assets/operators.py @@ -7,6 +7,7 @@ from bpy.props import (BoolProperty, StringProperty, EnumProperty) from .asset_helpers import does_asset_exist, get_user_assets, remove_asset, upsert_asset from .assets_scan import get_main_scene_assets_tree from ..core.path_helpers import absolute_path_from_blend_file +from .generate_asset_file import write_ron_assets_file class BLENVY_OT_assets_add(Operator): """Add asset""" @@ -172,32 +173,6 @@ class BLENVY_OT_assets_browse(Operator, ImportHelper): from types import SimpleNamespace -def write_ron_assets_file(level_name, assets_hierarchy, internal_only=False, levels_path_full="."): - # just for testing, this uses the format of bevy_asset_loader's asset files - ''' - ({ - "world":File (path: "models/StartLevel.glb"), - "level1":File (path: "models/Level1.glb"), - "level2":File (path: "models/Level2.glb"), - - "models": Folder ( - path: "models/library", - ), - "materials": Folder ( - path: "materials", - ), - }) - ''' - formated_assets = [] - for asset in assets_hierarchy: - if asset["internal"] or not internal_only: - bla = f'\n "{asset["name"]}": File ( path: "{asset["path"]}" ),' - formated_assets.append(bla) - with open(f"{levels_path_full}/{level_name}.assets.ron", "w") as assets_file: - assets_file.write("({") - assets_file.writelines(formated_assets) - assets_file.write("\n})") - class BLENVY_OT_assets_generate_files(Operator): """Test assets""" bl_idname = "blenvy.assets_generate_files" @@ -213,7 +188,7 @@ class BLENVY_OT_assets_generate_files(Operator): for scene in blenvy.main_scenes: assets_hierarchy = get_main_scene_assets_tree(scene, blueprints_data, settings) - scene["assets"] = json.dumps(assets_hierarchy) - write_ron_assets_file(scene.name, assets_hierarchy, internal_only = False, levels_path_full = blenvy.levels_path_full) + # scene["assets"] = json.dumps(assets_hierarchy) + write_ron_assets_file(scene.name, assets_hierarchy, internal_only = False, output_path_full = blenvy.levels_path_full) return {'FINISHED'}