[Bf-extensions-cvs] [e31cec5] master: Added Cycles Automatic Materials addon from https://bitbucket.org/Theo_Friberg/cycles-automatic-materials-addon
Théo Friberg
noreply at git.blender.org
Sun Aug 9 19:14:12 CEST 2015
Commit: e31cec5bf243f00441c7dad7a775ec4722f829d3
Author: Théo Friberg
Date: Sun Aug 9 19:42:54 2015 +0300
Branches: master
https://developer.blender.org/rBACe31cec5bf243f00441c7dad7a775ec4722f829d3
Added Cycles Automatic Materials addon from https://bitbucket.org/Theo_Friberg/cycles-automatic-materials-addon
===================================================================
A automat/AdjOp.py
A automat/AutoOp.py
A automat/JSONOps.py
A automat/__init__.py
A automat/adj_material.json
A automat/automatic_material.json
A automat/blur.json
A automat/seamless_vector.json
===================================================================
diff --git a/automat/AdjOp.py b/automat/AdjOp.py
new file mode 100644
index 0000000..846ba77
--- /dev/null
+++ b/automat/AdjOp.py
@@ -0,0 +1,118 @@
+# Copyright 2015 Théo Friberg under GNU GPL 3
+
+if "bpy" in locals():
+ import importlib
+ importlib.reload(JSONOps)
+else:
+ from . import JSONOps
+
+import bpy
+import os
+
+class AdjustableOperatorFromTexture(bpy.types.Operator):
+
+ """This operator generates adjustable materials from textures in Cycles.
+
+This is a subclass from bpy.types.Operator.
+"""
+
+ # Metadata of the operator
+
+ bl_idname = "com.new_adj_automat"
+ bl_label = "Adjustable 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")
+
+
+
+
+ def execute(self, context):
+
+ """This is the main runnable method of the operator.
+
+This creates all the node setup."""
+
+ # Create the material
+
+ mat = bpy.data.materials.new("Material")
+
+ mat.use_nodes = True
+ nodes = mat.node_tree.nodes
+
+ # Empty whatever nodes we allready had.
+
+ for node in nodes.keys():
+ nodes.remove(nodes[node])
+
+ nodes_dict = {}
+
+ # Create the main part of the material
+
+ nodes_dict = JSONOps.inflateFile(mat, os.path.dirname(
+ os.path.realpath(__file__))+os.sep+
+ "adj_material.json")
+
+ # We create all of our blurs
+
+ blurs = [
+
+ JSONOps.inflateFile(mat, os.path.dirname(os.path.realpath(__file__))+
+ os.sep+"blur.json", -2500, -300),
+ JSONOps.inflateFile(mat, os.path.dirname(os.path.realpath(__file__))+
+ os.sep+"blur.json", -2300, 300)
+ ]
+
+ # We set one of our blurs to be stronger
+
+ blurs[1]["Blur strength"].outputs[0].default_value = 1000
+
+ # We link the blurs up to the rest of the material
+
+ links = mat.node_tree.links
+
+ links.new(blurs[1]["Correct strength vector math"].outputs[0],
+ nodes_dict["Greater Than"].inputs[0])
+ links.new(blurs[0]["Correct strength vector math"].outputs[0],
+ nodes_dict["Bumpmap Mix RGB"].inputs[2])
+ links.new(nodes_dict["Texture Co-ordinate"].outputs["UV"],
+ blurs[0]["Add noise"].inputs[0])
+
+ # We load the images
+
+ image_data = bpy.data.images.load(self.filepath)
+ nodes_dict["Color Image"].image = image_data
+ nodes_dict["Bump Image"].image = image_data
+
+ # 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.
+
+ pass
+
+ # Tell that all went well
+
+ return {"FINISHED"}
+
+ def invoke(self, context, event):
+
+ """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"}
diff --git a/automat/AutoOp.py b/automat/AutoOp.py
new file mode 100644
index 0000000..480aaf1
--- /dev/null
+++ b/automat/AutoOp.py
@@ -0,0 +1,195 @@
+# Copyright 2015 Théo Friberg under GNU GPL 3
+
+if "bpy" in locals():
+ import importlib
+ importlib.reload(JSONOps)
+else:
+ from . import JSONOps
+
+import bpy
+import os
+import glob
+
+class AutomatOperatorFromTexture(bpy.types.Operator):
+
+ """This operator generates automatic materials from textures in Cycles."""
+
+ # Metadata of the operator
+
+ 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).")
+
+ def execute(self, context):
+
+ """This is the main runnable method of the operator.
+
+This creates all the node setup."""
+
+ # Create the material
+
+ mat = bpy.data.materials.new(self.filename)
+
+ mat.use_nodes = True
+ nodes = mat.node_tree.nodes
+
+ # Empty whatever nodes we allready had.
+
+ for node in nodes.keys():
+ nodes.remove(nodes[node])
+
+ nodes_dict = {}
+
+ # Create the main part of the material
+
+ nodes_dict = JSONOps.inflateFile(mat, os.path.dirname(
+ os.path.realpath(__file__))+os.sep+
+ "automatic_material.json")
+
+
+
+ # We load the images
+
+ 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"])
+
+ # Below we check potential maps
+
+ modified_fname = self.filename.split(".")
+
+ # Check if we are dealing with maps generated with CrazyBump.
+ # If so is the case, the color map is by default suffixed with _COLOR
+
+ known_scheme = False
+
+ if modified_fname[0][-6:] == "_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)
+
+ # We check if we can find a Specularity Map
+
+ specmap = ""
+
+ for file in other_files:
+ if "spec" in os.path.split(file)[-1].lower():
+ specmap = file
+ break
+
+ if len(specmap) > 0:
+
+ 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"])
+
+ # We check if we can find a Normal Map
+
+ normalmap = ""
+
+ 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"])
+
+ # We check if we can find a Bump Map
+
+ bumpmap = ""
+
+ 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.
+
+ pass
+
+ # Tell that all went well
+
+ return {"FINISHED"}
+
+ def invoke(self, context, event):
+
+ """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"}
diff --git a/automat/JSONOps.py b/automat/JSONOps.py
new file mode 100644
index 0000000..b080084
--- /dev/null
+++ b/automat/JSONOps.py
@@ -0,0 +1,136 @@
+# Copyright
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list