Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'materials_utils/materials_cycles_converter.py')
-rw-r--r--materials_utils/materials_cycles_converter.py977
1 files changed, 0 insertions, 977 deletions
diff --git a/materials_utils/materials_cycles_converter.py b/materials_utils/materials_cycles_converter.py
deleted file mode 100644
index 573e4309..00000000
--- a/materials_utils/materials_cycles_converter.py
+++ /dev/null
@@ -1,977 +0,0 @@
-# gpl: author Silvio Falcinelli. Fixes by angavrilov and others.
-# special thanks to user blenderartists.org cmomoney
-# -*- coding: utf-8 -*-
-
-import bpy
-from os import path as os_path
-from bpy.types import Operator
-from math import (
- log2, ceil, sqrt,
-)
-from bpy.props import (
- BoolProperty,
- EnumProperty,
-)
-from .warning_messages_utils import (
- warning_messages,
- c_is_cycles_addon_enabled,
- c_data_has_materials,
- collect_report,
-)
-
-# -----------------------------------------------------------------------------
-# Globals
-
-# switch for operator's function called after AutoNodeInitiate
-CHECK_AUTONODE = False
-
-# set the node color for baked images (default greenish)
-NODE_COLOR = (0.32, 0.75, 0.32)
-# set the node color for the paint base images (default reddish)
-NODE_COLOR_PAINT = (0.6, 0.0, 0.0)
-# set the mix node color (default blueish)
-NODE_COLOR_MIX = (0.1, 0.7, 0.8)
-
-# color for sculpt/texture painting setting (default clay the last entry is Roughness)
-PAINT_SC_COLOR = (0.80, 0.75, 0.54, 0.9)
-CLAY_GLOSSY = (0.38, 0.032, 0.023, 1)
-
-# -----------------------------------------------------------------------------
-# Functions
-
-
-def AutoNodeSwitch(renderer="CYCLES", switch="OFF", operator=None):
- mats = bpy.data.materials
- use_nodes = (True if switch in ("ON") else False)
- warn_message = ('BI_SW_NODES_ON' if switch in ("ON") else
- 'BI_SW_NODES_OFF')
- warn_message_2 = ('CYC_SW_NODES_ON' if switch in ("ON") else
- 'CYC_SW_NODES_OFF')
- for cmat in mats:
- cmat.use_nodes = use_nodes
- renders = ('CYCLES' if renderer and renderer == "CYCLES" else
- 'BLENDER_RENDER')
- bpy.context.scene.render.engine = renders
- if operator:
- warning_messages(operator, (warn_message_2 if renders in ('CYCLES') else
- warn_message))
-
-
-def SetFakeUserTex():
- images = bpy.data.images
- for image in images:
- has_user = getattr(image, "users", -1)
- image_name = getattr(image, "name", "NONAME")
-
- if has_user == 0:
- image.use_fake_user = True
- collect_report("INFO: Set fake user for unused image: " + image_name)
-
-
-def BakingText(tex, mode, tex_type=None):
- collect_report("INFO: start bake texture named: " + tex.name)
- saved_img_path = None
-
- bpy.ops.object.mode_set(mode='OBJECT')
- sc = bpy.context.scene
- tmat = ''
- img = ''
- Robj = bpy.context.active_object
- for n in bpy.data.materials:
- if n.name == 'TMP_BAKING':
- tmat = n
- if not tmat:
- tmat = bpy.data.materials.new('TMP_BAKING')
- tmat.name = "TMP_BAKING"
-
- bpy.ops.mesh.primitive_plane_add()
- tm = bpy.context.active_object
- tm.name = "TMP_BAKING"
- tm.data.name = "TMP_BAKING"
- bpy.ops.object.select_pattern(extend=False, pattern="TMP_BAKING",
- case_sensitive=False)
- sc.objects.active = tm
- bpy.context.scene.render.engine = 'BLENDER_RENDER'
- tm.data.materials.append(tmat)
- if len(tmat.texture_slots.items()) == 0:
- tmat.texture_slots.add()
- tmat.texture_slots[0].texture_coords = 'UV'
- tmat.texture_slots[0].use_map_alpha = True
- tmat.texture_slots[0].texture = tex.texture
- tmat.texture_slots[0].use_map_alpha = True
- tmat.texture_slots[0].use_map_color_diffuse = False
- tmat.use_transparency = True
- tmat.alpha = 0
- tmat.use_nodes = False
- tmat.diffuse_color = 1, 1, 1
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.uv.unwrap()
-
- # clean up temporary baking images if any
- for n in bpy.data.images:
- if n.name == 'TMP_BAKING':
- n.user_clear()
- bpy.data.images.remove(n)
-
- if mode == "ALPHA" and tex.texture.type == 'IMAGE':
- sizeX = tex.texture.image.size[0]
- sizeY = tex.texture.image.size[1]
- else:
- bake_size = (int(sc.mat_context_menu.img_bake_size) if
- sc.mat_context_menu.img_bake_size else 1024)
- sizeX = bake_size
- sizeY = bake_size
-
- bpy.ops.image.new(name="TMP_BAKING", width=sizeX, height=sizeY,
- color=(0.0, 0.0, 0.0, 1.0), alpha=True, float=False)
-
- sc.render.engine = 'BLENDER_RENDER'
- img = bpy.data.images["TMP_BAKING"]
- img = bpy.data.images.get("TMP_BAKING")
- img.file_format = ("JPEG" if not mode == "ALPHA" else "PNG")
-
- # switch temporarily to 'IMAGE EDITOR', other approaches are not reliable
- check_area = False
- store_area = bpy.context.area.type
- collect_report("INFO: Temporarily switching context to Image Editor")
- try:
- bpy.context.area.type = 'IMAGE_EDITOR'
- bpy.context.area.spaces[0].image = bpy.data.images["TMP_BAKING"]
- check_area = True
- except:
- collect_report("ERROR: Setting to Image Editor failed, Baking aborted")
- check_area = False
-
- if check_area:
- paths = bpy.path.abspath(sc.mat_context_menu.conv_path)
- tex_name = getattr(getattr(tex.texture, "image", None), "name", None)
- texture_name = (tex_name.rpartition(".")[0] if tex_name else tex.texture.name)
- new_tex_name = "baked"
- name_append = ("_BAKING" if mode == "ALPHA" and
- tex.texture.type == 'IMAGE' else "_PTEXT")
- new_appendix = (".jpg" if not mode == "ALPHA" else ".png")
-
- if name_append in texture_name:
- new_tex_name = texture_name
- elif tex_type:
- new_tex_name = tex_type + name_append
- else:
- new_tex_name = texture_name + name_append
-
- img.filepath_raw = paths + new_tex_name + new_appendix
- saved_img_path = img.filepath_raw
-
- sc.render.bake_type = 'ALPHA'
- sc.render.use_bake_selected_to_active = True
- sc.render.use_bake_clear = True
-
- # try to bake if it fails give report
- try:
- bpy.ops.object.bake_image()
- img.save()
- except:
- # no return value, so the image loading is skipped
- saved_img_path = None
- collect_report("ERROR: Baking could not be completed. "
- "Check System Console for info")
- if store_area:
- bpy.context.area.type = store_area
-
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.delete()
- bpy.ops.object.select_pattern(extend=False, pattern=Robj.name, case_sensitive=False)
- sc.objects.active = Robj
- img.user_clear()
- bpy.data.images.remove(img)
-
- if tmat.users == 0:
- bpy.data.materials.remove(tmat)
-
- if saved_img_path:
- collect_report("------- Baking finished -------")
- return saved_img_path
-
-
-def AutoNodeInitiate(active=False, operator=None):
- # Checks with bpy.ops.material.check_converter_path
- # if it's possible to write in the output path
- # if it passes proceeds with calling AutoNode
-
- # if CheckImagePath(operator):
- check_path = bpy.ops.material.check_converter_path()
-
- global CHECK_AUTONODE
-
- if 'FINISHED' in check_path:
- sc = bpy.context.scene
- CHECK_AUTONODE = True
- collect_report("_______________________", True, False)
- AutoNode(active, operator)
- if sc.mat_context_menu.SET_FAKE_USER:
- SetFakeUserTex()
- else:
- warning_messages(operator, 'DIR_PATH_CONVERT', override=True)
-
-
-def AutoNode(active=False, operator=None):
- global CHECK_AUTONODE
- sc = bpy.context.scene
- if active:
- # fix for empty slots by angavrilov
- mats = [slot.material for slot in bpy.context.active_object.material_slots if
- slot.material]
- else:
- mats = bpy.data.materials
-
- # No Materials for the chosen action - abort
- if not mats:
- CHECK_AUTONODE = False
- if operator:
- if active:
- act_obj = bpy.context.active_object
- warning_messages(operator, 'CONV_NO_OBJ_MAT', act_obj.name)
- else:
- warning_messages(operator, 'CONV_NO_SC_MAT')
- return
-
- for cmat in mats:
- # check for empty material (it will fall through the first check)
- test_empty = getattr(cmat, "name", None)
- if test_empty is None:
- collect_report("An empty material was hit, skipping")
- continue
-
- cmat.use_nodes = True
- TreeNodes = cmat.node_tree
- links = TreeNodes.links
-
- # Don't alter nodes of locked materials
- locked = False
- for n in TreeNodes.nodes:
- if n.type == 'ShaderNodeOutputMaterial':
- if n.label == 'Locked':
- locked = True
- break
-
- if not locked:
- # Convert this material from non-nodes to Cycles nodes
- shader = ''
- shtsl = ''
- Add_Emission = ''
- Add_Translucent = ''
- Mix_Alpha = ''
- sT = False
- # check if some link creation failed
- link_fail = False
-
- for n in TreeNodes.nodes:
- TreeNodes.nodes.remove(n)
-
- # Starting point is diffuse BSDF and output material and a Color Ramp node
- shader = TreeNodes.nodes.new('ShaderNodeBsdfDiffuse')
- shader.location = 10, 10
- shader_val = TreeNodes.nodes.new('ShaderNodeValToRGB')
- shader_val.location = 0, -200
- shout = TreeNodes.nodes.new('ShaderNodeOutputMaterial')
- shout.location = 200, 10
- try:
- links.new(shader.outputs[0], shout.inputs[0])
- links.new(shader.inputs[0], shader_val.outputs[0])
- except:
- link_fail = True
-
- # Create other shader types only sculpt/texture paint mode is False
- sculpt_paint = sc.mat_context_menu.SCULPT_PAINT
- if sculpt_paint is False:
-
- cmat_is_transp = cmat.use_transparency and cmat.alpha < 1
-
- if not cmat.raytrace_mirror.use and not cmat_is_transp:
- if not shader.type == 'ShaderNodeBsdfDiffuse':
- collect_report("INFO: Make DIFFUSE shader node for: " + cmat.name)
- TreeNodes.nodes.remove(shader)
- shader = TreeNodes.nodes.new('ShaderNodeBsdfDiffuse')
- shader.location = 10, 10
- try:
- links.new(shader.outputs[0], shout.inputs[0])
- except:
- link_fail = True
-
- if cmat.raytrace_mirror.use and cmat.raytrace_mirror.reflect_factor > 0.001 and cmat_is_transp:
- if not shader.type == 'ShaderNodeBsdfGlass':
- collect_report("INFO: Make GLASS shader node for: " + cmat.name)
- TreeNodes.nodes.remove(shader)
- shader = TreeNodes.nodes.new('ShaderNodeBsdfGlass')
- shader.location = 0, 100
- try:
- links.new(shader.outputs[0], shout.inputs[0])
- except:
- link_fail = True
-
- if cmat.raytrace_mirror.use and not cmat_is_transp and cmat.raytrace_mirror.reflect_factor > 0.001:
- if not shader.type == 'ShaderNodeBsdfGlossy':
- collect_report("INFO: Make MIRROR shader node for: " + cmat.name)
- TreeNodes.nodes.remove(shader)
- shader = TreeNodes.nodes.new('ShaderNodeBsdfGlossy')
- shader.location = 0, 10
- try:
- links.new(shader.outputs[0], shout.inputs[0])
- except:
- link_fail = True
-
- if cmat.emit > 0.001:
- if (not shader.type == 'ShaderNodeEmission' and not
- cmat.raytrace_mirror.reflect_factor > 0.001 and not cmat_is_transp):
-
- collect_report("INFO: Mix EMISSION shader node for: " + cmat.name)
- TreeNodes.nodes.remove(shader)
- shader = TreeNodes.nodes.new('ShaderNodeEmission')
- shader.location = 0, 200
- try:
- links.new(shader.outputs[0], shout.inputs[0])
- except:
- link_fail = True
- else:
- if not Add_Emission:
- collect_report("INFO: Add EMISSION shader node for: " + cmat.name)
- shout.location = 600, 100
- Add_Emission = TreeNodes.nodes.new('ShaderNodeAddShader')
- Add_Emission.location = 370, 100
-
- shem = TreeNodes.nodes.new('ShaderNodeEmission')
- shem.location = 0, 200
- try:
- links.new(Add_Emission.outputs[0], shout.inputs[0])
- links.new(shem.outputs[0], Add_Emission.inputs[1])
- links.new(shader.outputs[0], Add_Emission.inputs[0])
- except:
- link_fail = True
-
- shem.inputs['Color'].default_value = (cmat.diffuse_color.r,
- cmat.diffuse_color.g,
- cmat.diffuse_color.b, 1)
- shem.inputs['Strength'].default_value = cmat.emit
-
- if cmat.translucency > 0.001:
- collect_report("INFO: Add BSDF_TRANSLUCENT shader node for: " + cmat.name)
- shout.location = 770, 330
- Add_Translucent = TreeNodes.nodes.new('ShaderNodeAddShader')
- Add_Translucent.location = 580, 490
-
- shtsl = TreeNodes.nodes.new('ShaderNodeBsdfTranslucent')
- shtsl.location = 400, 350
- try:
- links.new(Add_Translucent.outputs[0], shout.inputs[0])
- links.new(shtsl.outputs[0], Add_Translucent.inputs[1])
-
- if Add_Emission:
- links.new(Add_Emission.outputs[0], Add_Translucent.inputs[0])
- else:
- links.new(shader.outputs[0], Add_Translucent.inputs[0])
- except:
- link_fail = True
-
- shtsl.inputs['Color'].default_value = (cmat.translucency,
- cmat.translucency,
- cmat.translucency, 1)
- if sculpt_paint is False:
- shader.inputs['Color'].default_value = (cmat.diffuse_color.r,
- cmat.diffuse_color.g,
- cmat.diffuse_color.b, 1)
- else:
- # Create Clay Material (Diffuse, Glossy, Layer Weight)
- shader.inputs['Color'].default_value = PAINT_SC_COLOR
- shader.inputs['Roughness'].default_value = 0.9486
-
- # remove Color Ramp and links from the default shader and reroute
- try:
- shout.location = 400, 0
- for link in links:
- links.remove(link)
-
- clay_frame = TreeNodes.nodes.new('NodeFrame')
- clay_frame.name = 'Clay Material'
- clay_frame.label = 'Clay Material'
-
- sh_glossy = TreeNodes.nodes.new('ShaderNodeBsdfGlossy')
- sh_glossy.location = 0, 200
- sh_glossy.inputs['Color'].default_value = CLAY_GLOSSY
- sh_mix = TreeNodes.nodes.new('ShaderNodeMixShader')
- sh_mix.location = 200, 0
- sh_weight = TreeNodes.nodes.new('ShaderNodeLayerWeight')
- sh_weight.location = 0, 350
- links.new(sh_mix.outputs[0], shout.inputs[0])
- links.new(sh_weight.outputs[1], sh_mix.inputs[0])
- links.new(shader.outputs[0], sh_mix.inputs[1])
- links.new(sh_glossy.outputs[0], sh_mix.inputs[2])
- # set frame as parent to everything
- for clay_node in (shader, sh_glossy, sh_mix, sh_weight):
- clay_node.parent = clay_frame
- except:
- collect_report("ERROR: Failure to create Clay Material")
-
- if not sculpt_paint:
- if shader.type == 'ShaderNodeBsdfDiffuse':
- shader.inputs['Roughness'].default_value = cmat.specular_intensity
-
- if shader.type == 'ShaderNodeBsdfGlossy':
- shader.inputs['Roughness'].default_value = sqrt(max(1 - cmat.raytrace_mirror.gloss_factor, 0.0))
-
- if shader.type == 'ShaderNodeBsdfGlass':
- shader.inputs['Roughness'].default_value = sqrt(max(1 - cmat.raytrace_mirror.gloss_factor, 0.0))
- shader.inputs['IOR'].default_value = cmat.raytrace_transparency.ior
-
- if shader.type == 'ShaderNodeEmission':
- shader.inputs['Strength'].default_value = cmat.emit
-
- # texture presence check
- is_textures = False
-
- for tex in cmat.texture_slots:
- if tex:
- if not is_textures:
- is_textures = True
- break
-
- if is_textures:
- # collect the texture nodes created
- # for spreading a bit the texture nodes
- tex_node_collect = []
-
- sM = True
-
- for tex in cmat.texture_slots:
- sT = False
- tex_use = getattr(tex, "use", None)
- baked_path = None
- if tex_use:
- tex_node_loc = -200, 450
- ma_alpha = getattr(tex, "use_map_alpha", None)
- sM = (False if ma_alpha else True)
- img = None
-
- if tex.texture.type == 'IMAGE':
- if sc.mat_context_menu.EXTRACT_ALPHA and tex.texture.use_alpha:
- if (not
- os_path.exists(bpy.path.abspath(tex.texture.image.filepath + "_BAKING.png")) or
- sc.mat_context_menu.EXTRACT_OW):
- baked_path = BakingText(tex, 'ALPHA')
-
- if baked_path:
- try:
- img = bpy.data.images.load(baked_path)
- collect_report("INFO: Loading Baked texture path:")
- collect_report(baked_path)
- except:
- collect_report("ERROR: Baked image could not be loaded")
- else:
- has_image = getattr(tex.texture, "image", None)
- if has_image:
- img = has_image
-
- if img:
- img_name = (img.name if hasattr(img, "name") else "NO NAME")
- shtext = TreeNodes.nodes.new('ShaderNodeTexImage')
- shtext.location = tex_node_loc
- shtext.hide = True
- shtext.width_hidden = 150
- shtext.image = img
- shtext.name = img_name
- shtext.label = "Image " + img_name
- if baked_path:
- shtext.use_custom_color = True
- shtext.color = NODE_COLOR
- collect_report("INFO: Creating Image Node for image: " + img_name)
- tex_node_collect.append(shtext)
- sT = True
- else:
- collect_report("ERROR: A problem occurred with loading an image for {} "
- "(possibly missing)".format(tex.texture.name))
- else:
- if sc.mat_context_menu.EXTRACT_PTEX or (sc.mat_context_menu.EXTRACT_ALPHA and ma_alpha):
- if (not os_path.exists(bpy.path.abspath(tex.texture.name + "_PTEXT.jpg")) or
- sc.mat_context_menu.EXTRACT_OW):
- tex_type = tex.texture.type.lower()
- collect_report("Attempting to Extract Procedural Texture type: " + tex_type)
- baked_path = BakingText(tex, 'PTEX', tex_type)
-
- if baked_path:
- try:
- img = bpy.data.images.load(baked_path)
- collect_report("Loading Baked texture path:")
- collect_report(baked_path)
- img_name = (img.name if hasattr(img, "name") else "NO NAME")
- shtext = TreeNodes.nodes.new('ShaderNodeTexImage')
- shtext.location = tex_node_loc
- shtext.hide = True
- shtext.width_hidden = 150
- shtext.image = img
- shtext.name = img_name
- shtext.label = "Baked Image " + img_name
- shtext.use_custom_color = True
- shtext.color = NODE_COLOR
- collect_report("Creating Image Node for baked image: " + img_name)
- tex_node_collect.append(shtext)
- sT = True
- except:
- collect_report("ERROR: Failure to load baked image: " + img_name)
- else:
- collect_report("ERROR: Failure during baking, no images loaded")
-
- if sculpt_paint is False:
- if (cmat_is_transp and cmat.raytrace_transparency.ior == 1 and
- not cmat.raytrace_mirror.use and sM):
-
- if not shader.type == 'ShaderNodeBsdfTransparent':
- collect_report("INFO: Make TRANSPARENT shader node for: " + cmat.name)
- TreeNodes.nodes.remove(shader)
- shader = TreeNodes.nodes.new('ShaderNodeBsdfTransparent')
- shader.location = 0, 470
- try:
- links.new(shader.outputs[0], shout.inputs[0])
- except:
- link_fail = True
-
- shader.inputs['Color'].default_value = (cmat.diffuse_color.r,
- cmat.diffuse_color.g,
- cmat.diffuse_color.b, 1)
-
- if sT and sculpt_paint is False:
- if tex.use_map_color_diffuse:
- try:
- links.new(shtext.outputs[0], shader.inputs[0])
- except:
- pass
- if tex.use_map_emit:
- if not Add_Emission:
- collect_report("INFO: Mix EMISSION + Texture shader node for: " + cmat.name)
- intensity = 0.5 + (tex.emit_factor / 2)
-
- shout.location = 550, 330
- Add_Emission = TreeNodes.nodes.new('ShaderNodeAddShader')
- Add_Emission.name = "Add_Emission"
- Add_Emission.location = 370, 490
-
- shem = TreeNodes.nodes.new('ShaderNodeEmission')
- shem.location = 180, 380
-
- try:
- links.new(Add_Emission.outputs[0], shout.inputs[0])
- links.new(shem.outputs[0], Add_Emission.inputs[1])
- links.new(shader.outputs[0], Add_Emission.inputs[0])
- links.new(shtext.outputs[0], shem.inputs[0])
- except:
- link_fail = True
-
- shem.inputs['Color'].default_value = (cmat.diffuse_color.r,
- cmat.diffuse_color.g,
- cmat.diffuse_color.b, 1)
- shem.inputs['Strength'].default_value = intensity * 2
-
- if tex.use_map_mirror:
- try:
- links.new(shtext.outputs[0], shader.inputs[0])
- except:
- link_fail = True
-
- if tex.use_map_translucency:
- if not Add_Translucent:
- collect_report("INFO: Add Translucency + Texture shader node for: " + cmat.name)
-
- intensity = 0.5 + (tex.emit_factor / 2)
- shout.location = 550, 330
- Add_Translucent = TreeNodes.nodes.new('ShaderNodeAddShader')
- Add_Translucent.name = "Add_Translucent"
- Add_Translucent.location = 370, 290
-
- shtsl = TreeNodes.nodes.new('ShaderNodeBsdfTranslucent')
- shtsl.location = 180, 240
- try:
- links.new(shtsl.outputs[0], Add_Translucent.inputs[1])
-
- if Add_Emission:
- links.new(Add_Translucent.outputs[0], shout.inputs[0])
- links.new(Add_Emission.outputs[0], Add_Translucent.inputs[0])
- pass
- else:
- links.new(Add_Translucent.outputs[0], shout.inputs[0])
- links.new(shader.outputs[0], Add_Translucent.inputs[0])
-
- links.new(shtext.outputs[0], shtsl.inputs[0])
- except:
- link_fail = True
-
- if tex.use_map_alpha:
- if not Mix_Alpha:
- collect_report("INFO: Mix Alpha + Texture shader node for: " + cmat.name)
-
- shout.location = 750, 330
- Mix_Alpha = TreeNodes.nodes.new('ShaderNodeMixShader')
- Mix_Alpha.name = "Add_Alpha"
- Mix_Alpha.location = 570, 290
- sMask = TreeNodes.nodes.new('ShaderNodeBsdfTransparent')
- sMask.location = 250, 180
- tMask, imask = None, None
-
- # search if the texture node already exists, if not create
- nodes = getattr(cmat.node_tree, "nodes", None)
- img_name = getattr(img, "name", "NO NAME")
- for node in nodes:
- if type(node) == bpy.types.ShaderNodeTexImage:
- node_name = getattr(node, "name")
- if img_name in node_name:
- tMask = node
- collect_report("INFO: Using existing Texture Node for Mask: " + node_name)
- break
-
- if tMask is None:
- tMask = TreeNodes.nodes.new('ShaderNodeTexImage')
- tMask.location = tex_node_loc
- tex_node_collect.append(tMask)
-
- try:
- file_path = getattr(img, "filepath", None)
- if file_path:
- imask = bpy.data.images.load(file_path)
- else:
- imask = bpy.data.images.get(img_name)
- collect_report("INFO: Attempting to load image for Mask: " + img_name)
- except:
- collect_report("ERROR: Failure to load image for Mask: " + img_name)
-
- if imask:
- tMask.image = imask
-
- if tMask:
- try:
- links.new(Mix_Alpha.inputs[0], tMask.outputs[1])
- links.new(shout.inputs[0], Mix_Alpha.outputs[0])
- links.new(sMask.outputs[0], Mix_Alpha.inputs[1])
-
- if not Add_Translucent:
- if Add_Emission:
- links.new(Mix_Alpha.inputs[2], Add_Emission.outputs[0])
- else:
- links.new(Mix_Alpha.inputs[2], shader.outputs[0])
- else:
- links.new(Mix_Alpha.inputs[2], Add_Translucent.outputs[0])
- except:
- link_fail = True
- else:
- collect_report("ERROR: Mix Alpha could not be created "
- "(mask image could not be loaded)")
-
- if tex.use_map_normal:
- t = TreeNodes.nodes.new('ShaderNodeRGBToBW')
- t.location = -0, 300
- try:
- links.new(t.outputs[0], shout.inputs[2])
- links.new(shtext.outputs[1], t.inputs[0])
- except:
- link_fail = True
-
- if sculpt_paint:
- try:
- # create a new image for texture painting and make it active
- img_size = (int(sc.mat_context_menu.img_bake_size) if
- sc.mat_context_menu.img_bake_size else 1024)
- paint_mat_name = getattr(cmat, "name", "NO NAME")
- paint_img_name = "Paint Base Image {}".format(paint_mat_name)
- bpy.ops.image.new(name=paint_img_name, width=img_size, height=img_size,
- color=(1.0, 1.0, 1.0, 1.0), alpha=True, float=False)
-
- img = bpy.data.images.get(paint_img_name)
- img_name = (img.name if hasattr(img, "name") else "NO NAME")
- shtext = TreeNodes.nodes.new('ShaderNodeTexImage')
- shtext.hide = True
- shtext.width_hidden = 150
- shtext.location = tex_node_loc
- shtext.image = img
- shtext.name = img_name
- shtext.label = "Paint: " + img_name
- shtext.use_custom_color = True
- shtext.color = NODE_COLOR_PAINT
- shtext.select = True
- collect_report("INFO: Creating Image Node for Painting: " + img_name)
- collect_report("WARNING: Don't forget to save it on Disk")
- tex_node_collect.append(shtext)
- except:
- collect_report("ERROR: Failed to create image and node for Texture Painting")
-
- # spread the texture nodes, create node frames if necessary
- # create texture coordinate and mapping too
- row_node = -1
- tex_node_collect_size = len(tex_node_collect)
- median_point = ((tex_node_collect_size / 2) * 100)
- check_frame = bool(tex_node_collect_size > 1)
-
- node_frame, tex_map = None, None
- node_f_coord, node_f_mix = None, None
- tex_map_collection, tex_map_coord = [], None
- tree_size, tree_tex_start = 0, 0
-
- if check_frame:
- node_frame = TreeNodes.nodes.new('NodeFrame')
- node_frame.name = 'Converter Textures'
- node_frame.label = 'Converter Textures'
-
- node_f_coord = TreeNodes.nodes.new('NodeFrame')
- node_f_coord.name = "Coordinates"
- node_f_coord.label = "Coordinates"
-
- node_f_mix = TreeNodes.nodes.new('NodeFrame')
- node_f_mix.name = "Mix"
- node_f_mix.label = "Mix"
-
- if tex_node_collect:
- tex_map_coord = TreeNodes.nodes.new('ShaderNodeTexCoord')
- tex_map_coord.location = -900, 575
-
- # precalculate the depth of the inverted tree
- tree_size = int(ceil(log2(tex_node_collect_size)))
- # offset the start of the mix nodes by the depth of the tree
- tree_tex_start = ((tree_size + 1) * 150)
-
- for node_tex in tex_node_collect:
- row_node += 1
- col_node_start = (median_point - (-(row_node * 50) + median_point))
- tex_node_row = tree_tex_start + 300
- mix_node_row = tree_tex_start + 620
- tex_node_loc = (-(tex_node_row), col_node_start)
-
- try:
- node_tex.location = tex_node_loc
- if check_frame:
- node_tex.parent = node_frame
- else:
- node_tex.hide = False
-
- tex_node_name = getattr(node_tex, "name", "NO NAME")
- tex_map_name = "Mapping: {}".format(tex_node_name)
- tex_map = TreeNodes.nodes.new('ShaderNodeMapping')
- tex_map.location = (-(mix_node_row), col_node_start)
- tex_map.width = 240
- tex_map.hide = True
- tex_map.width_hidden = 150
- tex_map.name = tex_map_name
- tex_map.label = tex_map_name
- tex_map_collection.append(tex_map)
- links.new(tex_map.outputs[0], node_tex.inputs[0])
- except:
- link_fail = True
- continue
-
- if tex_map_collection:
- tex_mix_start = len(tex_map_collection) / 2
- row_map_start = -(tree_tex_start + 850)
-
- if tex_map_coord:
- tex_map_coord.location = (row_map_start,
- (median_point - (tex_mix_start * 50)))
-
- for maps in tex_map_collection:
- try:
- if node_f_coord:
- maps.parent = node_f_coord
- else:
- maps.hide = False
-
- links.new(maps.inputs[0], tex_map_coord.outputs['UV'])
- except:
- link_fail = True
- continue
-
- # create mix nodes to connect texture nodes to the shader input
- # sculpt mode doesn't need them
- if check_frame and not sculpt_paint:
- mix_node_pairs = loop_node_from_list(TreeNodes, links, tex_node_collect,
- 0, tree_tex_start, median_point, node_f_mix)
-
- for n in range(1, tree_size):
- mix_node_pairs = loop_node_from_list(TreeNodes, links, mix_node_pairs,
- n, tree_tex_start, median_point, node_f_mix)
- try:
- for node in mix_node_pairs:
- links.new(node.outputs[0], shader.inputs[0])
- except:
- link_fail = True
-
- mix_node_pairs = []
-
- tex_node_collect, tex_map_collection = [], []
-
- if link_fail:
- collect_report("ERROR: Some of the node links failed to connect")
-
- else:
- collect_report("No textures in the Scene, no Image Nodes to add")
-
- bpy.context.scene.render.engine = 'CYCLES'
-
-
-def loop_node_from_list(TreeNodes, links, node_list, loc, start, median_point, frame):
- row = 1
- mix_nodes = []
- node_list_size = len(node_list)
- tuplify = [tuple(node_list[s:s + 2]) for s in range(0, node_list_size, 2)]
- for nodes in tuplify:
- row += 1
- create_mix = create_mix_node(TreeNodes, links, nodes, loc, start,
- median_point, row, frame)
- if create_mix:
- mix_nodes.append(create_mix)
- return mix_nodes
-
-
-def create_mix_node(TreeNodes, links, nodes, loc, start, median_point, row, frame):
- mix_node = TreeNodes.nodes.new('ShaderNodeMixRGB')
- mix_node.name = "MIX level: " + str(loc)
- mix_node.label = "MIX level: " + str(loc)
- mix_node.use_custom_color = True
- mix_node.color = NODE_COLOR_MIX
- mix_node.hide = True
- mix_node.width_hidden = 75
-
- if frame:
- mix_node.parent = frame
- mix_node.location = -(start - loc * 175), ((median_point / 4) + (row * 50))
-
- try:
- if len(nodes) > 1:
- links.new(nodes[0].outputs[0], mix_node.inputs["Color2"])
- links.new(nodes[1].outputs[0], mix_node.inputs["Color1"])
- elif len(nodes) == 1:
- links.new(nodes[0].outputs[0], mix_node.inputs["Color1"])
- except:
- collect_report("ERROR: Link failed for mix node {}".format(mix_node.label))
- return mix_node
-
-
-def unwrap_active_object(context):
- enable_unwrap = context.scene.mat_context_menu.UV_UNWRAP
- if enable_unwrap:
- obj_name = getattr(context.active_object, "name", "UNNAMED OBJECT")
- try:
- # it's possible that the active object would fail UV Unwrap
- bpy.ops.object.editmode_toggle()
- bpy.ops.uv.unwrap(method='ANGLE_BASED', margin=0.001)
- bpy.ops.object.editmode_toggle()
- collect_report("INFO: UV Unwrapping active object {}".format(obj_name))
- except:
- collect_report("ERROR: UV Unwrapping failed for "
- "active object {}".format(obj_name))
-
-
-# -----------------------------------------------------------------------------
-# Operator Classes
-
-class mllock(Operator):
- bl_idname = "ml.lock"
- bl_label = "Lock"
- bl_description = "Lock/unlock this material against modification by conversions"
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return (c_is_cycles_addon_enabled() and c_data_has_materials())
-
- def execute(self, context):
- cmat = bpy.context.selected_objects[0].active_material
- TreeNodes = cmat.node_tree
- for n in TreeNodes.nodes:
- if n.type == 'ShaderNodeOutputMaterial':
- n.label = "" if n.label == "Locked" else "Locked"
-
- return {'FINISHED'}
-
-
-class mlrefresh(Operator):
- bl_idname = "ml.refresh"
- bl_label = "Convert All Materials"
- bl_description = ("Convert All Materials in the scene from non-nodes to Cycles\n"
- "Needs saving the .blend file first")
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return (bpy.data.filepath != "" and c_is_cycles_addon_enabled() and
- c_data_has_materials())
-
- def execute(self, context):
- AutoNodeInitiate(False, self)
-
- if CHECK_AUTONODE is True:
- unwrap_active_object(context)
-
- collect_report("Conversion finished !", False, True)
-
- return {'FINISHED'}
-
-
-class mlrefresh_active(Operator):
- bl_idname = "ml.refresh_active"
- bl_label = "Convert All Materials From Active Object"
- bl_description = ("Convert all Active Object's Materials from non-nodes to Cycles\n"
- "Needs saving the .blend file first")
- bl_options = {'REGISTER', 'UNDO'}
-
- @classmethod
- def poll(cls, context):
- return (bpy.data.filepath != "" and c_is_cycles_addon_enabled() and
- c_data_has_materials() and context.active_object is not None)
-
- def execute(self, context):
- AutoNodeInitiate(True, self)
- if CHECK_AUTONODE is True:
- unwrap_active_object(context)
-
- collect_report("Conversion finished !", False, True)
-
- return {'FINISHED'}
-
-
-class mlrestore(Operator):
- bl_idname = "ml.restore"
- bl_label = "Switch Between Renderers"
- bl_description = ("Switch between Renderers \n"
- "(Doesn't create new nor converts existing materials)")
- bl_options = {'REGISTER', 'UNDO'}
-
- switcher: BoolProperty(
- name="Use Nodes",
- description="When restoring, switch Use Nodes On/Off",
- default=True
- )
- renderer: EnumProperty(
- name="Renderer",
- description="Choose Cycles or Blender Internal",
- items=(
- ('CYCLES', "Cycles", "Switch to Cycles"),
- ('BI', "Blender Internal", "Switch to Blender Internal")
- ),
- default='CYCLES',
- )
-
- @classmethod
- def poll(cls, context):
- return c_is_cycles_addon_enabled()
-
- def execute(self, context):
- switch = "ON" if self.switcher else "OFF"
- AutoNodeSwitch(self.renderer, switch, self)
-
- return {'FINISHED'}
-
-
-def register():
- bpy.utils.register_module(__name__)
- pass
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
- pass
-
-
-if __name__ == "__main__":
- register()