Blender_bevy_components_wor.../tools/blenvy/assets/assets_scan.py
Mark Moissette d1b5d2627d
feat(Blenvy): complete overhaul and re branding to : Blenvy (#192)
- replaced the various crates with a single one
- replaced the Blender add-ons with a single one
- this is an alpha release !
- for features etc see the various docs
2024-08-14 16:40:59 +02:00

182 lines
9.8 KiB
Python

import os
import json
import posixpath
import bpy
from ..materials.materials_helpers import get_blueprint_materials
from .asset_helpers import does_asset_exist, get_user_assets, get_user_assets_as_list
def scan_assets(scene, blueprints_data, settings):
project_root_path = getattr(settings, "project_root_path")
export_output_folder = getattr(settings,"export_output_folder")
levels_path = getattr(settings,"levels_path")
blueprints_path = getattr(settings, "blueprints_path")
export_gltf_extension = getattr(settings, "export_gltf_extension")
relative_blueprints_path = os.path.relpath(blueprints_path, project_root_path)
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_level_scene.get(scene.name, None)
blueprint_assets_list = []
if blueprint_instance_names_for_scene:
for blueprint_name in blueprint_instance_names_for_scene:
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
if blueprint is not None:
#print("BLUEPRINT", blueprint)
blueprint_exported_path = None
if blueprint.local:
blueprint_exported_path = posixpath.join(relative_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:
blueprint_assets_list.append({"name": blueprint.name, "path": blueprint_exported_path})
# fetch images/textures
# see https://blender.stackexchange.com/questions/139859/how-to-get-absolute-file-path-for-linked-texture-image
textures = []
for ob in bpy.data.objects:
if ob.type == "MESH":
for mat_slot in ob.material_slots:
if mat_slot.material:
if mat_slot.material.node_tree:
textures.extend([x.image.filepath for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE'])
print("textures", textures)
assets_list_name = f"assets_{scene.name}"
assets_list_data = {"blueprints": json.dumps(blueprint_assets_list), "sounds":[], "images":[]}
#print("blueprint assets", blueprint_assets_list)
def get_userTextures():
# TODO: limit this to the ones actually in use
# fetch images/textures
# see https://blender.stackexchange.com/questions/139859/how-to-get-absolute-file-path-for-linked-texture-image
textures = []
for ob in bpy.data.objects:
if ob.type == "MESH":
for mat_slot in ob.material_slots:
if mat_slot.material:
if mat_slot.material.node_tree:
textures.extend([x.image.filepath for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE'])
print("textures", textures)
def get_blueprint_assets_tree(blueprint, blueprints_data, parent, settings):
print("blueprint", blueprint.name)
blueprints_path = getattr(settings, "blueprints_path")
export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb")
assets_list = []
for blueprint_name in blueprint.nested_blueprints:
child_blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
if child_blueprint:
blueprint_exported_path = None
if blueprint.local:
blueprint_exported_path = posixpath.join(blueprints_path, f"{child_blueprint.name}{export_gltf_extension}")
else:
# get the injected path of the external blueprints
blueprint_exported_path = child_blueprint.collection['export_path'] if 'export_path' in child_blueprint.collection else None
if blueprint_exported_path is not None:
assets_list.append({"name": child_blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "generated": True,"internal":blueprint.local, "parent": blueprint.name})
# and add sub stuff
sub_assets_lists = get_blueprint_assets_tree(child_blueprint, blueprints_data, parent=child_blueprint.name, settings=settings)
assets_list += sub_assets_lists
direct_assets = get_user_assets_as_list(blueprint.collection)
for asset in direct_assets:
asset["parent"] = parent
asset["internal"] = blueprint.local
assets_list += direct_assets
# now get materials used by this blueprint
(blueprint_materials_names, materials_per_object) = get_blueprint_materials(blueprint=blueprint)
print("blueprint_materials", blueprint_materials_names)
for material_name in blueprint_materials_names:
materials_path = getattr(settings, "materials_path")
materials_exported_path = posixpath.join(materials_path, f"{material_name}{export_gltf_extension}")
assets_list.append({"name": material_name, "path": materials_exported_path, "type": "MATERIAL", "generated": True,"internal":blueprint.local, "parent": blueprint.name})
return assets_list
def get_level_scene_assets_tree(level_scene, blueprints_data, settings):
blueprints_path = getattr(settings, "blueprints_path")
export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb")
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_level_scene.get(level_scene.name, None)
assets_list = get_user_assets_as_list(level_scene)
if blueprint_instance_names_for_scene:
for blueprint_name in blueprint_instance_names_for_scene:
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
if blueprint is not None:
blueprint_exported_path = None
if blueprint.local:
blueprint_exported_path = posixpath.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):
assets_list.append({"name": blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "generated": True, "internal":blueprint.local, "parent": None})
assets_list += get_blueprint_assets_tree(blueprint, blueprints_data, parent=blueprint.name, settings=settings)
print("TOTAL ASSETS", assets_list)
# FIXME: do not do it here !!
scene = bpy.data.scenes[level_scene.name]
scene.generated_assets.clear()
for asset in assets_list:
if asset.get("generated", False):
added_asset = scene.generated_assets.add()
added_asset.name = asset["name"]
added_asset.path = asset["path"]
return assets_list
# same as the above, withouth the clutter below : TODO: unify
def get_level_scene_assets_tree2(level_scene, blueprints_data, settings):
blueprints_path = getattr(settings, "blueprints_path")
export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb")
blueprint_instance_names_for_scene = blueprints_data.blueprint_instances_per_level_scene.get(level_scene.name, None)
assets_list = get_user_assets_as_list(level_scene)
if blueprint_instance_names_for_scene:
for blueprint_name in blueprint_instance_names_for_scene:
blueprint = blueprints_data.blueprints_per_name.get(blueprint_name, None)
if blueprint is not None:
blueprint_exported_path = None
if blueprint.local:
blueprint_exported_path = posixpath.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):
assets_list.append({"name": blueprint.name, "path": blueprint_exported_path, "type": "MODEL", "generated": True, "internal":blueprint.local, "parent": None})
assets_list += get_blueprint_assets_tree(blueprint, blueprints_data, parent=blueprint.name, settings=settings)
return assets_list
def get_blueprint_asset_tree(blueprint, blueprints_data, settings):
blueprints_path = getattr(settings, "blueprints_path")
export_gltf_extension = getattr(settings, "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 = posixpath.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