Newer
Older
# Copyright 2015 Théo Friberg under GNU GPL 3
if "bpy" in locals():
import bpy
import os
import glob
class AutomatOperatorFromTexture(bpy.types.Operator):
"""This operator generates automatic materials from textures in Cycles"""
bl_idname = "com.new_automat"
bl_label = "Automatic Material from Image"
bl_options = {"UNDO"}
# Variables used for storing the filepath given by blender's file manager
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
filename: bpy.props.StringProperty()
directory: bpy.props.StringProperty(subtype="FILE_PATH")
make_seamless: bpy.props.BoolProperty(
name="Make Seamless",
description="Make tileable (removes visible borders of the image)",
)
"""This is the main runnable method of the operator.
This creates all the node setup."""
mat.use_nodes = True
nodes = mat.node_tree.nodes
for node in nodes.keys():
nodes.remove(nodes[node])
nodes_dict = JSONOps.inflateFile(mat, os.path.dirname(
os.path.realpath(__file__))+os.sep+
"automatic_material.json")
image_data = bpy.data.images.load(self.filepath)
nodes_dict["Color Image"].image = image_data
# We check if the texture must be made seamless
if self.make_seamless:
seamless_vector = JSONOps.inflateFile(mat, os.path.dirname(os.path.realpath(__file__))+os.sep+"seamless_vector.json", -3000, 0)
links = mat.node_tree.links
links.new(seamless_vector["Pick Vector"].outputs["Color"], nodes_dict["Color Image"].inputs["Vector"])
# Check if we are dealing with maps generated with CrazyBump.
# If so is the case, the color map is by default suffixed with _COLOR
# We are dealing with CrazyBump and we remove the suffix
modified_fname[0] = modified_fname[0][:-6]
known_scheme = True
other_files = []
folder = os.path.split(self.filepath)[0]+os.path.sep+"*"
pattern = folder + ".".join(modified_fname[:-1])+"*."+modified_fname[-1]
other_files = glob.glob(pattern)
for file in other_files:
if "spec" in os.path.split(file)[-1].lower():
specmap = file
break
spec_map = nodes.new("ShaderNodeTexImage")
spec_map.location = [nodes_dict["Adjust reflectivity"].location[0],
nodes_dict["Adjust reflectivity"].location[1]+50]
spec_map.label = "Specularity Map"
nodes.remove(nodes_dict["Adjust reflectivity"])
spec_map.image = bpy.data.images.load(specmap)
links = mat.node_tree.links
links.new(spec_map.outputs["Color"],
nodes_dict["Mix Shaders"].inputs[0])
if self.make_seamless:
links.new(seamless_vector["Pick Vector"].outputs["Color"], spec_map.inputs["Vector"])
for file in other_files:
if "normal" in os.path.split(file)[-1].lower() or ".".join(os.path.split(file)[1].split(".") [:-1])[-4:] == "_NRM":
normalmap = file
break
if len(normalmap) > 0 and ((not "normal" in self.filename.lower()) or known_scheme):
normal_map = nodes.new("ShaderNodeTexImage")
normal_map.location = [nodes_dict["Color Image"].location[0],
nodes_dict["Color Image"].location[1]-240]
normal_map.label = "Normal Map"
normal_map.image = bpy.data.images.load(normalmap)
links = mat.node_tree.links
normal = nodes.new("ShaderNodeNormalMap")
normal.location = [nodes_dict["Convert to Bump Map"].location[0],
nodes_dict["Convert to Bump Map"].location[1]]
nodes.remove(nodes_dict["Convert to Bump Map"])
links.new(normal_map.outputs["Color"],
normal.inputs[1])
links.new(normal.outputs["Normal"],
nodes_dict["Diffuse Component"].inputs[2])
links.new(normal.outputs["Normal"],
nodes_dict["Glossy Component"].inputs[2])
if self.make_seamless:
links.new(seamless_vector["Pick Vector"].outputs["Color"], normal_map.inputs["Vector"])
for file in other_files:
if "bump" in os.path.split(file.lower())[-1]:
bumpmap = file
break
if len(bumpmap) > 0 and not "bump" in self.filename.lower() and not len(normalmap) > 0:
bump_map = nodes.new("ShaderNodeTexImage")
bump_map.location = [nodes_dict["Color Image"].location[0],
nodes_dict["Color Image"].location[1]-240]
bump_map.label = "Bump Map"
bump_map.image = bpy.data.images.load(bumpmap)
links = mat.node_tree.links
links.new(bump_map.outputs["Color"], nodes_dict["Convert to Bump Map"].inputs[2])
if self.make_seamless:
links.new(seamless_vector["Pick Vector"].outputs["Color"], bump_map.inputs["Vector"])
# Try to add the material to the selected object
try:
bpy.context.object.data.materials.append(mat)
except AttributeError:
# If there is no object with materials selected,
# don't add the material to anythinng.
"""This method opens the file browser. After that, the
execute(...) method gets ran, creating the node setup.
It also checks that the render engine is Cycles. """
if bpy.context.scene.render.engine == 'CYCLES':
self.filename = ""
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
else:
self.report({'ERROR'}, "Can't generate Cycles material with Blender"
"internal as active renderer.")
return {"FINISHED"}