feat(Blenvy:Blender): numerous minor tweaks & fixes (mostly materials related)
* now correctly handling multi material meshes that have more materials in their slots as there are actual materials applied * per-blueprint materials are now correctly inserted/updated even when there are no material changes (ie cases where the ordering of slots etc is changed on a mesh) * conditions for trigerring exports of levels & materials are more coherent and exports are now trigerred on export setting changes (as they should have been !) * minor cleanups
This commit is contained in:
parent
ab7a0cab65
commit
94fe3f6d3c
2
TODO.md
2
TODO.md
|
@ -226,6 +226,8 @@ Blender side:
|
||||||
- [ ] materials_path custom property should be ignored both in the list of fixable component AND on export
|
- [ ] materials_path custom property should be ignored both in the list of fixable component AND on export
|
||||||
- [ ] if we want to add material_infos & others as normal components they should not be editable, so we need another attribute, and adapt the UI for that
|
- [ ] if we want to add material_infos & others as normal components they should not be editable, so we need another attribute, and adapt the UI for that
|
||||||
|
|
||||||
|
- [x] injection of materials_infos should be done outside of export_materials as it should run even if materials do not need exporting
|
||||||
|
|
||||||
- [x] if material library is toggled, then changes to materials should not change the blueprints that are using them => not really: as the name & co might change
|
- [x] if material library is toggled, then changes to materials should not change the blueprints that are using them => not really: as the name & co might change
|
||||||
- [ ] material assets seem to be added to list regardless of whether material exports are enabled or not
|
- [ ] material assets seem to be added to list regardless of whether material exports are enabled or not
|
||||||
- [x] review & upgrade overall logic of material libraries, their names & output path
|
- [x] review & upgrade overall logic of material libraries, their names & output path
|
||||||
|
|
|
@ -2,6 +2,7 @@ import os
|
||||||
import bpy
|
import bpy
|
||||||
from blenvy.assets.assets_scan import get_blueprint_asset_tree
|
from blenvy.assets.assets_scan import get_blueprint_asset_tree
|
||||||
from blenvy.assets.generate_asset_file import write_ron_assets_file
|
from blenvy.assets.generate_asset_file import write_ron_assets_file
|
||||||
|
from ....materials.materials_helpers import add_material_info_to_objects, get_blueprint_materials
|
||||||
from ..constants import TEMPSCENE_PREFIX
|
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.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
|
from ..common.export_gltf import generate_gltf_export_settings
|
||||||
|
@ -26,7 +27,11 @@ def export_blueprints(blueprints, settings, blueprints_data):
|
||||||
if export_materials_library:
|
if export_materials_library:
|
||||||
gltf_export_settings['export_materials'] = 'PLACEHOLDER'
|
gltf_export_settings['export_materials'] = 'PLACEHOLDER'
|
||||||
|
|
||||||
|
# inject blueprint asset data
|
||||||
upsert_blueprint_assets(blueprint, blueprints_data=blueprints_data, settings=settings)
|
upsert_blueprint_assets(blueprint, blueprints_data=blueprints_data, settings=settings)
|
||||||
|
# upsert material infos if needed
|
||||||
|
(_, materials_per_object) = get_blueprint_materials(blueprint)
|
||||||
|
add_material_info_to_objects(materials_per_object, settings)
|
||||||
|
|
||||||
# do the actual export
|
# do the actual export
|
||||||
generate_temporary_scene_and_export(
|
generate_temporary_scene_and_export(
|
||||||
|
|
|
@ -26,7 +26,7 @@ def auto_export(changes_per_scene, changes_per_collection, changes_per_material,
|
||||||
#should we use change detection or not
|
#should we use change detection or not
|
||||||
change_detection = getattr(settings.auto_export, "change_detection")
|
change_detection = getattr(settings.auto_export, "change_detection")
|
||||||
export_scene_settings = getattr(settings.auto_export, "export_scene_settings")
|
export_scene_settings = getattr(settings.auto_export, "export_scene_settings")
|
||||||
do_export_blueprints = getattr(settings.auto_export, "export_blueprints")
|
export_blueprints_enabled = getattr(settings.auto_export, "export_blueprints")
|
||||||
export_materials_library = getattr(settings.auto_export, "export_materials_library")
|
export_materials_library = getattr(settings.auto_export, "export_materials_library")
|
||||||
|
|
||||||
# standard gltf export settings are stored differently
|
# standard gltf export settings are stored differently
|
||||||
|
@ -62,7 +62,7 @@ def auto_export(changes_per_scene, changes_per_collection, changes_per_material,
|
||||||
light['BlenderLightShadows'] = f"(enabled: {enabled}, buffer_bias: {light.shadow_buffer_bias})"
|
light['BlenderLightShadows'] = f"(enabled: {enabled}, buffer_bias: {light.shadow_buffer_bias})"
|
||||||
|
|
||||||
# export
|
# export
|
||||||
if do_export_blueprints:
|
if export_blueprints_enabled:
|
||||||
print("EXPORTING")
|
print("EXPORTING")
|
||||||
# get blueprints/collections infos
|
# get blueprints/collections infos
|
||||||
(blueprints_to_export) = get_blueprints_to_export(changes_per_scene, changes_per_collection, changed_export_parameters, blueprints_data, settings)
|
(blueprints_to_export) = get_blueprints_to_export(changes_per_scene, changes_per_collection, changed_export_parameters, blueprints_data, settings)
|
||||||
|
@ -102,20 +102,19 @@ def auto_export(changes_per_scene, changes_per_collection, changes_per_material,
|
||||||
old_selections = bpy.context.selected_objects
|
old_selections = bpy.context.selected_objects
|
||||||
|
|
||||||
# deal with materials
|
# deal with materials
|
||||||
if export_materials_library and len(materials_to_export) > 0:
|
if export_materials_library and (not change_detection or changed_export_parameters or len(materials_to_export) > 0) :
|
||||||
print("export MATERIALS")
|
print("export MATERIALS")
|
||||||
export_materials(materials_to_export, settings, blueprints_data)
|
export_materials(materials_to_export, settings, blueprints_data)
|
||||||
|
|
||||||
# export any level/world scenes
|
# export any level/world scenes
|
||||||
if len(level_scenes_to_export) > 0:
|
if not change_detection or changed_export_parameters or len(level_scenes_to_export) > 0:
|
||||||
print("export LEVELS")
|
print("export LEVELS")
|
||||||
for scene_name in level_scenes_to_export:
|
for scene_name in level_scenes_to_export:
|
||||||
print(" exporting scene:", scene_name)
|
print(" exporting scene:", scene_name)
|
||||||
export_level_scene(bpy.data.scenes[scene_name], settings, blueprints_data)
|
export_level_scene(bpy.data.scenes[scene_name], settings, blueprints_data)
|
||||||
|
|
||||||
# now deal with blueprints/collections
|
# now deal with blueprints/collections
|
||||||
do_export_blueprints = not change_detection or changed_export_parameters or len(blueprints_to_export) > 0
|
if not change_detection or changed_export_parameters or len(blueprints_to_export) > 0:
|
||||||
if do_export_blueprints:
|
|
||||||
print("export BLUEPRINTS")
|
print("export BLUEPRINTS")
|
||||||
export_blueprints(blueprints_to_export, settings, blueprints_data)
|
export_blueprints(blueprints_to_export, settings, blueprints_data)
|
||||||
|
|
||||||
|
|
|
@ -74,13 +74,9 @@ def clear_materials_scene(temp_scene):
|
||||||
# exports the materials used inside the current project:
|
# exports the materials used inside the current project:
|
||||||
# the name of the output path is <materials_folder>/<name_of_your_blend_file>_materials_library.gltf/glb
|
# the name of the output path is <materials_folder>/<name_of_your_blend_file>_materials_library.gltf/glb
|
||||||
def export_materials(materials_to_export, settings, blueprints_data):
|
def export_materials(materials_to_export, settings, blueprints_data):
|
||||||
if len(materials_to_export) > 0:
|
|
||||||
gltf_export_settings = generate_gltf_export_settings(settings)
|
gltf_export_settings = generate_gltf_export_settings(settings)
|
||||||
materials_path_full = getattr(settings,"materials_path_full")
|
materials_path_full = getattr(settings,"materials_path_full")
|
||||||
|
|
||||||
(used_material_names, materials_per_object) = get_all_materials(blueprints_data.blueprint_names, settings.library_scenes)
|
|
||||||
add_material_info_to_objects(materials_per_object, settings)
|
|
||||||
|
|
||||||
gltf_export_settings = { **gltf_export_settings,
|
gltf_export_settings = { **gltf_export_settings,
|
||||||
'use_active_scene': True,
|
'use_active_scene': True,
|
||||||
'use_active_collection':True,
|
'use_active_collection':True,
|
||||||
|
|
|
@ -17,19 +17,50 @@ def check_if_material_on_disk(scene_name, folder_path, extension):
|
||||||
found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path)
|
found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path)
|
||||||
return found
|
return found
|
||||||
|
|
||||||
|
|
||||||
# get materials per object, and injects the materialInfo component
|
# get materials per object, and injects the materialInfo component
|
||||||
def get_materials(object, materials_per_object):
|
def get_materials(object, materials_per_object):
|
||||||
material_slots = object.material_slots
|
material_slots = object.material_slots
|
||||||
used_materials_names = []
|
used_materials_names = []
|
||||||
|
|
||||||
for m in material_slots:
|
if not hasattr(object, "data"):
|
||||||
material = m.material
|
return used_materials_names
|
||||||
# print(" slot", m, "material", material)
|
if not hasattr(object.data,"materials"):
|
||||||
|
return used_materials_names
|
||||||
|
if len(object.data.materials) == 0:
|
||||||
|
return used_materials_names
|
||||||
|
|
||||||
|
# since we are scanning polygons to get the actually used materials, we do not get them in the correct order
|
||||||
|
materials_per_object_unordered = []
|
||||||
|
|
||||||
|
"""materials_count = len(material_slots)
|
||||||
|
print("materials_count", materials_count)
|
||||||
|
material_indices = np.empty(materials_count, dtype=np.int64)
|
||||||
|
object.data.polygons.foreach_get("material_index", material_indices)
|
||||||
|
#for material_index in object.data.polygons.foreach_get("material_index", storage):
|
||||||
|
print("polygon material_indices", material_indices)"""
|
||||||
|
# TODO: perhaps optimise it using foreach_get
|
||||||
|
for polygon in object.data.polygons:
|
||||||
|
slot = material_slots[polygon.material_index]
|
||||||
|
material = slot.material
|
||||||
|
if not material.name in used_materials_names:
|
||||||
used_materials_names.append(material.name)
|
used_materials_names.append(material.name)
|
||||||
# TODO:, also respect slots & export multiple materials if applicable !
|
materials_per_object_unordered.append((material, polygon.material_index))
|
||||||
|
|
||||||
|
if len(used_materials_names) == len(material_slots): # we found all materials, bail out
|
||||||
|
break
|
||||||
|
|
||||||
|
# now re-order the materials as per the object's material slots
|
||||||
|
sorted_materials = sorted(materials_per_object_unordered, key=lambda tup: tup[1])
|
||||||
|
|
||||||
|
# and add them
|
||||||
if not object in materials_per_object:
|
if not object in materials_per_object:
|
||||||
materials_per_object[object] = []
|
materials_per_object[object] = []
|
||||||
materials_per_object[object].append(material)
|
materials_per_object[object] = [material[0] for material in sorted_materials]#.append(material)
|
||||||
|
|
||||||
|
"""for m in material_slots:
|
||||||
|
material = m.material"""
|
||||||
|
|
||||||
return used_materials_names
|
return used_materials_names
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue