New Addon: Import Autodesk .max #105013

Closed
Sebastian Sille wants to merge 136 commits from (deleted):nrgsille-import_max into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
15 changed files with 254 additions and 97 deletions
Showing only changes of commit a0b0603e68 - Show all commits

View File

@ -1331,7 +1331,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
elif new_chunk.ID == MORPH_SMOOTH and tracking == 'OBJECT': # Smooth angle
smooth_angle = read_float(new_chunk)
if child.data is not None: # Check if child is a dummy
child.data.set_sharp_from_angle(smooth_angle)
child.data.set_sharp_from_angle(angle=smooth_angle)
elif KEYFRAME and new_chunk.ID == COL_TRACK_TAG and tracking == 'AMBIENT': # Ambient
keyframe_data = {}

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": (4, 1, 13),
"version": (4, 1, 17),
'blender': (4, 1, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
@ -324,8 +324,8 @@ class ExportGLTF2_Base(ConvertGLTF2_Base):
)
export_colors: BoolProperty(
name='Vertex Colors',
description='Export vertex colors with meshes',
name='dummy',
description='Keep for compatibility only',
default=True
)
@ -810,7 +810,6 @@ class ExportGLTF2_Base(ConvertGLTF2_Base):
export_settings['gltf_draco_mesh_compression'] = False
export_settings['gltf_materials'] = self.export_materials
export_settings['gltf_colors'] = self.export_colors
export_settings['gltf_attributes'] = self.export_attributes
export_settings['gltf_cameras'] = self.export_cameras
@ -1097,7 +1096,6 @@ class GLTF_PT_export_data_mesh(bpy.types.Panel):
col = layout.column()
col.active = operator.export_normals
col.prop(operator, 'export_tangents')
layout.prop(operator, 'export_colors')
layout.prop(operator, 'export_attributes')
col = layout.column()

View File

@ -116,7 +116,7 @@ def __fix_json(obj):
def __should_include_json_value(key, value):
allowed_empty_collections = ["KHR_materials_unlit", "KHR_materials_specular"]
allowed_empty_collections = ["KHR_materials_unlit"]
if value is None:
return False

View File

