Merge branch 'blender-v4.5-release'

This commit is contained in:
Julien Duroure
2025-06-17 12:59:44 +02:00
3 changed files with 88 additions and 16 deletions

View File

@@ -5,7 +5,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
"version": (5, 0, 11),
"version": (5, 0, 12),
'blender': (4, 4, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
@@ -1962,6 +1962,12 @@ class ImportGLTF2(Operator, ConvertGLTF2_Base, ImportHelper):
default=True,
)
import_merge_material_slots: BoolProperty(
name='Merge Material Slot when possible',
description='Merge material slots when possible',
default=True,
)
def draw(self, context):
operator = self
layout = self.layout
@@ -1969,9 +1975,9 @@ class ImportGLTF2(Operator, ConvertGLTF2_Base, ImportHelper):
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
layout.prop(self, 'merge_vertices')
layout.prop(self, 'import_shading')
layout.prop(self, 'export_import_convert_lighting_mode')
import_mesh_panel(layout, operator)
import_texture_panel(layout, operator)
import_bone_panel(layout, operator)
import_ux_panel(layout, operator)
@@ -2062,6 +2068,13 @@ class ImportGLTF2(Operator, ConvertGLTF2_Base, ImportHelper):
return {'CANCELLED'}
def import_mesh_panel(layout, operator):
header, body = layout.panel("GLTF_import_mesh", default_closed=False)
header.label(text="Mesh")
if body:
body.prop(operator, 'merge_vertices')
body.prop(operator, 'import_merge_material_slots')
def import_bone_panel(layout, operator):
header, body = layout.panel("GLTF_import_bone", default_closed=False)
header.label(text="Bones & Skin")

View File

@@ -19,6 +19,25 @@ class BlenderMaterial():
@staticmethod
def create(gltf, material_idx, vertex_color):
"""Material creation."""
if material_idx is None:
# If no material is specified, we create a default one
mat = bpy.data.materials.new(name="DefaultMaterial")
mat.use_nodes = True
mat.node_tree.nodes.clear()
output_node = mat.node_tree.nodes.new(type='ShaderNodeOutputMaterial')
output_node.location = (0, 0)
shader_node = mat.node_tree.nodes.new(type='ShaderNodeBsdfPrincipled')
shader_node.location = (-200, 0)
mat.node_tree.links.new(shader_node.outputs[0], output_node.inputs[0])
if vertex_color:
# Add vertex color node
vertex_color_node = mat.node_tree.nodes.new(type='ShaderNodeVertexColor')
vertex_color_node.location = (-400, 0)
mat.node_tree.links.new(vertex_color_node.outputs[0], shader_node.inputs[0])
return mat.name
pymaterial = gltf.data.materials[material_idx]
import_user_extensions('gather_import_material_before_hook', gltf, pymaterial, vertex_color)

View File

@@ -402,16 +402,25 @@ def do_primitives(gltf, mesh_idx, skin_idx, mesh, ob):
has_materials = any(prim.extensions is not None and 'KHR_materials_variants' in prim.extensions.keys()
for prim in pymesh.primitives)
has_variant = prim.extensions is not None and 'KHR_materials_variants' in prim.extensions.keys() \
and 'mappings' in prim.extensions['KHR_materials_variants'].keys()
# Even if there is no material, some primitives can have some Vertex Color
# (and we need to create a slot for them, with a default material + vertex color)
if has_materials is False:
has_materials = any(prim.attributes.get('COLOR_0') is not None for prim in pymesh.primitives)
if has_materials:
default_materials = {} # Store VC => index
we_can_merge_slots = gltf.import_settings['import_merge_material_slots']
if has_materials is True:
bl_material_index_dtype = np.intc
material_indices = np.empty(num_faces, dtype=bl_material_index_dtype)
empty_material_slot_index = None
f = 0
for idx_prim, prim in enumerate(pymesh.primitives):
has_variant = prim.extensions is not None and 'KHR_materials_variants' in prim.extensions.keys() \
and 'mappings' in prim.extensions['KHR_materials_variants'].keys()
if prim.material is not None:
# Get the material
pymaterial = gltf.data.materials[prim.material]
@@ -421,24 +430,55 @@ def do_primitives(gltf, mesh_idx, skin_idx, mesh, ob):
material_name = pymaterial.blender_material[vertex_color]
# Put material in slot (if not there)
if not has_variant:
# So we are going to use the existing slot if exists, or create a new one
if we_can_merge_slots is True and not has_variant:
if material_name not in mesh.materials:
mesh.materials.append(bpy.data.materials[material_name])
material_index = mesh.materials.find(material_name)
else:
# In case of variant, do not merge slots
# In case of variant, do not merge slots // or if user does not want to merge slots
# So we are going to create a new slot
mesh.materials.append(bpy.data.materials[material_name])
material_index = len(mesh.materials) - 1
else:
if not has_variant:
if empty_material_slot_index is None:
mesh.materials.append(None)
empty_material_slot_index = len(mesh.materials) - 1
material_index = empty_material_slot_index
else:
# In case of variant, do not merge slots
mesh.materials.append(None)
material_index = len(mesh.materials) - 1
# Check if the primitive has a vertex color
vertex_color = 'COLOR_0' if ('COLOR_0' in prim.attributes) else None
if vertex_color is not None:
if we_can_merge_slots is True and not has_variant:
# Check if we already have a slot for default material + this vertec color
if vertex_color in default_materials.keys():
material_index = default_materials[vertex_color]
else:
# Create a new slot for default material + this vertec color
name = BlenderMaterial.create(gltf, None, vertex_color)
mesh.materials.append(bpy.data.materials[name])
material_index = len(mesh.materials) - 1
default_materials[vertex_color] = material_index
else:
# In case of variant, do not merge slots // or if user does not want to merge slots
# So we are going to create a new slot if not exists already
# Else, create a new slot, but using the existing material
if vertex_color in default_materials.keys():
material_index = default_materials[vertex_color]
mesh.materials.append(bpy.data.materials[mesh.materials[material_index].name])
material_index = len(mesh.materials) - 1
else:
name = BlenderMaterial.create(gltf, None, vertex_color)
mesh.materials.append(bpy.data.materials[name])
material_index = len(mesh.materials) - 1
default_materials[vertex_color] = material_index
else:
if we_can_merge_slots is True and not has_variant:
# Create an empty slot if not exists already, or use the existing one
if empty_material_slot_index is None:
mesh.materials.append(None)
empty_material_slot_index = len(mesh.materials) - 1
material_index = empty_material_slot_index
else:
# In case of variant, do not merge slots // or if user does not want to merge slots
# So we are going to create a new slot
mesh.materials.append(None)
material_index = len(mesh.materials) - 1
material_indices[f:f + prim.num_faces].fill(material_index)