Compare commits

...

3 Commits

Author SHA1 Message Date
Mark Moissette dc174272a8
Merge 17b31daa30 into 9b50d77790 2024-07-27 20:07:52 +00:00
Beni Bachmann 17b31daa30
feat(Blenvy:Bevy): Disable ExportRegistryPlugin on WASM (#201)
Because it tries to write to the assets directory
2024-07-27 22:07:48 +02:00
kaosat.dev 94fe3f6d3c 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
2024-07-27 21:59:57 +02:00
6 changed files with 74 additions and 40 deletions

View File

@ -226,6 +226,8 @@ Blender side:
- [ ] 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
- [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
- [ ] 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

View File

@ -60,6 +60,7 @@ impl Plugin for BlenvyPlugin {
fn build(&self, app: &mut App) {
app.add_plugins((
ComponentsFromGltfPlugin::default(),
#[cfg(not(target_arch = "wasm32"))]
ExportRegistryPlugin::default(),
BlueprintsPlugin::default(),
))

View File

@ -2,6 +2,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 ....materials.materials_helpers import add_material_info_to_objects, get_blueprint_materials
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
@ -26,7 +27,11 @@ def export_blueprints(blueprints, settings, blueprints_data):
if export_materials_library:
gltf_export_settings['export_materials'] = 'PLACEHOLDER'
# inject blueprint asset data
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
generate_temporary_scene_and_export(

View File

@ -26,7 +26,7 @@ def auto_export(changes_per_scene, changes_per_collection, changes_per_material,
#should we use change detection or not
change_detection = getattr(settings.auto_export, "change_detection")
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")
# 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})"
# export
if do_export_blueprints:
if export_blueprints_enabled:
print("EXPORTING")
# get blueprints/collections infos
(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
# 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")
export_materials(materials_to_export, settings, blueprints_data)
# 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")
for scene_name in level_scenes_to_export:
print(" exporting scene:", scene_name)
export_level_scene(bpy.data.scenes[scene_name], settings, blueprints_data)
# now deal with blueprints/collections
do_export_blueprints = not change_detection or changed_export_parameters or len(blueprints_to_export) > 0
if do_export_blueprints:
if not change_detection or changed_export_parameters or len(blueprints_to_export) > 0:
print("export BLUEPRINTS")
export_blueprints(blueprints_to_export, settings, blueprints_data)

View File

@ -74,34 +74,30 @@ def clear_materials_scene(temp_scene):
# 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
def export_materials(materials_to_export, settings, blueprints_data):
if len(materials_to_export) > 0:
gltf_export_settings = generate_gltf_export_settings(settings)
materials_path_full = getattr(settings,"materials_path_full")
gltf_export_settings = generate_gltf_export_settings(settings)
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,
'use_active_scene': True,
'use_active_collection':True,
'use_active_collection_with_nested':True,
'use_visible': False,
'use_renderable': False,
'export_apply':True
}
gltf_export_settings = { **gltf_export_settings,
'use_active_scene': True,
'use_active_collection':True,
'use_active_collection_with_nested':True,
'use_visible': False,
'use_renderable': False,
'export_apply':True
}
for material in materials_to_export:
print("exporting material", material.name)
gltf_output_path = os.path.join(materials_path_full, material.name)
for material in materials_to_export:
print("exporting material", material.name)
gltf_output_path = os.path.join(materials_path_full, material.name)
generate_temporary_scene_and_export(
settings=settings,
gltf_export_settings=gltf_export_settings,
temp_scene_name="__materials_scene",
gltf_output_path=gltf_output_path,
tempScene_filler= lambda temp_collection: generate_material_scene_content(temp_collection, material.name),
tempScene_cleaner= lambda temp_scene, params: clear_materials_scene(temp_scene=temp_scene)
)
generate_temporary_scene_and_export(
settings=settings,
gltf_export_settings=gltf_export_settings,
temp_scene_name="__materials_scene",
gltf_output_path=gltf_output_path,
tempScene_filler= lambda temp_collection: generate_material_scene_content(temp_collection, material.name),
tempScene_cleaner= lambda temp_scene, params: clear_materials_scene(temp_scene=temp_scene)
)
def cleanup_materials(collections, library_scenes):

View File

@ -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)
return found
# get materials per object, and injects the materialInfo component
def get_materials(object, materials_per_object):
material_slots = object.material_slots
used_materials_names = []
for m in material_slots:
material = m.material
# print(" slot", m, "material", material)
used_materials_names.append(material.name)
# TODO:, also respect slots & export multiple materials if applicable !
if not object in materials_per_object:
materials_per_object[object] = []
materials_per_object[object].append(material)
if not hasattr(object, "data"):
return used_materials_names
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)
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:
materials_per_object[object] = []
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