@ -55,7 +55,7 @@ def __gather_intensity(blender_lamp, export_settings) -> Optional[float]:
if blender_lamp.type != 'SUN':
# When using cycles, the strength should be influenced by a LightFalloff node
result = gltf2_blender_search_node_tree.from_socket(
emission_node.inputs.get("Strength"),
gltf2_blender_search_node_tree.NodeSocket(emission_node.inputs.get("Strength"), blender_lamp),
gltf2_blender_search_node_tree.FilterByType(bpy.types.ShaderNodeLightFalloff)
)
if result:
@ -131,7 +131,7 @@ def __get_cycles_emission_node(blender_lamp) -> Optional[bpy.types.ShaderNodeEmi
if not currentNode.is_active_output:
continue
result = gltf2_blender_search_node_tree.from_socket(
currentNode.inputs.get("Surface"),
gltf2_blender_search_node_tree.NodeSocket(currentNode.inputs.get("Surface"), blender_lamp),
gltf2_blender_search_node_tree.FilterByType(bpy.types.ShaderNodeEmission)
)
if not result:

View File

@ -10,7 +10,7 @@ from ...io.com.gltf2_io_constants import ROUNDING_DIGIT
from ...io.exp.gltf2_io_user_extensions import export_user_extensions
from ...io.com import gltf2_io_constants
from ..com import gltf2_blender_conversion
from .material.gltf2_blender_gather_materials import get_base_material
from .material.gltf2_blender_gather_materials import get_base_material, get_material_from_idx
from . import gltf2_blender_gather_skins
@ -24,7 +24,7 @@ def extract_primitives(materials, blender_mesh, uuid_for_skined_data, blender_ve
primitive_creator.create_dots_data_structure()
primitive_creator.populate_dots_data()
primitive_creator.primitive_split()
primitive_creator.material_uvmap_attribute_add()
primitive_creator.manage_material_info() # UVMap & Vertex Color
return primitive_creator.primitive_creation()
class PrimitiveCreator:
@ -142,7 +142,7 @@ class PrimitiveCreator:
self.attr_name = attr_name
self.keep = attr_name.startswith("_")
# Manage attributes + COLOR_0
# Manage attributes
for blender_attribute_index, blender_attribute in enumerate(self.blender_mesh.attributes):
attr = {}
@ -162,42 +162,27 @@ class PrimitiveCreator:
continue
if self.blender_mesh.color_attributes.find(blender_attribute.name) == self.blender_mesh.color_attributes.render_color_index \
and self.blender_mesh.color_attributes.render_color_index != -1:
# Custom attributes
# Keep only attributes that starts with _
# As Blender create lots of attributes that are internal / not needed are as duplicated of standard glTF accessors (position, uv, material_index...)
if self.export_settings['gltf_attributes'] is False:
continue
# Check if there is an extension that want to keep this attribute, or change the exported name
keep_attribute = KeepAttribute(blender_attribute.name)
if self.export_settings['gltf_colors'] is False:
continue
attr['gltf_attribute_name'] = 'COLOR_0'
attr['get'] = self.get_function()
export_user_extensions('gather_attribute_keep', self.export_settings, keep_attribute)
# Seems we sometime can have name collision about attributes
# Avoid crash and ignoring one of duplicated attribute name
if 'COLOR_0' in [a['gltf_attribute_name'] for a in self.blender_attributes]:
print_console('WARNING', 'Attribute (vertex color) collision name: ' + blender_attribute.name + ", ignoring one of them")
continue
if keep_attribute.keep is False:
continue
else:
# Custom attributes
# Keep only attributes that starts with _
# As Blender create lots of attributes that are internal / not needed are as duplicated of standard glTF accessors (position, uv, material_index...)
if self.export_settings['gltf_attributes'] is False:
continue
# Check if there is an extension that want to keep this attribute, or change the exported name
keep_attribute = KeepAttribute(blender_attribute.name)
attr['gltf_attribute_name'] = keep_attribute.attr_name.upper()
attr['get'] = self.get_function()
export_user_extensions('gather_attribute_keep', self.export_settings, keep_attribute)
if keep_attribute.keep is False:
continue
attr['gltf_attribute_name'] = keep_attribute.attr_name.upper()
attr['get'] = self.get_function()
# Seems we sometime can have name collision about attributes
# Avoid crash and ignoring one of duplicated attribute name
if attr['gltf_attribute_name'] in [a['gltf_attribute_name'] for a in self.blender_attributes]:
print_console('WARNING', 'Attribute collision name: ' + blender_attribute.name + ", ignoring one of them")
continue
# Seems we sometime can have name collision about attributes
# Avoid crash and ignoring one of duplicated attribute name
if attr['gltf_attribute_name'] in [a['gltf_attribute_name'] for a in self.blender_attributes]:
print_console('WARNING', 'Attribute collision name: ' + blender_attribute.name + ", ignoring one of them")
continue
self.blender_attributes.append(attr)
@ -388,12 +373,18 @@ class PrimitiveCreator:
for material_idx in unique_material_idxs:
self.prim_indices[material_idx] = loop_indices[loop_material_idxs == material_idx]
def material_uvmap_attribute_add(self):
def manage_material_info(self):
# If user defined UVMap as a custom attribute, we need to add it/them in the dots structure and populate data
# So we need to get, for each material, what are these custom attribute
# No choice : We need to retrieve materials here. Anyway, this will be baked, and next call will be quick
# We also need to shuffle Vertex Color data if needed
materials_use_vc = None
warning_already_displayed = False
for material_idx in self.prim_indices.keys():
_, material_info = get_base_material(material_idx, self.materials, self.export_settings)
# UVMaps
self.uvmap_attribute_list = list(set([i['value'] for i in material_info["uv_info"].values() if 'type' in i.keys() and i['type'] == "Attribute" ]))
additional_fields = []
@ -402,10 +393,11 @@ class PrimitiveCreator:
additional_fields.append((attr + str(0), gltf2_blender_conversion.get_numpy_type('FLOAT2')))
additional_fields.append((attr + str(1), gltf2_blender_conversion.get_numpy_type('FLOAT2')))
new_dt = np.dtype(self.dots.dtype.descr + additional_fields)
dots = np.zeros(self.dots.shape, dtype=new_dt)
for f in self.dots.dtype.names:
dots[f] = self.dots[f]
if len(additional_fields) > 0:
new_dt = np.dtype(self.dots.dtype.descr + additional_fields)
dots = np.zeros(self.dots.shape, dtype=new_dt)
for f in self.dots.dtype.names:
dots[f] = self.dots[f]
# Now we need to get data and populate
for attr in self.uvmap_attribute_list:
@ -424,7 +416,57 @@ class PrimitiveCreator:
dots[attr + '1'] = data[:, 1]
del data
self.dots = dots
if len(additional_fields) > 0:
self.dots = dots
# There are multiple case to take into account for VC
# The simplier test is when no vertex color are used
if material_info['vc_info']['color_type'] is None and material_info['vc_info']['alpha_type'] is None:
# Nothing to do
continue
if material_info['vc_info']['color_type'] is None and material_info['vc_info']['alpha_type'] is not None:
print_console('WARNING', 'We are not managing this case (Vertex Color alpha without color)')
continue
vc_color_name = None
vc_alpha_name = None
if material_info['vc_info']['color_type'] == "name":
vc_color_name = material_info['vc_info']['color']
elif material_info['vc_info']['color_type'] == "active":
# Get active (render) Vertex Color
vc_color_name = self.blender_mesh.color_attributes[self.blender_mesh.color_attributes.render_color_index].name
if material_info['vc_info']['alpha_type'] == "name":
vc_alpha_name = material_info['vc_info']['alpha']
elif material_info['vc_info']['alpha_type'] == "active":
# Get active (render) Vertex Color
vc_alpha_name = self.blender_mesh.color_attributes[self.blender_mesh.color_attributes.render_color_index].name
if vc_color_name is not None:
vc_key = ""
vc_key += vc_color_name if vc_color_name is not None else ""
vc_key += vc_alpha_name if vc_alpha_name is not None else ""
if materials_use_vc is not None and materials_use_vc != vc_key:
if warning_already_displayed is False:
print_console('WARNING', 'glTF specification does not allow this case (multiple materials with different Vertex Color)')
warning_already_displayed = True
materials_use_vc = vc_key
continue
elif materials_use_vc is None:
materials_use_vc = vc_key
# We need to check if we need to add alpha
add_alpha = vc_alpha_name is not None
mat = get_material_from_idx(material_idx, self.materials, self.export_settings)
add_alpha = add_alpha and not (mat.blend_method is None or mat.blend_method == 'OPAQUE')
# Manage Vertex Color (RGB and Alpha if needed)
self.__manage_color_attribute(vc_color_name, vc_alpha_name if add_alpha else None)
else:
pass # Using the same Vertex Color
def primitive_creation(self):
primitives = []
@ -628,9 +670,7 @@ class PrimitiveCreator:
def get_function(self):
def getting_function(attr):
if attr['gltf_attribute_name'] == "COLOR_0":
self.__get_color_attribute(attr)
elif attr['gltf_attribute_name'].startswith("_"):
if attr['gltf_attribute_name'].startswith("_"):
self.__get_layer_attribute(attr)
elif attr['gltf_attribute_name'].startswith("TEXCOORD_"):
self.__get_uvs_attribute(int(attr['gltf_attribute_name'].split("_")[-1]), attr)
@ -642,15 +682,79 @@ class PrimitiveCreator:
return getting_function
def __get_color_attribute(self, attr):
blender_color_idx = self.blender_mesh.color_attributes.render_color_index
def __manage_color_attribute(self, attr_name, attr_name_alpha):
blender_color_idx = self.blender_mesh.color_attributes.find(attr_name)
if blender_color_idx < 0:
return None
if attr['blender_domain'] == "POINT":
# Add COLOR_0 in dots data
attr = self.blender_mesh.color_attributes[blender_color_idx]
# Get data
data_dots, data_dots_edges, data_dots_points = self.__get_color_attribute_data(attr)
# Get data for alpha if needed
if attr_name_alpha is not None and attr_name_alpha != attr_name:
blender_alpha_idx = self.blender_mesh.color_attributes.find(attr_name_alpha)
if blender_alpha_idx >= 0:
attr_alpha = self.blender_mesh.color_attributes[blender_alpha_idx]
data_dots_alpha, data_dots_edges_alpha, data_dots_points_alpha = self.__get_color_attribute_data(attr_alpha)
# Merging data
data_dots[:, 3] = data_dots_alpha[:, 3]
if data_dots_edges is not None:
data_dots_edges[:, 3] = data_dots_edges_alpha[:, 3]
if data_dots_points is not None:
data_dots_points[:, 3] = data_dots_points_alpha[:, 3]
# Check if we need to get alpha (the 4th channel) here
max_index = 4 if attr_name_alpha is not None else 3
# Add this data to dots structure
additional_fields = []
for i in range(max_index):
# Must calculate the type of the field : FLOAT_COLOR or BYTE_COLOR
additional_fields.append(('COLOR_0' + str(i), gltf2_blender_conversion.get_numpy_type('FLOAT_COLOR' if max_index == 3 else 'BYTE_COLOR')))
# Keep the existing custom attribute
# Data will be exported twice, one for COLOR_O, one for the custom attribute
new_dt = np.dtype(self.dots.dtype.descr + additional_fields)
dots = np.zeros(self.dots.shape, dtype=new_dt)
for f in self.dots.dtype.names:
dots[f] = self.dots[f]
self.dots = dots
# colors are already linear, no need to switch color space
for i in range(max_index):
self.dots['COLOR_0' +str(i)] = data_dots[:, i]
if self.export_settings['gltf_loose_edges'] and attr.domain == "POINT":
self.dots_edges['COLOR_0' + str(i)] = data_dots_edges[:, i]
if self.export_settings['gltf_loose_points'] and attr['blender_domain'] == "POINT":
self.dots_points['COLOR_0' + str(i)] = data_dots_points[:, i]
# Add COLOR_0 in attribute list
attr_color_0 = {}
attr_color_0['blender_data_type'] = 'FLOAT_COLOR' if max_index == 3 else 'BYTE_COLOR'
attr_color_0['blender_domain'] = attr.domain
attr_color_0['gltf_attribute_name'] = 'COLOR_0'
attr_color_0['len'] = max_index # 3 or 4, depending if we have alpha
attr_color_0['type'] = gltf2_blender_conversion.get_numpy_type(attr_color_0['blender_data_type'])
attr_color_0['component_type'] = gltf2_blender_conversion.get_component_type(attr_color_0['blender_data_type'])
attr_color_0['data_type'] = gltf2_io_constants.DataType.Vec3 if max_index == 3 else gltf2_io_constants.DataType.Vec4
self.blender_attributes.append(attr_color_0)
def __get_color_attribute_data(self, attr):
data_dots_edges = None
data_dots_points = None
if attr.domain == "POINT":
colors = np.empty(len(self.blender_mesh.vertices) * 4, dtype=np.float32)
elif attr['blender_domain'] == "CORNER":
elif attr.domain == "CORNER":
colors = np.empty(len(self.blender_mesh.loops) * 4, dtype=np.float32)
self.blender_mesh.color_attributes[blender_color_idx].data.foreach_get('color', colors)
if attr['blender_domain'] == "POINT":
attr.data.foreach_get('color', colors)
if attr.domain == "POINT":
colors = colors.reshape(-1, 4)
data_dots = colors[self.dots['vertex_index']]
if self.export_settings['gltf_loose_edges']:
@ -658,18 +762,13 @@ class PrimitiveCreator:
if self.export_settings['gltf_loose_points']:
data_dots_points = colors[self.dots_points['vertex_index']]
elif attr['blender_domain'] == "CORNER":
elif attr.domain == "CORNER":
colors = colors.reshape(-1, 4)
data_dots = colors
del colors
# colors are already linear, no need to switch color space
for i in range(4):
self.dots[attr['gltf_attribute_name'] + str(i)] = data_dots[:, i]
if self.export_settings['gltf_loose_edges'] and attr['blender_domain'] == "POINT":
self.dots_edges[attr['gltf_attribute_name'] + str(i)] = data_dots_edges[:, i]
if self.export_settings['gltf_loose_points'] and attr['blender_domain'] == "POINT":
self.dots_points[attr['gltf_attribute_name'] + str(i)] = data_dots_points[:, i]
return data_dots, data_dots_edges, data_dots_points
def __get_layer_attribute(self, attr):
if attr['blender_domain'] in ['CORNER']:
@ -969,15 +1068,19 @@ class PrimitiveCreator:
res[:, i] = self.prim_dots[attr['gltf_attribute_name'] + str(i)]
self.attributes[attr['gltf_attribute_name']] = {}
self.attributes[attr['gltf_attribute_name']]["data"] = res
if 'gltf_attribute_name' == "NORMAL":
if attr['gltf_attribute_name'] == "NORMAL":
self.attributes[attr['gltf_attribute_name']]["component_type"] = gltf2_io_constants.ComponentType.Float
self.attributes[attr['gltf_attribute_name']]["data_type"] = gltf2_io_constants.DataType.Vec3
elif 'gltf_attribute_name' == "TANGENT":
elif attr['gltf_attribute_name'] == "TANGENT":
self.attributes[attr['gltf_attribute_name']]["component_type"] = gltf2_io_constants.ComponentType.Float
self.attributes[attr['gltf_attribute_name']]["data_type"] = gltf2_io_constants.DataType.Vec4
elif attr['gltf_attribute_name'].startswith('TEXCOORD_'):
self.attributes[attr['gltf_attribute_name']]["component_type"] = gltf2_io_constants.ComponentType.Float
self.attributes[attr['gltf_attribute_name']]["data_type"] = gltf2_io_constants.DataType.Vec2
elif attr['gltf_attribute_name'].startswith('COLOR_'):
# This is already managed, we only have to copy
self.attributes[attr['gltf_attribute_name']]["component_type"] = attr['component_type']
self.attributes[attr['gltf_attribute_name']]["data_type"] = attr['data_type']
else:
self.attributes[attr['gltf_attribute_name']]["component_type"] = gltf2_blender_conversion.get_component_type(attr['blender_data_type'])
self.attributes[attr['gltf_attribute_name']]["data_type"] = gltf2_blender_conversion.get_data_type(attr['blender_data_type'])

View File

@ -279,7 +279,7 @@ def __get_image_data_mapping(sockets, default_sockets, results, export_settings)
dst_chan = Channel.G
elif socket.socket.name == 'Thickness': # For KHR_materials_volume
dst_chan = Channel.G
elif socket.socket.name == "Specular IOR Level": # For KHR_material_specular
elif socket.socket.name == "Specular IOR Level": # For KHR_materials_specular
dst_chan = Channel.A
elif socket.socket.name == "Sheen Roughness": # For KHR_materials_sheen
dst_chan = Channel.A

View File

@ -26,7 +26,8 @@ from .gltf2_blender_search_node_tree import \
has_image_node_from_socket, \
get_socket_from_gltf_material_node, \
get_socket, \
get_node_socket
get_node_socket, \
get_vertex_color_info
@cached
def get_material_cache_key(blender_material, export_settings):
@ -47,7 +48,7 @@ def gather_material(blender_material, export_settings):
:return: a glTF material
"""
if not __filter_material(blender_material, export_settings):
return None, {}
return None, {"uv_info": {}, "vc_info": {'color': None, 'alpha': None, 'color_type': None, 'alpha_type': None}}
mat_unlit, uvmap_info, vc_info = __export_unlit(blender_material, export_settings)
if mat_unlit is not None:
@ -299,9 +300,11 @@ def __export_unlit(blender_material, export_settings):
info = gltf2_unlit.detect_shadeless_material(blender_material, export_settings)
if info is None:
return None, {}, {"color": None, "alpha": None}
return None, {}, {"color": None, "alpha": None, "color_type": None, "alpha_type": None}
base_color_texture, uvmap_info, vc_info = gltf2_unlit.gather_base_color_texture(info, export_settings)
base_color_texture, uvmap_info = gltf2_unlit.gather_base_color_texture(info, export_settings)
vc_info = get_vertex_color_info(info.get('rgb_socket'), info.get('alpha_socket'), export_settings)
material = gltf2_io.Material(
alpha_cutoff=__gather_alpha_cutoff(blender_material, export_settings),
@ -447,7 +450,7 @@ def get_material_from_idx(material_idx, materials, export_settings):
def get_base_material(material_idx, materials, export_settings):
material = None
material_info = {"uv_info": {}, "vc_info": {}}
material_info = {"uv_info": {}, "vc_info": {"color": None, "alpha": None, "color_type": None, "alpha_type": None}}
mat = get_material_from_idx(material_idx, materials, export_settings)
if mat is not None:

View File

@ -20,17 +20,19 @@ from .gltf2_blender_search_node_tree import \
@cached
def gather_material_pbr_metallic_roughness(blender_material, orm_texture, export_settings):
if not __filter_pbr_material(blender_material, export_settings):
return None, {}
return None, {}, {'color': None, 'alpha': None, 'color_type': None, 'alpha_type': None}
uvmap_infos = {}
base_color_texture, uvmap_info, vc_info, _ = __gather_base_color_texture(blender_material, export_settings)
base_color_texture, uvmap_info, _ = __gather_base_color_texture(blender_material, export_settings)
uvmap_infos.update(uvmap_info)
metallic_roughness_texture, uvmap_info, _ = __gather_metallic_roughness_texture(blender_material, orm_texture, export_settings)
uvmap_infos.update(uvmap_info)
base_color_factor, vc_info = __gather_base_color_factor(blender_material, export_settings)
material = gltf2_io.MaterialPBRMetallicRoughness(
base_color_factor=__gather_base_color_factor(blender_material, export_settings),
base_color_factor=base_color_factor,
base_color_texture=base_color_texture,
extensions=__gather_extensions(blender_material, export_settings),
extras=__gather_extras(blender_material, export_settings),
@ -50,7 +52,7 @@ def __filter_pbr_material(blender_material, export_settings):
def __gather_base_color_factor(blender_material, export_settings):
if not blender_material.use_nodes:
return [*blender_material.diffuse_color[:3], 1.0]
return [*blender_material.diffuse_color[:3], 1.0], {"color": None, "alpha": None, "color_type": None, "alpha_type": None}
rgb, alpha = None, None
@ -80,8 +82,10 @@ def __gather_base_color_factor(blender_material, export_settings):
rgba = [*rgb, alpha]
if rgba == [1, 1, 1, 1]: return None
return rgba
vc_info = get_vertex_color_info(base_color_socket, alpha_socket, export_settings)
if rgba == [1, 1, 1, 1]: return None, vc_info
return rgba, vc_info
def __gather_base_color_texture(blender_material, export_settings):
@ -99,11 +103,10 @@ def __gather_base_color_texture(blender_material, export_settings):
if socket.socket is not None and has_image_node_from_socket(socket, export_settings)
)
if not inputs:
return None, {}, {"uv_info": {}, "vc_info": {}}, None
return None, {}, None
tex, uvmap_info, factor = gather_texture_info(inputs[0], inputs, (), export_settings)
vc_info = get_vertex_color_info(inputs[0], inputs, export_settings)
return tex, {'baseColorTexture': uvmap_info}, vc_info, factor
return tex, {'baseColorTexture': uvmap_info}, factor
def __gather_extensions(blender_material, export_settings):

View File

@ -3,7 +3,6 @@
# SPDX-License-Identifier: Apache-2.0
from . import gltf2_blender_gather_texture_info
from .gltf2_blender_search_node_tree import get_vertex_color_info
from .gltf2_blender_search_node_tree import \
get_socket, \
NodeSocket, \
@ -143,7 +142,5 @@ def gather_base_color_texture(info, export_settings):
export_settings,
)
vc_info = get_vertex_color_info(sockets[0], sockets, export_settings)
return unlit_texture, {'baseColorTexture': uvmap_info}, vc_info
return None, {}, {"color": None, "alpha": None}
return unlit_texture, {'baseColorTexture': uvmap_info}
return None, {}

View File

@ -437,5 +437,58 @@ def check_if_is_linked_to_active_output(shader_socket, group_path):
return False
def get_vertex_color_info(primary_socket, sockets, export_settings):
return {"color": None, "alpha": None} #TODO, placeholder for now
def get_vertex_color_info(color_socket, alpha_socket, export_settings):
attribute_color = None
attribute_alpha = None
attribute_color_type = None
attribute_alpha_type = None
# Retrieve Attribute used as vertex color for Color
if color_socket is not None and color_socket.socket is not None:
node = previous_node(color_socket)
if node.node is not None:
if node.node.type == 'MIX' and node.node.data_type == "RGBA" and node.node.blend_type == 'MULTIPLY':
use_vc, attribute_color, use_active = get_attribute_name(NodeSocket(node.node.inputs[6], node.group_path), export_settings)
if use_vc is False:
use_vc, attribute_color, use_active = get_attribute_name(NodeSocket(node.node.inputs[7], node.group_path), export_settings)
if use_vc is True and use_active is True:
attribute_color_type = "active"
elif use_vc is True and use_active is None and attribute_color is not None:
attribute_color_type = "name"
if alpha_socket is not None and alpha_socket.socket is not None:
node = previous_node(alpha_socket)
if node.node is not None:
if node.node.type == 'MIX' and node.node.data_type == "FLOAT" and node.node.blend_type == 'MULTIPLY':
use_vc, attribute_alpha, use_active = get_attribute_name(NodeSocket(node.node.inputs[2], node.group_path), export_settings)
if use_vc is False:
use_vc, attribute_alpha, use_active = get_attribute_name(NodeSocket(node.node.inputs[3], node.group_path), export_settings)
if use_vc is True and use_active is True:
attribute_alpha_type = "active"
elif use_vc is True and use_active is None and attribute_alpha is not None:
attribute_alpha_type = "name"
return {"color": attribute_color, "alpha": attribute_alpha, "color_type": attribute_color_type, "alpha_type": attribute_alpha_type}
def get_attribute_name(socket, export_settings):
node = previous_node(socket)
if node.node is not None and node.node.type == "ATTRIBUTE" \
and node.node.attribute_type == "GEOMETRY" \
and node.node.attribute_name is not None \
and node.node.attribute_name != "":
return True, node.node.attribute_name, None
elif node.node is not None and node.node.type == "ATTRIBUTE" \
and node.node.attribute_type == "GEOMETRY" \
and node.node.attribute_name == "":
return True, None, True
if node.node is not None and node.node.type == "VERTEX_COLOR" \
and node.node.layer_name is not None \
and node.node.layer_name != "":
return True, node.node.layer_name, None
elif node.node is not None and node.node.type == "VERTEX_COLOR" \
and node.node.layer_name == "":
return True, None, True
return False, None, None

View File

@ -3013,7 +3013,7 @@ def importShape_ProcessObject(
# solid=false, we don't support it yet.
creaseAngle = geom.getFieldAsFloat('creaseAngle', None, ancestry)
if creaseAngle is not None:
bpydata.set_sharp_from_angle(creaseAngle)
bpydata.set_sharp_from_angle(angle=creaseAngle)
else:
bpydata.polygons.foreach_set("use_smooth", [False] * len(bpydata.polygons))

View File

@ -677,7 +677,7 @@ def mu_set_auto_smooth(self, angle, affect, set_smooth_shading):
#bpy.ops.object.shade_smooth()
object.data.set_sharp_from_angle(angle) # 35 degrees as radians
object.data.set_sharp_from_angle(angle=angle) # 35 degrees as radians
objects_affected += 1

View File

@ -338,7 +338,7 @@ def CreateBevel(context, CurrentObject):
bpy.ops.object.shade_smooth()
context.object.data.set_sharp_from_angle(1.0471975)
context.object.data.set_sharp_from_angle(angle=1.0471975)
# Restore the active object
context.view_layer.objects.active = SavActive

View File

@ -656,7 +656,7 @@ def pov_torus_define(context, op, ob):
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
ob.data.set_sharp_from_angle(0.6)
ob.data.set_sharp_from_angle(angle=0.6)
ob.pov.object_as = "TORUS"
ob.update_tag() # as prop set via python not updated in depsgraph

View File

@ -171,7 +171,7 @@ def pov_superellipsoid_define(context, op, ob):
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
ob.data.set_sharp_from_angle(1.3)
ob.data.set_sharp_from_angle(angle=1.3)
ob.pov.object_as = "SUPERELLIPSOID"
ob.update_tag() # as prop set via python not updated in depsgraph
@ -1050,7 +1050,7 @@ def pov_parametric_define(context, op, ob):
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
ob.data.set_sharp_from_angle(0.6)
ob.data.set_sharp_from_angle(angle=0.6)
ob.pov.object_as = "PARAMETRIC"
ob.update_tag() # as prop set via python not updated in depsgraph
return{'FINISHED'}