Source code for PyR3.shortcut.material

# -*- coding: utf-8 -*-
from __future__ import annotations

from typing import Any, Dict, Tuple

import bpy
from bpy.types import Object

from PyR3.shortcut.context import Objects


[docs]def new_node_material(name: str = "material"): material = bpy.data.materials.new(name=name) material.use_nodes = True return material
Color_T = Tuple[float, float, float, float]
[docs]def update_BSDF_node( material: bpy.types.Material, color: Color_T = None, subsurface: float = None, subsurfaceRadius: Tuple[float, float, float] = None, subsurfaceColor: Color_T = None, metallic: float = None, specular: float = None, specularTint: float = None, roughness: float = None, anisotropic: float = None, anisotropicRotation: float = None, sheen: float = None, sheenTint: float = None, clearcoat: float = None, clearcoatRoughness: float = None, IOR: float = None, transmission: float = None, transmissionRoughness: float = None, emission: Color_T = None, emissionStrength: float = None, alpha: float = None, *, autonormalize_color: bool = True, autonormalize_subsurfaceColor: bool = True, autonormalize_emission: bool = True, ) -> None: """Updates default values in Principled BSDF node of material. None params are ignored and doesn't modify node. :param material: Material to modify. :type material: bpy.types.Material :param color: Diffuse or metal surface color. :type color: Color_T, optional :param subsurface: Mix between diffuse and subsurface scattering. Rather than being a simple mix between Diffuse and Subsurface Scattering, it acts as a multiplier for the Subsurface Radius. :type subsurface: float, optional :param subsurfaceRadius: Average distance that light scatters below the surface. Higher radius gives a softer appearance, as light bleeds into shadows and through the object. The scattering distance is specified separately for the RGB channels, to render materials such as skin where red light scatters deeper. The X, Y and Z values are mapped to the R, G and B values, respectively. :type subsurfaceRadius: Tuple[float, float, float], optional :param subsurfaceColor: Subsurface scattering base color. :type subsurfaceColor: Color_T, optional :param metallic: Blends between a non-metallic and metallic material model. A value of 1.0 gives a fully specular reflection tinted with the base color, without diffuse reflection or transmission. At 0.0 the material consists of a diffuse or transmissive base layer, with a specular reflection layer on top. :type metallic: float, optional :param specular: Amount of dielectric specular reflection. Specifies facing (along normal) reflectivity in the most common 0 - 8% range. :type specular: float, optional :param specularTint: Tints the facing specular reflection using the base color, while glancing reflection remains white. :type specularTint: float, optional :param roughness: Specifies microfacet roughness of the surface for diffuse and specular reflection. :type roughness: float, optional :param anisotropic: Amount of anisotropy for specular reflection. Higher values give elongated highlights along the tangent direction; negative values give highlights shaped perpendicular to the tangent direction. :type anisotropic: float, optional :param anisotropicRotation: Rotates the direction of anisotropy, with 1.0 going full circle. :type anisotropicRotation: float, optional :param sheen: Amount of soft velvet like reflection near edges, for simulating materials such as cloth. :type sheen: float, optional :param sheenTint: Mix between white and using base color for sheen reflection. :type sheenTint: float, optional :param clearcoat: Extra white specular layer on top of others. This is useful for materials like car paint and the like. :type clearcoat: float, optional :param clearcoatRoughness: Roughness of clearcoat specular. :type clearcoatRoughness: float, optional :param IOR: Index of refraction for transmission. :type IOR: float, optional :param transmission: Mix between fully opaque surface at zero and fully glass like transmission at one. :type transmission: float, optional :param transmissionRoughness: With GGX distribution controls roughness used for transmitted light. :type transmissionRoughness: float, optional :param emission: Light emission from the surface, like the Emission shader. :type emission: Color_T, optional :param emissionStrength: Strength of the emitted light. A value of 1.0 will ensure that the object in the image has the exact same color as the Emission Color, i.e. make it ‘shadeless’. :type emissionStrength: float, optional :param alpha: Controls the transparency of the surface, with 1.0 fully opaque. Usually linked to the Alpha output of an Image Texture node. :type alpha: float, optional """ BSDF_node = material.node_tree.nodes["Principled BSDF"] if color is not None: if autonormalize_color: BSDF_node.inputs[0].default_value = tuple(c / 255 for c in color) else: BSDF_node.inputs[0].default_value = color if subsurface is not None: BSDF_node.inputs[1].default_value = subsurface if subsurfaceRadius is not None: BSDF_node.inputs[2].default_value = subsurfaceRadius if subsurfaceColor is not None: if autonormalize_subsurfaceColor: BSDF_node.inputs[3].default_value = tuple( c / 255 for c in subsurfaceColor ) else: BSDF_node.inputs[3].default_value = subsurfaceColor if metallic is not None: BSDF_node.inputs[4].default_value = metallic if specular is not None: BSDF_node.inputs[5].default_value = specular if specularTint is not None: BSDF_node.inputs[6].default_value = specularTint if roughness is not None: BSDF_node.inputs[7].default_value = roughness if anisotropic is not None: BSDF_node.inputs[8].default_value = anisotropic if anisotropicRotation is not None: BSDF_node.inputs[9].default_value = anisotropicRotation if sheen is not None: BSDF_node.inputs[10].default_value = sheen if sheenTint is not None: BSDF_node.inputs[11].default_value = sheenTint if clearcoat is not None: BSDF_node.inputs[12].default_value = clearcoat if clearcoatRoughness is not None: BSDF_node.inputs[13].default_value = clearcoatRoughness if IOR is not None: BSDF_node.inputs[14].default_value = IOR if transmission is not None: BSDF_node.inputs[15].default_value = transmission if transmissionRoughness is not None: BSDF_node.inputs[16].default_value = transmissionRoughness if emission is not None: if autonormalize_emission: BSDF_node.inputs[17].default_value = tuple( c / 255 for c in emission ) else: BSDF_node.inputs[17].default_value = emission if emissionStrength is not None: BSDF_node.inputs[18].default_value = emissionStrength if alpha is not None: BSDF_node.inputs[19].default_value = alpha
[docs]def set_material(ob: bpy.types.Object, material: bpy.types.Material): if len(ob.data.materials) == 0: ob.data.materials.append(material) else: ob.data.materials[0] = material
[docs]def apply_BSDF_material_params( ob: Object = None, params: Dict[str, Any] = None, ) -> str: """Apply BSDF Node params to this type of node of given object ob. If ob is None, currently active object is used. If params is none, only result of calling this function is creation of new material for ob if it had no materials before. :param ob: Object, to which's material to apply params to, defaults to None :type ob: Object, optional :param params: Dictionary of material params (listed in update_BSDF_node() function), defaults to None :type params: Dict[str, Any], optional :return: Name of modified material. :rtype: str """ if ob is None: ob = Objects.active if ob.active_material is None: material = new_node_material(f"{ob.name_full}_material") set_material(ob, material) material_name = material.name_full else: material = ob.active_material material_name = material.name_full if params is None: params = {} else: update_BSDF_node(material, **params) return material_name