Merge pull request 'main' (#132) from Onek8/LNXSDK:main into main

Reviewed-on: LeenkxTeam/LNXSDK#132
This commit is contained in:
2026-07-24 09:22:31 +00:00
5 changed files with 99 additions and 88 deletions

View File

@ -7,7 +7,7 @@ bl_info = {
"description": "Full Stack SDK", "description": "Full Stack SDK",
"author": "Leenkx.com", "author": "Leenkx.com",
"version": (2026, 5, 0), "version": (2026, 5, 0),
"blender": (4, 5, 0), "blender": (5, 2, 0),
"doc_url": "https://leenkx.com/", "doc_url": "https://leenkx.com/",
"tracker_url": "https://leenkx.com/support" "tracker_url": "https://leenkx.com/support"
} }

View File

@ -1,3 +1,4 @@
import bpy
import importlib import importlib
import inspect import inspect
import pkgutil import pkgutil

View File

@ -16,19 +16,29 @@ if lnx.is_reload(__name__):
else: else:
lnx.enable_reload(__name__) lnx.enable_reload(__name__)
# Principled BSDF socket names that differ between Blender versions
if bpy.app.version < (4, 0, 0):
EMISSION_COLOR = 'Emission'
SUBSURFACE = 'Subsurface'
SPECULAR = 'Specular'
else:
EMISSION_COLOR = 'Emission Color'
SUBSURFACE = 'Subsurface Weight'
SPECULAR = 'Specular IOR Level'
def parse_mixshader(node: bpy.types.ShaderNodeMixShader, out_socket: NodeSocket, state: ParserState) -> None: def parse_mixshader(node: bpy.types.ShaderNodeMixShader, out_socket: NodeSocket, state: ParserState) -> None:
# Skip mixing if only one input is effectively used # Skip mixing if only one input is effectively used
if not node.inputs[0].is_linked: if not node.inputs['Fac'].is_linked:
if node.inputs[0].default_value <= 0.0: if node.inputs['Fac'].default_value <= 0.0:
c.parse_shader_input(node.inputs[1]) c.parse_shader_input(node.inputs[1])
return return
elif node.inputs[0].default_value >= 1.0: elif node.inputs['Fac'].default_value >= 1.0:
c.parse_shader_input(node.inputs[2]) c.parse_shader_input(node.inputs[2])
return return
prefix = '' if node.inputs[0].is_linked else 'const ' prefix = '' if node.inputs['Fac'].is_linked else 'const '
fac = c.parse_value_input(node.inputs[0]) fac = c.parse_value_input(node.inputs['Fac'])
fac_var = c.node_name(node.name) + '_fac' + state.get_parser_pass_suffix() fac_var = c.node_name(node.name) + '_fac' + state.get_parser_pass_suffix()
fac_inv_var = c.node_name(node.name) + '_fac_inv' fac_inv_var = c.node_name(node.name) + '_fac_inv'
state.curshader.write('{0}float {1} = clamp({2}, 0.0, 1.0);'.format(prefix, fac_var, fac)) state.curshader.write('{0}float {1} = clamp({2}, 0.0, 1.0);'.format(prefix, fac_var, fac))
@ -88,42 +98,42 @@ def parse_addshader(node: bpy.types.ShaderNodeAddShader, out_socket: NodeSocket,
# TODO: Refactor using c.get_*_input() # TODO: Refactor using c.get_*_input()
if bpy.app.version < (2, 92, 0): if bpy.app.version < (2, 91, 0):
def parse_bsdfprincipled(node: bpy.types.ShaderNodeBsdfPrincipled, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfprincipled(node: bpy.types.ShaderNodeBsdfPrincipled, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[20]) c.write_normal(node.inputs['Normal'])
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Base Color'])
if node.inputs[1].is_linked or node.inputs[1].default_value > 0.0: if node.inputs[SUBSURFACE].is_linked or node.inputs[SUBSURFACE].default_value > 0.0:
mat_state.needs_sss = True mat_state.needs_sss = True
state.out_metallic = c.parse_value_input(node.inputs[4]) state.out_metallic = c.parse_value_input(node.inputs['Metallic'])
state.out_specular = c.parse_value_input(node.inputs[5]) state.out_specular = c.parse_value_input(node.inputs[SPECULAR])
state.out_roughness = c.parse_value_input(node.inputs[7]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
if node.inputs['Emission'].is_linked or not mat_utils.equals_color_socket(node.inputs['Emission'], (0.0, 0.0, 0.0), comp_alpha=False): if node.inputs[EMISSION_COLOR].is_linked or not mat_utils.equals_color_socket(node.inputs[EMISSION_COLOR], (0.0, 0.0, 0.0), comp_alpha=False):
emission_col = c.parse_vector_input(node.inputs[17]) emission_col = c.parse_vector_input(node.inputs[EMISSION_COLOR])
state.out_emission_col = emission_col state.out_emission_col = emission_col
mat_state.emission_type = mat_state.EmissionType.SHADED mat_state.emission_type = mat_state.EmissionType.SHADED
else: else:
mat_state.emission_type = mat_state.EmissionType.NO_EMISSION mat_state.emission_type = mat_state.EmissionType.NO_EMISSION
if state.parse_opacity: if state.parse_opacity:
state.out_ior = c.parse_value_input(node.inputs[14]) state.out_ior = c.parse_value_input(node.inputs['IOR'])
# In Blender 2.83, Alpha socket is at index 18, not 19 # In Blender 2.83, Alpha socket is at index 18, not 19
if 'Alpha' in node.inputs: if 'Alpha' in node.inputs:
state.out_opacity = c.parse_value_input(node.inputs['Alpha']) state.out_opacity = c.parse_value_input(node.inputs['Alpha'])
else: else:
state.out_opacity = '1.0' state.out_opacity = '1.0'
if bpy.app.version >= (2, 92, 0) and bpy.app.version <= (4, 1, 0): if bpy.app.version >= (2, 91, 0) and bpy.app.version < (4, 0, 0):
def parse_bsdfprincipled(node: bpy.types.ShaderNodeBsdfPrincipled, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfprincipled(node: bpy.types.ShaderNodeBsdfPrincipled, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[22]) c.write_normal(node.inputs['Normal'])
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Base Color'])
if node.inputs[1].is_linked or node.inputs[1].default_value > 0.0: if node.inputs[SUBSURFACE].is_linked or node.inputs[SUBSURFACE].default_value > 0.0:
mat_state.needs_sss = True mat_state.needs_sss = True
# subsurface_radius = c.parse_vector_input(node.inputs[2]) # subsurface_radius = c.parse_vector_input(node.inputs[2])
# subsurface_color = c.parse_vector_input(node.inputs[3]) # subsurface_color = c.parse_vector_input(node.inputs[3])
state.out_metallic = c.parse_value_input(node.inputs[6]) state.out_metallic = c.parse_value_input(node.inputs['Metallic'])
state.out_specular = c.parse_value_input(node.inputs[7]) state.out_specular = c.parse_value_input(node.inputs[SPECULAR])
# specular_tint = c.parse_vector_input(node.inputs[6]) # specular_tint = c.parse_vector_input(node.inputs[6])
state.out_roughness = c.parse_value_input(node.inputs[9]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
# aniso = c.parse_vector_input(node.inputs[8]) # aniso = c.parse_vector_input(node.inputs[8])
# aniso_rot = c.parse_vector_input(node.inputs[9]) # aniso_rot = c.parse_vector_input(node.inputs[9])
# sheen = c.parse_vector_input(node.inputs[10]) # sheen = c.parse_vector_input(node.inputs[10])
@ -134,9 +144,9 @@ if bpy.app.version >= (2, 92, 0) and bpy.app.version <= (4, 1, 0):
# transmission = c.parse_vector_input(node.inputs[15]) # transmission = c.parse_vector_input(node.inputs[15])
# transmission_roughness = c.parse_vector_input(node.inputs[16]) # transmission_roughness = c.parse_vector_input(node.inputs[16])
if (node.inputs['Emission Strength'].is_linked or node.inputs['Emission Strength'].default_value != 0.0)\ if (node.inputs['Emission Strength'].is_linked or node.inputs['Emission Strength'].default_value != 0.0)\
and (node.inputs['Emission'].is_linked or not mat_utils.equals_color_socket(node.inputs['Emission'], (0.0, 0.0, 0.0), comp_alpha=False)): and (node.inputs[EMISSION_COLOR].is_linked or not mat_utils.equals_color_socket(node.inputs[EMISSION_COLOR], (0.0, 0.0, 0.0), comp_alpha=False)):
emission_col = c.parse_vector_input(node.inputs[19]) emission_col = c.parse_vector_input(node.inputs[EMISSION_COLOR])
emission_strength = c.parse_value_input(node.inputs[20]) emission_strength = c.parse_value_input(node.inputs['Emission Strength'])
state.out_emission_col = '({0} * {1})'.format(emission_col, emission_strength) state.out_emission_col = '({0} * {1})'.format(emission_col, emission_strength)
mat_state.emission_type = mat_state.EmissionType.SHADED mat_state.emission_type = mat_state.EmissionType.SHADED
else: else:
@ -144,26 +154,32 @@ if bpy.app.version >= (2, 92, 0) and bpy.app.version <= (4, 1, 0):
# clearcoar_normal = c.parse_vector_input(node.inputs[21]) # clearcoar_normal = c.parse_vector_input(node.inputs[21])
# tangent = c.parse_vector_input(node.inputs[22]) # tangent = c.parse_vector_input(node.inputs[22])
if state.parse_opacity: if state.parse_opacity:
state.out_ior = c.parse_value_input(node.inputs[16]) state.out_ior = c.parse_value_input(node.inputs['IOR'])
if len(node.inputs) >= 21: if 'Alpha' in node.inputs:
state.out_opacity = c.parse_value_input(node.inputs[21]) state.out_opacity = c.parse_value_input(node.inputs['Alpha'])
if bpy.app.version > (4, 1, 0): else:
state.out_opacity = '1.0'
if bpy.app.version >= (4, 0, 0):
def parse_bsdfprincipled(node: bpy.types.ShaderNodeBsdfPrincipled, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfprincipled(node: bpy.types.ShaderNodeBsdfPrincipled, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[5]) c.write_normal(node.inputs['Normal'])
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Base Color'])
sss_input = node.inputs.get('Subsurface Weight') or node.inputs.get('Subsurface') sss_input = node.inputs.get(SUBSURFACE)
if sss_input is not None: if sss_input is not None:
if sss_input.is_linked or sss_input.default_value > 0.0: if sss_input.is_linked or sss_input.default_value > 0.0:
mat_state.needs_sss = True mat_state.needs_sss = True
subsurface = c.parse_value_input(node.inputs[7]) subsurface = c.parse_value_input(node.inputs[SUBSURFACE])
subsurface_radius = c.parse_vector_input(node.inputs[9]) subsurface_radius = c.parse_vector_input(node.inputs['Subsurface Radius'])
subsurface_color = c.parse_vector_input(node.inputs[8]) subsurface_color_input = node.inputs.get('Subsurface Color')
state.out_metallic = c.parse_value_input(node.inputs[1]) if subsurface_color_input is not None:
subsurface_color = c.parse_vector_input(subsurface_color_input)
else:
subsurface_color = c.parse_vector_input(node.inputs['Base Color'])
state.out_metallic = c.parse_value_input(node.inputs['Metallic'])
specular_socket = node.inputs.get('Specular IOR Level') specular_socket = node.inputs.get(SPECULAR)
if specular_socket is not None: if specular_socket is not None:
state.out_specular = f'({c.parse_value_input(specular_socket)} * 2.0)' state.out_specular = f'({c.parse_value_input(specular_socket)} * 2.0)'
else: else:
@ -173,7 +189,7 @@ if bpy.app.version > (4, 1, 0):
else: else:
state.out_specular = '1.0' state.out_specular = '1.0'
state.out_roughness = c.parse_value_input(node.inputs[2]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
# Prevent black material when metal = 1.0 and roughness = 0.0 # Prevent black material when metal = 1.0 and roughness = 0.0
try: try:
if float(state.out_roughness) < 0.00101: if float(state.out_roughness) < 0.00101:
@ -181,13 +197,9 @@ if bpy.app.version > (4, 1, 0):
except ValueError: except ValueError:
pass pass
if (node.inputs['Emission Strength'].is_linked or node.inputs['Emission Strength'].default_value != 0.0)\ if (node.inputs['Emission Strength'].is_linked or node.inputs['Emission Strength'].default_value != 0.0)\
and (node.inputs['Emission Color'].is_linked or not mat_utils.equals_color_socket(node.inputs['Emission Color'], (0.0, 0.0, 0.0), comp_alpha=False)): and (node.inputs[EMISSION_COLOR].is_linked or not mat_utils.equals_color_socket(node.inputs[EMISSION_COLOR], (0.0, 0.0, 0.0), comp_alpha=False)):
if bpy.app.version >= (4, 4, 0): emission_col = c.parse_vector_input(node.inputs[EMISSION_COLOR])
emission_col = c.parse_vector_input(node.inputs[27]) emission_strength = c.parse_value_input(node.inputs['Emission Strength'])
emission_strength = c.parse_value_input(node.inputs[28])
else:
emission_col = c.parse_vector_input(node.inputs[26])
emission_strength = c.parse_value_input(node.inputs[27])
state.out_emission_col = '({0} * {1})'.format(emission_col, emission_strength) state.out_emission_col = '({0} * {1})'.format(emission_col, emission_strength)
mat_state.emission_type = mat_state.EmissionType.SHADED mat_state.emission_type = mat_state.EmissionType.SHADED
else: else:
@ -203,58 +215,58 @@ if bpy.app.version > (4, 1, 0):
#state.out_transmission = c.parse_vector_input(node.inputs[17]) #state.out_transmission = c.parse_vector_input(node.inputs[17])
#state.out_transmission_roughness = state.out_roughness #state.out_transmission_roughness = state.out_roughness
if state.parse_opacity: if state.parse_opacity:
state.out_ior = c.parse_value_input(node.inputs[3]) state.out_ior = c.parse_value_input(node.inputs['IOR'])
state.out_opacity = c.parse_value_input(node.inputs[4]) state.out_opacity = c.parse_value_input(node.inputs['Alpha'])
def parse_bsdfdiffuse(node: bpy.types.ShaderNodeBsdfDiffuse, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfdiffuse(node: bpy.types.ShaderNodeBsdfDiffuse, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[2]) c.write_normal(node.inputs['Normal'])
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
state.out_roughness = c.parse_value_input(node.inputs[1]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
state.out_specular = '0.0' state.out_specular = '0.0'
if bpy.app.version >= (4, 0, 0): if bpy.app.version >= (4, 0, 0):
def parse_bsdfsheen(node: bpy.types.ShaderNodeBsdfSheen, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfsheen(node: bpy.types.ShaderNodeBsdfSheen, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[2]) c.write_normal(node.inputs['Normal'])
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
state.out_roughness = c.parse_value_input(node.inputs[1]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
if bpy.app.version < (4, 1, 0): if bpy.app.version < (4, 0, 0):
def parse_bsdfglossy(node: bpy.types.ShaderNodeBsdfGlossy, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfglossy(node: bpy.types.ShaderNodeBsdfGlossy, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[2]) c.write_normal(node.inputs['Normal'])
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
state.out_roughness = c.parse_value_input(node.inputs[1]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
state.out_metallic = '1.0' state.out_metallic = '1.0'
else: else:
def parse_bsdfglossy(node: bpy.types.ShaderNodeBsdfAnisotropic, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfglossy(node: bpy.types.ShaderNodeBsdfAnisotropic, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[4]) c.write_normal(node.inputs['Normal'])
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
state.out_roughness = c.parse_value_input(node.inputs[1]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
state.out_metallic = '1.0' state.out_metallic = '1.0'
def parse_ambientocclusion(node: bpy.types.ShaderNodeAmbientOcclusion, out_socket: NodeSocket, state: ParserState) -> None: def parse_ambientocclusion(node: bpy.types.ShaderNodeAmbientOcclusion, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
# Single channel # Single channel
state.out_occlusion = c.parse_vector_input(node.inputs[0]) + '.r' state.out_occlusion = c.parse_vector_input(node.inputs['Distance']) + '.r'
def parse_bsdfanisotropic(node: bpy.types.ShaderNodeBsdfAnisotropic, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfanisotropic(node: bpy.types.ShaderNodeBsdfAnisotropic, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[4]) c.write_normal(node.inputs['Normal'])
# Revert to glossy # Revert to glossy
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
state.out_roughness = c.parse_value_input(node.inputs[1]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
state.out_metallic = '1.0' state.out_metallic = '1.0'
def parse_emission(node: bpy.types.ShaderNodeEmission, out_socket: NodeSocket, state: ParserState) -> None: def parse_emission(node: bpy.types.ShaderNodeEmission, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
emission_col = c.parse_vector_input(node.inputs[0]) emission_col = c.parse_vector_input(node.inputs['Color'])
emission_strength = c.parse_value_input(node.inputs[1]) emission_strength = c.parse_value_input(node.inputs['Strength'])
state.out_emission_col = '({0} * {1})'.format(emission_col, emission_strength) state.out_emission_col = '({0} * {1})'.format(emission_col, emission_strength)
state.out_basecol = 'vec3(0.0)' state.out_basecol = 'vec3(0.0)'
state.out_specular = '0.0' state.out_specular = '0.0'
@ -264,12 +276,12 @@ def parse_emission(node: bpy.types.ShaderNodeEmission, out_socket: NodeSocket, s
def parse_bsdfglass(node: bpy.types.ShaderNodeBsdfGlass, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfglass(node: bpy.types.ShaderNodeBsdfGlass, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
c.write_normal(node.inputs[3]) c.write_normal(node.inputs['Normal'])
state.out_roughness = c.parse_value_input(node.inputs[1]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
if state.parse_opacity: if state.parse_opacity:
state.out_opacity = '1.0' state.out_opacity = '1.0'
state.out_ior = c.parse_value_input(node.inputs[2]) state.out_ior = c.parse_value_input(node.inputs['IOR'])
def parse_bsdfhair(node: bpy.types.ShaderNodeBsdfHair, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfhair(node: bpy.types.ShaderNodeBsdfHair, out_socket: NodeSocket, state: ParserState) -> None:
@ -284,22 +296,19 @@ def parse_holdout(node: bpy.types.ShaderNodeHoldout, out_socket: NodeSocket, sta
def parse_bsdfrefraction(node: bpy.types.ShaderNodeBsdfRefraction, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfrefraction(node: bpy.types.ShaderNodeBsdfRefraction, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
c.write_normal(node.inputs[3]) c.write_normal(node.inputs['Normal'])
state.out_roughness = c.parse_value_input(node.inputs[1]) state.out_roughness = c.parse_value_input(node.inputs['Roughness'])
if state.parse_opacity: if state.parse_opacity:
state.out_opacity = '1.0' state.out_opacity = '1.0'
state.out_ior = c.parse_value_input(node.inputs[2]) state.out_ior = c.parse_value_input(node.inputs['IOR'])
def parse_subsurfacescattering(node: bpy.types.ShaderNodeSubsurfaceScattering, out_socket: NodeSocket, state: ParserState) -> None: def parse_subsurfacescattering(node: bpy.types.ShaderNodeSubsurfaceScattering, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
# Mark that this material needs SSS # Mark that this material needs SSS
mat_state.needs_sss = True mat_state.needs_sss = True
if bpy.app.version < (4, 1, 0): c.write_normal(node.inputs['Normal'])
c.write_normal(node.inputs[4]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
else:
c.write_normal(node.inputs[6])
state.out_basecol = c.parse_vector_input(node.inputs[0])
def parse_bsdftoon(node: bpy.types.ShaderNodeBsdfToon, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdftoon(node: bpy.types.ShaderNodeBsdfToon, out_socket: NodeSocket, state: ParserState) -> None:
@ -309,21 +318,21 @@ def parse_bsdftoon(node: bpy.types.ShaderNodeBsdfToon, out_socket: NodeSocket, s
def parse_bsdftranslucent(node: bpy.types.ShaderNodeBsdfTranslucent, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdftranslucent(node: bpy.types.ShaderNodeBsdfTranslucent, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[1]) c.write_normal(node.inputs['Normal'])
if state.parse_opacity: if state.parse_opacity:
state.out_opacity = '(1.0 - {0}.r)'.format(c.parse_vector_input(node.inputs[0])) state.out_opacity = '(1.0 - {0}.r)'.format(c.parse_vector_input(node.inputs['Color']))
state.out_ior = '1.0' state.out_ior = '1.0'
def parse_bsdftransparent(node: bpy.types.ShaderNodeBsdfTransparent, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdftransparent(node: bpy.types.ShaderNodeBsdfTransparent, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_opacity: if state.parse_opacity:
state.out_opacity = '(1.0 - {0}.r)'.format(c.parse_vector_input(node.inputs[0])) state.out_opacity = '(1.0 - {0}.r)'.format(c.parse_vector_input(node.inputs['Color']))
state.out_ior = '1.0' state.out_ior = '1.0'
if bpy.app.version < (4, 1, 0): if bpy.app.version < (4, 0, 0):
def parse_bsdfvelvet(node: bpy.types.ShaderNodeBsdfVelvet, out_socket: NodeSocket, state: ParserState) -> None: def parse_bsdfvelvet(node: bpy.types.ShaderNodeBsdfVelvet, out_socket: NodeSocket, state: ParserState) -> None:
if state.parse_surface: if state.parse_surface:
c.write_normal(node.inputs[2]) c.write_normal(node.inputs['Normal'])
state.out_basecol = c.parse_vector_input(node.inputs[0]) state.out_basecol = c.parse_vector_input(node.inputs['Color'])
state.out_roughness = '1.0' state.out_roughness = '1.0'
state.out_metallic = '1.0' state.out_metallic = '1.0'

View File

@ -205,8 +205,9 @@ ALL_NODES: Dict[str, MaterialNodeMeta] = {
if bpy.app.version > (3, 2, 0): if bpy.app.version > (3, 2, 0):
ALL_NODES['SEPARATE_COLOR'] = MaterialNodeMeta(parse_func=nodes_converter.parse_separate_color) ALL_NODES['SEPARATE_COLOR'] = MaterialNodeMeta(parse_func=nodes_converter.parse_separate_color)
ALL_NODES['COMBINE_COLOR'] = MaterialNodeMeta(parse_func=nodes_converter.parse_combine_color) ALL_NODES['COMBINE_COLOR'] = MaterialNodeMeta(parse_func=nodes_converter.parse_combine_color)
if bpy.app.version < (4, 1, 0): if bpy.app.version < (4, 0, 0):
ALL_NODES['BSDF_VELVET'] = MaterialNodeMeta(parse_func=nodes_shader.parse_bsdfvelvet) ALL_NODES['BSDF_VELVET'] = MaterialNodeMeta(parse_func=nodes_shader.parse_bsdfvelvet)
if bpy.app.version < (4, 1, 0):
ALL_NODES['TEX_MUSGRAVE'] = MaterialNodeMeta(parse_func=nodes_texture.parse_tex_musgrave) ALL_NODES['TEX_MUSGRAVE'] = MaterialNodeMeta(parse_func=nodes_texture.parse_tex_musgrave)
if bpy.app.version >= (4, 0, 0): if bpy.app.version >= (4, 0, 0):
ALL_NODES['BSDF_SHEEN'] = MaterialNodeMeta(parse_func=nodes_shader.parse_bsdfsheen) ALL_NODES['BSDF_SHEEN'] = MaterialNodeMeta(parse_func=nodes_shader.parse_bsdfsheen)

View File

@ -875,7 +875,7 @@ def check_blender_version(op: bpy.types.Operator):
"""Check whether the Blender version is supported by Leenkx, """Check whether the Blender version is supported by Leenkx,
if not, report in UI. if not, report in UI.
""" """
if bpy.app.version[:2] not in [(4, 5), (4, 4), (4, 2), (3, 6), (3, 3)]: if bpy.app.version[:2] not in [(5, 2), (4, 5), (4, 4), (4, 2), (3, 6), (3, 3)]:
op.report({'INFO'}, 'INFO: For Leenkx to work correctly, use a Blender LTS version') op.report({'INFO'}, 'INFO: For Leenkx to work correctly, use a Blender LTS version')