[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