feat(Blenvy):

* fixed handling of scene gltf_extras
 * fixed handling of colors for BlenderBackgroundShader
 * added scene tonemapping & scene colorgrading and handling on the Bevy side.
 * experimented with exporting ron asset files, updated & overhauled asset file generation, adapted
for blueprints
 * various cleanups
This commit is contained in:
kaosat.dev 2024-06-23 19:14:00 +02:00
parent ed5dfeb3cd
commit 4b1268f0a3
13 changed files with 240 additions and 97 deletions

View File

@ -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]

View File

@ -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::<BlenderBackgroundShader>()
.register_type::<BlenderShadowSettings>()
.register_type::<BlenderLightShadows>()
.register_type::<BlenderToneMapping>()
.register_type::<BlenderColorGrading>()
.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 <https://github.com/bevyengine/bevy/issues/12280>
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<BlenderToneMapping>>,
cameras: Query<Entity, With<Camera>>,
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::<Tonemapping>();
}
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<BlenderColorGrading>>,
cameras: Query<Entity, With<Camera>>,
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()
}
);
}
}
}

View File

@ -16,14 +16,14 @@ use bevy::{
use crate::{ronstring_to_reflect_component, GltfProcessed};
// , mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>
fn find_entity_components(entity: Entity, name: &Name, parent: &Parent, reflect_components: Vec<(Box<dyn Reflect>, TypeRegistration)>, entity_components: &HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>) -> (Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>){
fn find_entity_components(entity: Entity, name: &Name, parent: Option<&Parent>, reflect_components: Vec<(Box<dyn Reflect>, TypeRegistration)>, entity_components: &HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>>) -> (Entity, Vec<(Box<dyn Reflect>, 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<GltfExtras>, Without<GltfProcessed>)>();
let mut scene_extras = world.query_filtered::<(Entity, &Name, &GltfSceneExtras, &Parent), (Added<GltfSceneExtras>, Without<GltfProcessed>)>();
let mut mesh_extras = world.query_filtered::<(Entity, &Name, &GltfMeshExtras, &Parent), (Added<GltfMeshExtras>, Without<GltfProcessed>)>();
let mut material_extras = world.query_filtered::<(Entity, &Name, &GltfMaterialExtras, &Parent), (Added<GltfMaterialExtras>, Without<GltfProcessed>)>();
let mut extras = world.query_filtered::<(Entity, &Name, &GltfExtras, Option<&Parent>), (Added<GltfExtras>, Without<GltfProcessed>)>();
let mut scene_extras = world.query_filtered::<(Entity, &Name, &GltfSceneExtras, Option<&Parent>), (Added<GltfSceneExtras>, Without<GltfProcessed>)>();
let mut mesh_extras = world.query_filtered::<(Entity, &Name, &GltfMeshExtras, Option<&Parent>), (Added<GltfMeshExtras>, Without<GltfProcessed>)>();
let mut material_extras = world.query_filtered::<(Entity, &Name, &GltfMaterialExtras, Option<&Parent>), (Added<GltfMaterialExtras>, Without<GltfProcessed>)>();
let mut entity_components: HashMap<Entity, Vec<(Box<dyn Reflect>, TypeRegistration)>> =
HashMap::new();
@ -63,6 +61,7 @@ pub fn add_components_from_gltf_extras(world: &mut World) {
// let gltf_components_config = world.resource::<GltfComponentsConfig>();
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

View File

@ -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())

View File

@ -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<f32> & 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

View File

@ -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

View File

@ -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

View File

@ -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
return component

View File

@ -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),

View File

@ -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

View File

@ -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

View File

@ -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})")

View File

@ -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'}