feat(Blenvy): experimenting with injection of assets data into exported scenes/gltf files
* added extraction of local/all (wip) assets into auto export * added injection of LocalAssets & AllAssets (unsure) * related tweaks & experiments * also cleaned up asset ui for external assets * started updating the bevy integration tests
This commit is contained in:
parent
6f6b813474
commit
ba25c3cb20
|
@ -112,3 +112,8 @@ General issues:
|
|||
- [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 'export_marked_assets' it should be a default setting
|
||||
- [x] disable/ hide asset editing ui for external assets
|
||||
|
||||
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
|
|
@ -105,7 +105,7 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
|||
print("export MAIN scenes")
|
||||
for scene_name in main_scenes_to_export:
|
||||
print(" exporting scene:", scene_name)
|
||||
export_main_scene(bpy.data.scenes[scene_name], blend_file_path, settings, blueprints_data)
|
||||
export_main_scene(bpy.data.scenes[scene_name], settings, blueprints_data)
|
||||
|
||||
# now deal with blueprints/collections
|
||||
do_export_library_scene = not change_detection or changed_export_parameters or len(blueprints_to_export) > 0
|
||||
|
@ -124,7 +124,7 @@ def auto_export(changes_per_scene, changed_export_parameters, settings):
|
|||
|
||||
else:
|
||||
for scene in settings.main_scenes:
|
||||
export_main_scene(scene, blend_file_path, settings, [])
|
||||
export_main_scene(scene, settings, [])
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import json
|
||||
import bpy
|
||||
from blenvy.core.helpers_collections import (set_active_collection)
|
||||
from blenvy.core.object_makers import (make_empty)
|
||||
from .duplicate_object import duplicate_object
|
||||
from .export_gltf import export_gltf
|
||||
from blenvy.core.scene_helpers import add_scene_property
|
||||
|
||||
"""
|
||||
generates a temporary scene, fills it with data, cleans up after itself
|
||||
|
@ -12,11 +14,26 @@ generates a temporary scene, fills it with data, cleans up after itself
|
|||
* cleaned up using tempScene_cleaner
|
||||
|
||||
"""
|
||||
def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_output_path, temp_scene_name="__temp_scene", tempScene_filler=None, tempScene_cleaner=None):
|
||||
def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_output_path, temp_scene_name="__temp_scene", tempScene_filler=None, tempScene_cleaner=None, additional_data=None):
|
||||
|
||||
temp_scene = bpy.data.scenes.new(name=temp_scene_name)
|
||||
temp_root_collection = temp_scene.collection
|
||||
|
||||
print("additional_dataAAAAAAAAAAAAAAAH", additional_data)
|
||||
if additional_data is not None: # FIXME not a fan of having this here
|
||||
for entry in dict(additional_data):
|
||||
print("entry in additional data", entry)
|
||||
if entry == "local_assets":
|
||||
temp_scene["local_assets"] = additional_data[entry] # this is for bevy 0.14
|
||||
temp_root_collection["local_assets"] = additional_data[entry] # for previous bevy versions, remove when migration done
|
||||
bla = "[(name: \"test_asset\", path: \"audio/fake.mp3\")]"
|
||||
add_scene_property(temp_scene, 'assets_components', {"LocalAssets": f"LocalAssets({additional_data[entry]})".replace("'", '')})
|
||||
|
||||
if entry == entry == "AllAssets":
|
||||
temp_scene["AllAssets"] = additional_data[entry]
|
||||
temp_root_collection["AllAssets"] = additional_data[entry] # for previous bevy versions, remove when migration done
|
||||
add_scene_property(temp_scene, 'assets_components', {"AllAssets": f"AllAssets({additional_data[entry]})".replace("'", '')})
|
||||
|
||||
# save active scene
|
||||
original_scene = bpy.context.window.scene
|
||||
# and selected collection
|
||||
|
@ -43,6 +60,7 @@ def generate_temporary_scene_and_export(settings, gltf_export_settings, gltf_out
|
|||
scene_filler_data = tempScene_filler(temp_root_collection)
|
||||
# export the temporary scene
|
||||
try:
|
||||
print("dry_run MODE", settings.auto_export.dry_run)
|
||||
if settings.auto_export.dry_run == "DISABLED":
|
||||
export_gltf(gltf_output_path, gltf_export_settings)
|
||||
except Exception as error:
|
||||
|
|
|
@ -18,7 +18,7 @@ def prepare_and_export():
|
|||
setting_changes = get_setting_changes()
|
||||
print("setting_changes", setting_changes)
|
||||
# do the actual export
|
||||
blenvy.auto_export.dry_run = 'NO_EXPORT'#'DISABLED'#
|
||||
# blenvy.auto_export.dry_run = 'NO_EXPORT'#'DISABLED'#
|
||||
auto_export(per_scene_changes, setting_changes, blenvy)
|
||||
|
||||
# cleanup
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
import json
|
||||
import os
|
||||
from types import SimpleNamespace
|
||||
from blenvy.blueprints.blueprint_helpers import inject_blueprints_list_into_main_scene, remove_blueprints_list_from_main_scene
|
||||
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, export_gltf)
|
||||
from .is_object_dynamic import is_object_dynamic, is_object_static
|
||||
|
||||
def export_main_scene(scene, blend_file_path, settings, blueprints_data):
|
||||
def assets_to_fake_ron(list_like):
|
||||
result = []
|
||||
for item in list_like:
|
||||
result.append(f"(name: \"{item['name']}\", path: \"{item['path']}\")")
|
||||
return result#.join(", ")
|
||||
|
||||
|
||||
def export_main_scene(scene, settings, blueprints_data):
|
||||
gltf_export_settings = generate_gltf_export_settings(settings)
|
||||
assets_path_full = getattr(settings,"assets_path_full")
|
||||
levels_path_full = getattr(settings,"levels_path_full")
|
||||
|
@ -25,7 +34,44 @@ def export_main_scene(scene, blend_file_path, settings, blueprints_data):
|
|||
if export_blueprints :
|
||||
gltf_output_path = os.path.join(levels_path_full, scene.name)
|
||||
|
||||
#inject_blueprints_list_into_main_scene(scene, blueprints_data, settings)
|
||||
inject_blueprints_list_into_main_scene(scene, blueprints_data, settings)
|
||||
print("main scene", scene)
|
||||
for asset in scene.user_assets:
|
||||
print(" user asset", asset.name, asset.path)
|
||||
for asset in scene.generated_assets:
|
||||
print(" generated asset", asset)
|
||||
"""for blueprint in blueprints_data.blueprints_per_scenes[scene.name]:
|
||||
print("BLUEPRINT", blueprint)"""
|
||||
blueprint_instances_in_scene = blueprints_data.blueprint_instances_per_main_scene.get(scene.name, {}).keys()
|
||||
blueprints_in_scene = [blueprints_data.blueprints_per_name[blueprint_name] for blueprint_name in blueprint_instances_in_scene]
|
||||
#yala = [blueprint.collection.user_assets for blueprint in blueprints_in_scene]
|
||||
#print("dsfsdf", yala)
|
||||
auto_assets = []
|
||||
|
||||
all_assets = []
|
||||
|
||||
blueprints_path = getattr(settings, "blueprints_path")
|
||||
export_gltf_extension = getattr(settings.auto_export, "export_gltf_extension", ".glb")
|
||||
for blueprint in blueprints_in_scene:
|
||||
if blueprint.local:
|
||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||
else:
|
||||
# get the injected path of the external blueprints
|
||||
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
||||
if blueprint_exported_path is not None: # and not does_asset_exist(assets_list, blueprint_exported_path):
|
||||
auto_assets.append({"name": blueprint.name, "path": blueprint_exported_path})#, "generated": True, "internal":blueprint.local, "parent": None})
|
||||
|
||||
# now also add the assets of the blueprints # TODO: wait no , these should not be a part of the (scene) local assets
|
||||
for asset in blueprint.collection.user_assets:
|
||||
print("adding assets of blueprint", asset.name)
|
||||
all_assets.append({"name": asset.name, "path": asset.path})
|
||||
|
||||
"""for asset in auto_assets:
|
||||
print(" generated asset", asset.name, asset.path)"""
|
||||
|
||||
scene["local_assets"] = assets_to_fake_ron([{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + auto_assets)
|
||||
scene["AllAssets"] = assets_to_fake_ron(all_assets + [{"name": asset.name, "path": asset.path} for asset in scene.user_assets] + auto_assets)
|
||||
|
||||
if export_separate_dynamic_and_static_objects:
|
||||
#print("SPLIT STATIC AND DYNAMIC")
|
||||
# first export static objects
|
||||
|
@ -54,19 +100,21 @@ def export_main_scene(scene, blend_file_path, 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, settings=settings),
|
||||
tempScene_cleaner= lambda temp_scene, params: clear_hollow_scene(original_root_collection=scene.collection, temp_scene=temp_scene, **params)
|
||||
)
|
||||
|
||||
remove_blueprints_list_from_main_scene(scene)
|
||||
|
||||
else:
|
||||
gltf_output_path = os.path.join(assets_path_full, scene.name)
|
||||
print(" exporting gltf to", gltf_output_path, ".gltf/glb")
|
||||
if settings.auto_export.dry_run == "DISABLED":
|
||||
export_gltf(gltf_output_path, gltf_export_settings)
|
||||
|
||||
remove_blueprints_list_from_main_scene(scene)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
|||
|
||||
add_possible = does_asset_exist(target, {"path": asset_registry.asset_path_selector}) #"name": asset_registry.asset_name_selector,
|
||||
|
||||
if header:
|
||||
if header and editable:
|
||||
row = header.row()
|
||||
row.alert = add_possible
|
||||
|
||||
|
@ -41,23 +41,6 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
|||
if panel:
|
||||
if editable:
|
||||
row = panel.row()
|
||||
|
||||
|
||||
"""row.alert = add_possible
|
||||
row.prop(asset_registry, "asset_name_selector", text="")
|
||||
row.label(text=asset_registry.asset_path_selector)
|
||||
asset_selector = row.operator(operator="asset.open_filebrowser", text="", icon="FILE_FOLDER")
|
||||
|
||||
add_asset_layout = row.column()
|
||||
add_asset_layout.enabled = not add_possible
|
||||
|
||||
add_asset = add_asset_layout.operator(operator="bevyassets.add", text="", icon="ADD")
|
||||
add_asset.target_type = target_type
|
||||
add_asset.target_name = target_name
|
||||
add_asset.asset_name = asset_registry.asset_name_selector
|
||||
add_asset.asset_type = asset_registry.asset_type_selector
|
||||
add_asset.asset_path = asset_registry.asset_path_selector"""
|
||||
|
||||
#panel.separator()
|
||||
|
||||
for asset in user_assets:
|
||||
|
@ -77,27 +60,6 @@ def draw_assets(layout, name, title, asset_registry, target_type, target_name, e
|
|||
remove_asset.target_type = target_type
|
||||
remove_asset.target_name = target_name
|
||||
remove_asset.asset_path = asset.path
|
||||
|
||||
'''for asset in generated_assets:
|
||||
row = panel.row()
|
||||
#row.label(text=asset.name)
|
||||
#row.label(text=asset.path)
|
||||
split = row.split(factor=nesting_indent)
|
||||
col = split.column()
|
||||
col.label(text=" ")
|
||||
col = split.column()
|
||||
|
||||
|
||||
sub_header, sub_panel = col.panel(f"assets_sub{asset.name}", default_closed=False)
|
||||
sub_header.label(text=f"{asset.name} ({asset.path})", icon="XRAY")
|
||||
if sub_panel:
|
||||
sub_panel.label(text=" some stuff")
|
||||
"""remove_asset = row.operator(operator="bevyassets.remove", text="", icon="TRASH")
|
||||
remove_asset.target_type = target_type
|
||||
remove_asset.target_name = target_name
|
||||
remove_asset.asset_path = asset.path"""'''
|
||||
|
||||
|
||||
return panel
|
||||
|
||||
class Blenvy_assets(bpy.types.Panel):
|
||||
|
|
|
@ -77,4 +77,4 @@ class GLTF_PT_auto_export_blueprints_list(bpy.types.Panel):
|
|||
generated_assets = get_generated_assets(blueprint.collection)
|
||||
|
||||
draw_assets(layout=col, name=blueprint.name, title="Assets", asset_registry=asset_registry, user_assets=user_assets, generated_assets=generated_assets, target_type="BLUEPRINT", target_name=blueprint.name, editable=False)
|
||||
panel.label(text="External")
|
||||
panel.label(text="External blueprint, assets are not editable")
|
||||
|
|
|
@ -9,7 +9,7 @@ import filecmp
|
|||
from PIL import Image
|
||||
from pixelmatch.contrib.PIL import pixelmatch
|
||||
|
||||
from blenvy.auto_export.export.prepare_and_export import prepare_and_export
|
||||
from blenvy.add_ons.auto_export.common.prepare_and_export import prepare_and_export
|
||||
|
||||
@pytest.fixture
|
||||
def setup_data(request):
|
||||
|
@ -73,14 +73,11 @@ def setup_data(request):
|
|||
"""
|
||||
def test_export_complex(setup_data):
|
||||
root_path = setup_data["root_path"]
|
||||
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||
|
||||
# with change detection
|
||||
# first, configure things
|
||||
# we use the global settings for that
|
||||
export_props = {
|
||||
"main_scene_names" : ['World'],
|
||||
"library_scene_names": ['Library'],
|
||||
}
|
||||
gltf_settings = {
|
||||
"export_animations": True,
|
||||
|
@ -102,26 +99,29 @@ def test_export_complex(setup_data):
|
|||
# move the cube in the library
|
||||
# TODO: add back bpy.data.objects["Blueprint1_mesh"].location = [1, 2, 1]
|
||||
|
||||
registry = bpy.context.window_manager.components_registry
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
main_scene = blenvy.main_scenes.add()
|
||||
main_scene.name = "World"
|
||||
#blenvy.project_root_path =
|
||||
#blenvy.blueprints_path
|
||||
blenvy.auto_export.auto_export = True
|
||||
blenvy.auto_export.export_scene_settings = True
|
||||
blenvy.auto_export.export_blueprints = True
|
||||
blenvy.auto_export.export_materials_library = True
|
||||
|
||||
bpy.data.scenes['World'].blenvy_scene_type = 'Level' # set scene as main/level scene
|
||||
bpy.data.scenes['Library'].blenvy_scene_type = 'Library' # set scene as Library scene
|
||||
|
||||
# scene asset
|
||||
user_asset = bpy.data.scenes['World'].user_assets.add()
|
||||
user_asset.name = "test_asset"
|
||||
user_asset.path = "audio/fake.mp3"
|
||||
|
||||
# blueprint asset
|
||||
user_asset = bpy.data.collections['Blueprint4_nested'].user_assets.add()
|
||||
user_asset.name = "yoho_audio"
|
||||
user_asset.path = "audio/fake.mp3"
|
||||
|
||||
prepare_and_export()
|
||||
|
||||
"""auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
project_root_path = os.path.abspath(root_path),
|
||||
#blueprints_path = os.path.join("assets", "models", "library"),
|
||||
export_output_folder = os.path.join("assets", "models"), #"./models",
|
||||
#levels_path = os.path.join("assets", "models"),
|
||||
|
||||
export_scene_settings=True,
|
||||
export_blueprints=True,
|
||||
export_materials_library=True
|
||||
)"""
|
||||
# blueprint1 => has an instance, got changed, should export
|
||||
# blueprint2 => has NO instance, but marked as asset, should export
|
||||
# blueprint3 => has NO instance, not marked as asset, used inside blueprint 4: should export
|
||||
|
|
|
@ -2,6 +2,7 @@ import os
|
|||
import json
|
||||
import pytest
|
||||
import bpy
|
||||
from blenvy.add_ons.auto_export.common.prepare_and_export import prepare_and_export
|
||||
|
||||
@pytest.fixture
|
||||
def setup_data(request):
|
||||
|
@ -25,14 +26,11 @@ def setup_data(request):
|
|||
# this runs the external blueprints file
|
||||
def test_export_external_blueprints(setup_data):
|
||||
root_path = setup_data["root_path"]
|
||||
auto_export_operator = bpy.ops.export_scenes.auto_gltf
|
||||
|
||||
# with change detection
|
||||
# first, configure things
|
||||
# we use the global settings for that
|
||||
export_props = {
|
||||
"main_scene_names" : [],
|
||||
"library_scene_names": ['Library'],
|
||||
}
|
||||
gltf_settings = {
|
||||
"export_animations": True,
|
||||
|
@ -49,20 +47,20 @@ def test_export_external_blueprints(setup_data):
|
|||
stored_gltf_settings.clear()
|
||||
stored_gltf_settings.write(json.dumps(gltf_settings))
|
||||
|
||||
blenvy = bpy.context.window_manager.blenvy
|
||||
#blenvy.project_root_path =
|
||||
#blenvy.blueprints_path
|
||||
blenvy.auto_export.auto_export = True
|
||||
blenvy.auto_export.export_scene_settings = True
|
||||
blenvy.auto_export.export_blueprints = True
|
||||
blenvy.auto_export.export_materials_library = True
|
||||
|
||||
auto_export_operator(
|
||||
auto_export=True,
|
||||
direct_mode=True,
|
||||
project_root_path = os.path.abspath(root_path),
|
||||
#blueprints_path = os.path.join("assets", "models", "library"),
|
||||
#export_output_folder = os.path.join("assets", "models"), #"./models",
|
||||
#levels_path = os.path.join("assets", "models"),
|
||||
|
||||
export_scene_settings=False,
|
||||
export_blueprints=True,
|
||||
export_materials_library=True,
|
||||
export_marked_assets= True
|
||||
)
|
||||
print("SCENES", bpy.data.scenes)
|
||||
for scene in bpy.data.scenes:
|
||||
print("SCNE", scene)
|
||||
bpy.data.scenes['Library'].blenvy_scene_type = 'Library' # set scene as Library scene
|
||||
# do the actual export
|
||||
prepare_and_export()
|
||||
|
||||
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "External_blueprint.glb")) == True
|
||||
assert os.path.exists(os.path.join(setup_data["blueprints_path"], "External_blueprint2.glb")) == True
|
||||
|
|
Loading…
Reference in New Issue