2025-07-01
This commit is contained in:
@@ -0,0 +1,768 @@
|
||||
# #### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import mathutils
|
||||
from typing import Optional
|
||||
|
||||
import bpy
|
||||
|
||||
from .material_import_utils import (
|
||||
load_poliigon_node_group,
|
||||
set_value)
|
||||
|
||||
|
||||
def create_node(
|
||||
group: bpy.types.Node,
|
||||
bl_idname: str,
|
||||
parent: Optional[bpy.types.Node],
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
select: bool = False,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates an arbitrary node of type bl_idname."""
|
||||
|
||||
node = group.node_tree.nodes.new(bl_idname)
|
||||
if name is not None:
|
||||
node.label = name
|
||||
node.name = name
|
||||
if parent is not None:
|
||||
node.parent = parent
|
||||
if location is not None:
|
||||
node.location = location
|
||||
if width is not None:
|
||||
node.width = width
|
||||
if height is not None:
|
||||
node.height = height
|
||||
node.select = select
|
||||
node.hide = hide
|
||||
return node
|
||||
|
||||
|
||||
def create_node_socket(
|
||||
node_group: bpy.types.Node,
|
||||
*,
|
||||
socket_type: str = "NodeSocketVector",
|
||||
in_out: str = "INPUT",
|
||||
name: str = "Vector",
|
||||
description: str = ""
|
||||
) -> None:
|
||||
"""Creates a new input or output socket on a group node."""
|
||||
|
||||
if bpy.app.version >= (4, 0):
|
||||
node_group.node_tree.interface.new_socket(
|
||||
name,
|
||||
description=description,
|
||||
in_out=in_out,
|
||||
socket_type=socket_type,
|
||||
parent=None
|
||||
)
|
||||
elif bpy.app.version >= (3, 4):
|
||||
if in_out == "INPUT":
|
||||
node_group.node_tree.inputs.new(socket_type, name)
|
||||
else:
|
||||
node_group.node_tree.outputs.new(socket_type, name)
|
||||
else:
|
||||
if in_out == "INPUT":
|
||||
node_group.inputs.new(socket_type, name)
|
||||
else:
|
||||
node_group.outputs.new(socket_type, name)
|
||||
|
||||
|
||||
def create_frame(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node],
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates an arbitrary node of type bl_idname."""
|
||||
|
||||
frame = create_node(
|
||||
group=group,
|
||||
bl_idname="NodeFrame",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
return frame
|
||||
|
||||
|
||||
def create_add_shader_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates an 'Add Shader' node."""
|
||||
|
||||
node_add_shader = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeAddShader",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
return node_add_shader
|
||||
|
||||
|
||||
def create_color_invert_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
factor: Optional[float] = 1.0,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates an 'Color Invert' node."""
|
||||
|
||||
node_invert_color = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeInvert",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if factor is not None:
|
||||
set_value(
|
||||
node=node_invert_color,
|
||||
sock_name="Fac",
|
||||
sock_bl_idname_expected="NodeSocketFloatFactor",
|
||||
value=factor)
|
||||
return node_invert_color
|
||||
|
||||
|
||||
def create_combine_xyz_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
value_x: Optional[float] = 1.0,
|
||||
value_y: Optional[float] = 1.0,
|
||||
value_z: Optional[float] = 1.0,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates an 'Combine XYZ' node."""
|
||||
|
||||
node_combine_xyz = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeCombineXYZ",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if value_x is not None:
|
||||
set_value(
|
||||
node=node_combine_xyz,
|
||||
sock_name="X",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=value_x)
|
||||
if value_y is not None:
|
||||
set_value(
|
||||
node=node_combine_xyz,
|
||||
sock_name="Y",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=value_y)
|
||||
if value_z is not None:
|
||||
set_value(
|
||||
node=node_combine_xyz,
|
||||
sock_name="Z",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=value_z)
|
||||
return node_combine_xyz
|
||||
|
||||
|
||||
def create_displacement_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
midlevel: Optional[float] = 0.0,
|
||||
scale: Optional[float] = 0.0,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Displacement' node."""
|
||||
|
||||
node_displacement = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeDisplacement",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if midlevel is not None:
|
||||
set_value(
|
||||
node=node_displacement,
|
||||
sock_name="Midlevel",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=midlevel)
|
||||
if scale is not None:
|
||||
set_value(
|
||||
node=node_displacement,
|
||||
sock_name="Scale",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=scale)
|
||||
return node_displacement
|
||||
|
||||
|
||||
def create_fresnel_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
ior: Optional[float] = 1.150,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Fresnel' node."""
|
||||
|
||||
node_fresnel = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeFresnel",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if ior is not None:
|
||||
set_value(
|
||||
node=node_fresnel,
|
||||
sock_name="IOR",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=ior)
|
||||
return node_fresnel
|
||||
|
||||
|
||||
def create_group_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
node_tree: Optional[bpy.types.NodeTree] = None,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Group' node."""
|
||||
|
||||
node_group = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeGroup",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if node_tree is not None:
|
||||
node_group.node_tree = node_tree
|
||||
else:
|
||||
node_tree = bpy.data.node_groups.new(name, "ShaderNodeTree")
|
||||
node_group.node_tree = node_tree
|
||||
|
||||
node_inputs = node_group.node_tree.nodes.new("NodeGroupInput")
|
||||
node_inputs.select = False
|
||||
node_outputs = node_group.node_tree.nodes.new("NodeGroupOutput")
|
||||
node_outputs.select = False
|
||||
return node_group
|
||||
|
||||
|
||||
def create_mapping_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
scale: float = 1.0,
|
||||
name: Optional[str] = None,
|
||||
location: mathutils.Vector = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False,
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Mapping' node."""
|
||||
|
||||
node_mapping = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeMapping",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
set_value(
|
||||
node=node_mapping,
|
||||
sock_name="Scale",
|
||||
sock_bl_idname_expected="NodeSocketVectorXYZ",
|
||||
value=[scale] * 3)
|
||||
return node_mapping
|
||||
|
||||
|
||||
def create_math_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
operation: Optional[str] = "MULTIPLY",
|
||||
use_clamp: Optional[bool] = True,
|
||||
value1: Optional[float] = None,
|
||||
value2: Optional[float] = None,
|
||||
name: Optional[str] = None,
|
||||
location: mathutils.Vector = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False,
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Math' node."""
|
||||
|
||||
node_math = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeMath",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if operation is not None:
|
||||
node_math.operation = operation
|
||||
if use_clamp is not None:
|
||||
node_math.use_clamp = use_clamp
|
||||
|
||||
if value1 is not None:
|
||||
set_value(
|
||||
node=node_math,
|
||||
sock_name="A",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=value1,
|
||||
# Math node's input ports have identical names
|
||||
allow_index=True)
|
||||
if value2 is not None:
|
||||
set_value(
|
||||
node=node_math,
|
||||
sock_name="B",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=value2,
|
||||
# Math node's input ports have identical names
|
||||
allow_index=True)
|
||||
return node_math
|
||||
|
||||
|
||||
def create_mix_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
data_type: Optional[str] = "RGBA",
|
||||
use_clamp: Optional[bool] = True,
|
||||
clamp_result: Optional[bool] = False,
|
||||
blend_type: Optional[str] = "MULTIPLY",
|
||||
blend_factor: Optional[float] = None,
|
||||
name: Optional[str] = None,
|
||||
location: mathutils.Vector = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Mix' (or 'MixRGB') node."""
|
||||
|
||||
if bpy.app.version >= (3, 4):
|
||||
bl_idname = "ShaderNodeMix"
|
||||
else:
|
||||
bl_idname = "ShaderNodeMixRGB"
|
||||
node_mix = create_node(
|
||||
group=group,
|
||||
bl_idname=bl_idname,
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if data_type is not None:
|
||||
if bpy.app.version >= (3, 4):
|
||||
node_mix.data_type = "RGBA"
|
||||
if use_clamp is not None:
|
||||
if bpy.app.version >= (3, 4):
|
||||
node_mix.clamp_factor = use_clamp
|
||||
else:
|
||||
node_mix.use_clamp = use_clamp
|
||||
if clamp_result is not None:
|
||||
if bpy.app.version >= (3, 4):
|
||||
node_mix.clamp_result = clamp_result
|
||||
if blend_type is not None:
|
||||
node_mix.blend_type = blend_type
|
||||
if blend_factor is not None:
|
||||
set_value(
|
||||
node=node_mix,
|
||||
sock_name="Factor",
|
||||
sock_bl_idname_expected="NodeSocketFloatFactor",
|
||||
value=blend_factor)
|
||||
return node_mix
|
||||
|
||||
|
||||
def create_mix_shader_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Mix Shader' node."""
|
||||
|
||||
node_mix_shader = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeMixShader",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
return node_mix_shader
|
||||
|
||||
|
||||
def create_mosaic_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
scale: float = 1.0,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Poliigon Mosaic' node group."""
|
||||
|
||||
node_group_mosaic = load_poliigon_node_group(
|
||||
"Mosaic_UV_Mapping")
|
||||
|
||||
if name is None:
|
||||
name = node_group_mosaic.name
|
||||
|
||||
node_mosaic = create_group_node(
|
||||
group=group,
|
||||
parent=parent,
|
||||
node_tree=node_group_mosaic,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
set_value(
|
||||
node=node_mosaic,
|
||||
sock_name="Scale",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=scale)
|
||||
return node_mosaic
|
||||
|
||||
|
||||
def create_normal_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
space: Optional[str] = "TANGENT",
|
||||
strength: Optional[float] = None,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Normal' node."""
|
||||
|
||||
node_normal = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeNormalMap",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if space is not None:
|
||||
node_normal.space = space
|
||||
if strength is not None:
|
||||
set_value(
|
||||
node=node_normal,
|
||||
sock_name="Strength",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=strength)
|
||||
return node_normal
|
||||
|
||||
|
||||
def create_texture_coordinate_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Texture Coordinate' node."""
|
||||
|
||||
node_tex_coord = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeTexCoord",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
return node_tex_coord
|
||||
|
||||
|
||||
def create_transparent_bsdf_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Transparent BSDF' node."""
|
||||
|
||||
node_transparent_bsdf = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeBsdfTransparent",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
return node_transparent_bsdf
|
||||
|
||||
|
||||
def create_translucent_bsdf_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Translucent BSDF' node."""
|
||||
|
||||
node_translucent_bsdf = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeBsdfTranslucent",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
return node_translucent_bsdf
|
||||
|
||||
|
||||
def create_value_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
value: Optional[float] = 0.0,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Value' node."""
|
||||
|
||||
node_value = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeValue",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if value is not None:
|
||||
# Note: This is an output being set.
|
||||
# set_value() is only for inputs!
|
||||
node_value.outputs[0].default_value = value
|
||||
return node_value
|
||||
|
||||
|
||||
def create_vector_math_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
operation: str = "MULTIPLY",
|
||||
value1: Optional[mathutils.Vector] = None,
|
||||
value2: Optional[mathutils.Vector] = None,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Vector Math' node."""
|
||||
|
||||
node_vector_math = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeVectorMath",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if operation is not None:
|
||||
node_vector_math.operation = operation
|
||||
|
||||
if value1 is not None:
|
||||
set_value(
|
||||
node=node_vector_math,
|
||||
sock_name="A",
|
||||
sock_bl_idname_expected="NodeSocketVector",
|
||||
value=value1,
|
||||
# Vector Math node's input ports have identical names
|
||||
allow_index=True)
|
||||
if value2 is not None:
|
||||
set_value(
|
||||
node=node_vector_math,
|
||||
sock_name="B",
|
||||
sock_bl_idname_expected="NodeSocketVector",
|
||||
value=value2,
|
||||
# Vector Math node's input ports have identical names
|
||||
allow_index=True)
|
||||
return node_vector_math
|
||||
|
||||
|
||||
def create_vector_rotate_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
angle_rad: Optional[mathutils.Vector] = None,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Vector Rotate' node."""
|
||||
|
||||
node_vector_rotate = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeVectorRotate",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if angle_rad is not None:
|
||||
set_value(
|
||||
node=node_vector_rotate,
|
||||
sock_name="Angle",
|
||||
sock_bl_idname_expected="NodeSocketVector",
|
||||
value=angle_rad)
|
||||
return node_vector_rotate
|
||||
|
||||
|
||||
def create_volume_absorption_node(
|
||||
group: bpy.types.Node,
|
||||
parent: Optional[bpy.types.Node] = None,
|
||||
*,
|
||||
density: Optional[float] = 100.0,
|
||||
name: Optional[str] = None,
|
||||
location: Optional[mathutils.Vector] = None,
|
||||
width: Optional[float] = None,
|
||||
height: Optional[float] = None,
|
||||
hide: bool = False
|
||||
) -> bpy.types.Node:
|
||||
"""Creates a 'Volume Absorption' node."""
|
||||
|
||||
node_vol_abs = create_node(
|
||||
group=group,
|
||||
bl_idname="ShaderNodeVolumeAbsorption",
|
||||
parent=parent,
|
||||
name=name,
|
||||
location=location,
|
||||
width=width,
|
||||
height=height,
|
||||
hide=hide
|
||||
)
|
||||
if density is not None:
|
||||
set_value(
|
||||
node=node_vol_abs,
|
||||
sock_name="Density",
|
||||
sock_bl_idname_expected="NodeSocketFloat",
|
||||
value=density)
|
||||
return node_vol_abs
|
||||
Reference in New Issue
Block a user