def __gather_base_color_factor(blender_material, export_settings): if not blender_material.use_nodes: return [*blender_material.diffuse_color[:3], 1.0] rgb, alpha = None, None alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha") if isinstance(alpha_socket, bpy.types.NodeSocket): if export_settings['gltf_image_format'] != "NONE": alpha = gltf2_blender_get.get_factor_from_socket(alpha_socket, kind='VALUE') else: alpha = gltf2_blender_get.get_const_from_default_value_socket(alpha_socket, kind='VALUE') base_color_socket = gltf2_blender_get.get_socket(blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket(blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_old(blender_material, "BaseColorFactor") if isinstance(base_color_socket, bpy.types.NodeSocket): if export_settings['gltf_image_format'] != "NONE": rgb = gltf2_blender_get.get_factor_from_socket(base_color_socket, kind='RGB') else: rgb = gltf2_blender_get.get_const_from_default_value_socket(base_color_socket, kind='RGB') if rgb is None: rgb = [1.0, 1.0, 1.0] if alpha is None: alpha = 1.0 rgba = [*rgb, alpha] if rgba == [1, 1, 1, 1]: return None return rgba
def __gather_base_color_factor(blender_material, export_settings): rgb, alpha = None, None alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha") if isinstance(alpha_socket, bpy.types.NodeSocket): alpha = gltf2_blender_get.get_factor_from_socket(alpha_socket, kind='VALUE') base_color_socket = gltf2_blender_get.get_socket(blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket( blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_old( blender_material, "BaseColorFactor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket( blender_material, "Background") if isinstance(base_color_socket, bpy.types.NodeSocket): rgb = gltf2_blender_get.get_factor_from_socket(base_color_socket, kind='RGB') if rgb is None: rgb = [1.0, 1.0, 1.0] if alpha is None: alpha = 1.0 rgba = [*rgb, alpha] if rgba == [1, 1, 1, 1]: return None return rgba
def __gather_metallic_roughness_texture(blender_material, orm_texture, export_settings): if orm_texture is not None: texture_input = orm_texture else: metallic_socket = gltf2_blender_get.get_socket(blender_material, "Metallic") roughness_socket = gltf2_blender_get.get_socket( blender_material, "Roughness") hasMetal = metallic_socket is not None and __has_image_node_from_socket( metallic_socket) hasRough = roughness_socket is not None and __has_image_node_from_socket( roughness_socket) if not hasMetal and not hasRough: metallic_roughness = gltf2_blender_get.get_socket_old( blender_material, "MetallicRoughness") if metallic_roughness is None or not __has_image_node_from_socket( metallic_roughness): return None texture_input = (metallic_roughness, ) elif not hasMetal: texture_input = (roughness_socket, ) elif not hasRough: texture_input = (metallic_socket, ) else: texture_input = (metallic_socket, roughness_socket) return gltf2_blender_gather_texture_info.gather_texture_info( texture_input, export_settings)
def __gather_clearcoat_extension(blender_material, export_settings): clearcoat_enabled = False has_clearcoat_texture = False has_clearcoat_roughness_texture = False clearcoat_extension = {} clearcoat_roughness_slots = () clearcoat_socket = gltf2_blender_get.get_socket(blender_material, 'Clearcoat') clearcoat_roughness_socket = gltf2_blender_get.get_socket(blender_material, 'Clearcoat Roughness') clearcoat_normal_socket = gltf2_blender_get.get_socket(blender_material, 'Clearcoat Normal') if isinstance(clearcoat_socket, bpy.types.NodeSocket) and not clearcoat_socket.is_linked: clearcoat_extension['clearcoatFactor'] = clearcoat_socket.default_value clearcoat_enabled = clearcoat_extension['clearcoatFactor'] > 0 elif __has_image_node_from_socket(clearcoat_socket): clearcoat_extension['clearcoatFactor'] = 1 has_clearcoat_texture = True clearcoat_enabled = True if not clearcoat_enabled: return None if isinstance(clearcoat_roughness_socket, bpy.types.NodeSocket) and not clearcoat_roughness_socket.is_linked: clearcoat_extension['clearcoatRoughnessFactor'] = clearcoat_roughness_socket.default_value elif __has_image_node_from_socket(clearcoat_roughness_socket): clearcoat_extension['clearcoatRoughnessFactor'] = 1 has_clearcoat_roughness_texture = True # Pack clearcoat (R) and clearcoatRoughness (G) channels. if has_clearcoat_texture and has_clearcoat_roughness_texture: clearcoat_roughness_slots = (clearcoat_socket, clearcoat_roughness_socket,) elif has_clearcoat_texture: clearcoat_roughness_slots = (clearcoat_socket,) elif has_clearcoat_roughness_texture: clearcoat_roughness_slots = (clearcoat_roughness_socket,) if len(clearcoat_roughness_slots) > 0: if has_clearcoat_texture: clearcoat_extension['clearcoatTexture'] = gltf2_blender_gather_texture_info.gather_texture_info( clearcoat_socket, clearcoat_roughness_slots, export_settings, ) if has_clearcoat_roughness_texture: clearcoat_extension['clearcoatRoughnessTexture'] = gltf2_blender_gather_texture_info.gather_texture_info( clearcoat_roughness_socket, clearcoat_roughness_slots, export_settings, ) if __has_image_node_from_socket(clearcoat_normal_socket): clearcoat_extension['clearcoatNormalTexture'] = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class( clearcoat_normal_socket, (clearcoat_normal_socket,), export_settings ) return Extension('KHR_materials_clearcoat', clearcoat_extension, False)
def __gather_base_color_factor(blender_material, export_settings): alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha") alpha = alpha_socket.default_value if alpha_socket is not None and not alpha_socket.is_linked else 1.0 base_color_socket = gltf2_blender_get.get_socket(blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket( blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_old( blender_material, "BaseColorFactor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket( blender_material, "Background") if not isinstance(base_color_socket, bpy.types.NodeSocket): return None if not base_color_socket.is_linked: return list(base_color_socket.default_value)[:3] + [alpha] texture_node = __get_tex_from_socket(base_color_socket) if texture_node is None: return None def is_valid_multiply_node(node): return isinstance(node, bpy.types.ShaderNodeMixRGB) and \ node.blend_type == "MULTIPLY" and \ len(node.inputs) == 3 multiply_node = next((link.from_node for link in texture_node.path if is_valid_multiply_node(link.from_node)), None) if multiply_node is None: return None def is_factor_socket(socket): return isinstance(socket, bpy.types.NodeSocketColor) and \ (not socket.is_linked or socket.links[0] not in texture_node.path) factor_socket = next( (socket for socket in multiply_node.inputs if is_factor_socket(socket)), None) if factor_socket is None: return None if factor_socket.is_linked: print_console( "WARNING", "BaseColorFactor only supports sockets without links (in Node '{}')." .format(multiply_node.name)) return None return list(factor_socket.default_value)[:3] + [alpha]
def __gather_orm_texture(blender_material, export_settings): # Check for the presence of Occlusion, Roughness, Metallic sharing a single image. # If not fully shared, return None, so the images will be cached and processed separately. occlusion = gltf2_blender_get.get_socket(blender_material, "Occlusion") if occlusion is None or not __has_image_node_from_socket(occlusion): occlusion = gltf2_blender_get.get_socket_old(blender_material, "Occlusion") if occlusion is None or not __has_image_node_from_socket(occlusion): return None metallic_socket = gltf2_blender_get.get_socket(blender_material, "Metallic") roughness_socket = gltf2_blender_get.get_socket(blender_material, "Roughness") hasMetal = metallic_socket is not None and __has_image_node_from_socket( metallic_socket) hasRough = roughness_socket is not None and __has_image_node_from_socket( roughness_socket) if not hasMetal and not hasRough: metallic_roughness = gltf2_blender_get.get_socket_old( blender_material, "MetallicRoughness") if metallic_roughness is None or not __has_image_node_from_socket( metallic_roughness): return None result = (occlusion, metallic_roughness) elif not hasMetal: result = (occlusion, roughness_socket) elif not hasRough: result = (occlusion, metallic_socket) else: result = (occlusion, roughness_socket, metallic_socket) if not gltf2_blender_gather_texture_info.check_same_size_images(result): print_console( "INFO", "Occlusion and metal-roughness texture will be exported separately " "(use same-sized images if you want them combined)") return None # Double-check this will past the filter in texture_info info = gltf2_blender_gather_texture_info.gather_texture_info( result[0], result, export_settings) if info is None: return None return result
def __gather_metallic_factor(blender_material, export_settings): metallic_socket = gltf2_blender_get.get_socket(blender_material, "Metallic") if metallic_socket is None: metallic_socket = gltf2_blender_get.get_socket_old(blender_material, "MetallicFactor") if isinstance(metallic_socket, bpy.types.NodeSocket) and not metallic_socket.is_linked: return metallic_socket.default_value return None
def __gather_emissive_texture(blender_material, export_settings): emissive = gltf2_blender_get.get_socket(blender_material, "Emissive") if emissive is None: emissive = gltf2_blender_get.get_socket_old(blender_material, "Emissive") return gltf2_blender_gather_texture_info.gather_texture_info( emissive, (emissive, ), export_settings)
def __gather_base_color_texture(blender_material, export_settings): base_color_socket = gltf2_blender_get.get_socket(blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket(blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_old(blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket(blender_material, "Background") alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha") if alpha_socket is not None and alpha_socket.is_linked: inputs = (base_color_socket, alpha_socket, ) else: inputs = (base_color_socket,) return gltf2_blender_gather_texture_info.gather_texture_info(inputs, export_settings)
def __gather_transmission_extension(blender_material, export_settings): transmission_enabled = False has_transmission_texture = False transmission_extension = {} transmission_slots = () transmission_socket = gltf2_blender_get.get_socket(blender_material, 'Transmission') if isinstance(transmission_socket, bpy.types.NodeSocket) and not transmission_socket.is_linked: transmission_extension['transmissionFactor'] = transmission_socket.default_value transmission_enabled = transmission_extension['transmissionFactor'] > 0 elif __has_image_node_from_socket(transmission_socket): transmission_extension['transmissionFactor'] = 1 has_transmission_texture = True transmission_enabled = True if not transmission_enabled: return None # Pack transmission channel (R). if has_transmission_texture: transmission_slots = (transmission_socket,) if len(transmission_slots) > 0: combined_texture = gltf2_blender_gather_texture_info.gather_texture_info(transmission_slots, export_settings) if has_transmission_texture: transmission_extension['transmissionTexture'] = combined_texture return Extension('KHR_materials_transmission', transmission_extension, False)
def __gather_extensions(blender_material, export_settings): extensions = {} # KHR_materials_unlit if gltf2_blender_get.get_socket(blender_material, "Background") is not None: extensions["KHR_materials_unlit"] = Extension("KHR_materials_unlit", {}, False) # KHR_materials_clearcoat clearcoat_extension = __gather_clearcoat_extension(blender_material, export_settings) if clearcoat_extension: extensions["KHR_materials_clearcoat"] = clearcoat_extension # KHR_materials_transmission transmission_extension = __gather_transmission_extension( blender_material, export_settings) if transmission_extension: extensions["KHR_materials_transmission"] = transmission_extension return extensions if extensions else None
def __gather_occlusion_texture(blender_material, orm_texture, export_settings): occlusion = gltf2_blender_get.get_socket(blender_material, "Occlusion") if occlusion is None: occlusion = gltf2_blender_get.get_socket_old(blender_material, "Occlusion") return gltf2_blender_gather_texture_info.gather_material_occlusion_texture_info_class( occlusion, orm_texture or (occlusion, ), export_settings)
def __gather_normal_texture(blender_material, export_settings): normal = gltf2_blender_get.get_socket(blender_material, "Normal") if normal is None: normal = gltf2_blender_get.get_socket_old(blender_material, "Normal") return gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class( (normal,), export_settings)
def __gather_roughness_factor(blender_material, export_settings): roughness_socket = gltf2_blender_get.get_socket(blender_material, "Roughness") if roughness_socket is None: roughness_socket = gltf2_blender_get.get_socket_old(blender_material, "RoughnessFactor") if isinstance(roughness_socket, bpy.types.NodeSocket) and not roughness_socket.is_linked: return roughness_socket.default_value return None
def __gather_normal_texture(blender_material, export_settings): normal = gltf2_blender_get.get_socket(blender_material, "Normal") if normal is None: normal = gltf2_blender_get.get_socket_old(blender_material, "Normal") normal_texture, use_active_uvmap_normal = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class( normal, (normal, ), export_settings) return normal_texture, ["normalTexture" ] if use_active_uvmap_normal else None
def __gather_base_color_texture(blender_material, export_settings): base_color_socket = gltf2_blender_get.get_socket(blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket(blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_old(blender_material, "BaseColor") alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha") # keep sockets that have some texture : color and/or alpha inputs = tuple( socket for socket in [base_color_socket, alpha_socket] if socket is not None and __has_image_node_from_socket(socket) ) if not inputs: return None, None return gltf2_blender_gather_texture_info.gather_texture_info(inputs[0], inputs, export_settings)
def __gather_emissive_texture(blender_material, export_settings): emissive = gltf2_blender_get.get_socket(blender_material, "Emissive") if emissive is None: emissive = gltf2_blender_get.get_socket_old(blender_material, "Emissive") emissive_texture, use_actives_uvmap_emissive = gltf2_blender_gather_texture_info.gather_texture_info( emissive, (emissive, ), export_settings) return emissive_texture, ["emissiveTexture" ] if use_actives_uvmap_emissive else None
def __gather_occlusion_texture(blender_material, orm_texture, export_settings): occlusion = gltf2_blender_get.get_socket(blender_material, "Occlusion") if occlusion is None: occlusion = gltf2_blender_get.get_socket_old(blender_material, "Occlusion") occlusion_texture, use_active_uvmap_occlusion = gltf2_blender_gather_texture_info.gather_material_occlusion_texture_info_class( occlusion, orm_texture or (occlusion, ), export_settings) return occlusion_texture, ["occlusionTexture" ] if use_active_uvmap_occlusion else None
def __gather_roughness_factor(blender_material, export_settings): if not blender_material.use_nodes: return blender_material.roughness roughness_socket = gltf2_blender_get.get_socket(blender_material, "Roughness") if roughness_socket is None: roughness_socket = gltf2_blender_get.get_socket_old(blender_material, "RoughnessFactor") if isinstance(roughness_socket, bpy.types.NodeSocket): fac = gltf2_blender_get.get_factor_from_socket(roughness_socket, kind='VALUE') return fac if fac != 1 else None return None
def __gather_metallic_factor(blender_material, export_settings): if not blender_material.use_nodes: return blender_material.metallic metallic_socket = gltf2_blender_get.get_socket(blender_material, "Metallic") if metallic_socket is None: metallic_socket = gltf2_blender_get.get_socket_old(blender_material, "MetallicFactor") if isinstance(metallic_socket, bpy.types.NodeSocket): fac = gltf2_blender_get.get_factor_from_socket(metallic_socket, kind='VALUE') return fac if fac != 1 else None return None
def __gather_emissive_factor(blender_material, export_settings): emissive_socket = gltf2_blender_get.get_socket(blender_material, "Emissive") if emissive_socket is None: emissive_socket = gltf2_blender_get.get_socket_old(blender_material, "EmissiveFactor") if isinstance(emissive_socket, bpy.types.NodeSocket): if emissive_socket.is_linked: # In glTF, the default emissiveFactor is all zeros, so if an emission texture is connected, # we have to manually set it to all ones. return [1.0, 1.0, 1.0] else: return list(emissive_socket.default_value)[0:3] return None
def __gather_emissive_factor(blender_material, export_settings): emissive_socket = gltf2_blender_get.get_socket(blender_material, "Emissive") if emissive_socket is None: emissive_socket = gltf2_blender_get.get_socket_old(blender_material, "EmissiveFactor") if isinstance(emissive_socket, bpy.types.NodeSocket): fac = gltf2_blender_get.get_factor_from_socket(emissive_socket, kind='RGB') if fac is None and emissive_socket.is_linked: # In glTF, the default emissiveFactor is all zeros, so if an emission texture is connected, # we have to manually set it to all ones. fac = [1.0, 1.0, 1.0] if fac == [0, 0, 0]: fac = None return fac return None
def detect_shadeless_material(blender_material, export_settings): """Detect if this material is "shadeless" ie. should be exported with KHR_materials_unlit. Returns None if not. Otherwise, returns a dict with info from parsing the node tree. """ if not blender_material.use_nodes: return None # Old Background node detection (unlikely to happen) bg_socket = gltf2_blender_get.get_socket(blender_material, "Background") if bg_socket is not None: return {'rgb_socket': bg_socket} # Look for # * any color socket, connected to... # * optionally, the lightpath trick, connected to... # * optionally, a mix-with-transparent (for alpha), connected to... # * the output node info = {} for node in blender_material.node_tree.nodes: if node.type == 'OUTPUT_MATERIAL': socket = node.inputs[0] break else: return None # Be careful not to misidentify a lightpath trick as mix-alpha. result = __detect_lightpath_trick(socket) if result is not None: socket = result['next_socket'] else: result = __detect_mix_alpha(socket) if result is not None: socket = result['next_socket'] info['alpha_socket'] = result['alpha_socket'] result = __detect_lightpath_trick(socket) if result is not None: socket = result['next_socket'] # Check if a color socket, or connected to a color socket if socket.type != 'RGBA': from_socket = gltf2_blender_get.previous_socket(socket) if from_socket is None: return None if from_socket.type != 'RGBA': return None info['rgb_socket'] = socket return info
def __gather_extensions(blender_material, export_settings): extensions = {} # KHR_materials_unlit if gltf2_blender_get.get_socket(blender_material, "Background") is not None: extensions["KHR_materials_unlit"] = Extension("KHR_materials_unlit", {}, False) # KHR_materials_clearcoat clearcoat_extension = __gather_clearcoat_extension(blender_material, export_settings) if clearcoat_extension: extensions["KHR_materials_clearcoat"] = clearcoat_extension # TODO KHR_materials_pbrSpecularGlossiness return extensions if extensions else None
def __gather_emissive_factor(blender_material, export_settings): emissive_socket = gltf2_blender_get.get_socket(blender_material, "Emissive") if emissive_socket is None: emissive_socket = gltf2_blender_get.get_socket_old( blender_material, "EmissiveFactor") if isinstance(emissive_socket, bpy.types.NodeSocket): if export_settings['gltf_image_format'] != "NONE": factor = gltf2_blender_get.get_factor_from_socket(emissive_socket, kind='RGB') else: factor = gltf2_blender_get.get_const_from_default_value_socket( emissive_socket, kind='RGB') if factor is None and emissive_socket.is_linked: # In glTF, the default emissiveFactor is all zeros, so if an emission texture is connected, # we have to manually set it to all ones. factor = [1.0, 1.0, 1.0] if factor is None: factor = [0.0, 0.0, 0.0] # Handle Emission Strength strength_socket = None if emissive_socket.node.type == 'EMISSION': strength_socket = emissive_socket.node.inputs['Strength'] elif 'Emission Strength' in emissive_socket.node.inputs: strength_socket = emissive_socket.node.inputs['Emission Strength'] strength = (gltf2_blender_get.get_const_from_socket(strength_socket, kind='VALUE') if strength_socket is not None else None) if strength is not None: factor = [f * strength for f in factor] # Clamp to range [0,1] factor = [min(1.0, f) for f in factor] if factor == [0, 0, 0]: factor = None return factor return None
def __gather_clearcoat_extension(blender_material, export_settings): clearcoat_enabled = False has_clearcoat_texture = False has_clearcoat_roughness_texture = False clearcoat_extension = {} clearcoat_roughness_slots = () clearcoat_socket = gltf2_blender_get.get_socket(blender_material, 'Clearcoat') clearcoat_roughness_socket = gltf2_blender_get.get_socket( blender_material, 'Clearcoat Roughness') clearcoat_normal_socket = gltf2_blender_get.get_socket( blender_material, 'Clearcoat Normal') if isinstance(clearcoat_socket, bpy.types.NodeSocket) and not clearcoat_socket.is_linked: clearcoat_extension['clearcoatFactor'] = clearcoat_socket.default_value clearcoat_enabled = clearcoat_extension['clearcoatFactor'] > 0 elif __has_image_node_from_socket(clearcoat_socket): fac = gltf2_blender_get.get_factor_from_socket(clearcoat_socket, kind='VALUE') # default value in glTF is 0.0, but if there is a texture without factor, use 1 clearcoat_extension['clearcoatFactor'] = fac if fac != None else 1.0 has_clearcoat_texture = True clearcoat_enabled = True if not clearcoat_enabled: return None, None if isinstance( clearcoat_roughness_socket, bpy.types.NodeSocket) and not clearcoat_roughness_socket.is_linked: clearcoat_extension[ 'clearcoatRoughnessFactor'] = clearcoat_roughness_socket.default_value elif __has_image_node_from_socket(clearcoat_roughness_socket): fac = gltf2_blender_get.get_factor_from_socket( clearcoat_roughness_socket, kind='VALUE') # default value in glTF is 0.0, but if there is a texture without factor, use 1 clearcoat_extension[ 'clearcoatRoughnessFactor'] = fac if fac != None else 1.0 has_clearcoat_roughness_texture = True # Pack clearcoat (R) and clearcoatRoughness (G) channels. if has_clearcoat_texture and has_clearcoat_roughness_texture: clearcoat_roughness_slots = ( clearcoat_socket, clearcoat_roughness_socket, ) elif has_clearcoat_texture: clearcoat_roughness_slots = (clearcoat_socket, ) elif has_clearcoat_roughness_texture: clearcoat_roughness_slots = (clearcoat_roughness_socket, ) use_actives_uvmaps = [] if len(clearcoat_roughness_slots) > 0: if has_clearcoat_texture: clearcoat_texture, clearcoat_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info( clearcoat_socket, clearcoat_roughness_slots, export_settings, ) clearcoat_extension['clearcoatTexture'] = clearcoat_texture if clearcoat_texture_use_active_uvmap: use_actives_uvmaps.append("clearcoatTexture") if has_clearcoat_roughness_texture: clearcoat_roughness_texture, clearcoat_roughness_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info( clearcoat_roughness_socket, clearcoat_roughness_slots, export_settings, ) clearcoat_extension[ 'clearcoatRoughnessTexture'] = clearcoat_roughness_texture if clearcoat_roughness_texture_use_active_uvmap: use_actives_uvmaps.append("clearcoatRoughnessTexture") if __has_image_node_from_socket(clearcoat_normal_socket): clearcoat_normal_texture, clearcoat_normal_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class( clearcoat_normal_socket, (clearcoat_normal_socket, ), export_settings) clearcoat_extension[ 'clearcoatNormalTexture'] = clearcoat_normal_texture if clearcoat_normal_texture_use_active_uvmap: use_actives_uvmaps.append("clearcoatNormalTexture") return Extension('KHR_materials_clearcoat', clearcoat_extension, False), use_actives_uvmaps