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:
authorMaurice Raybaud <mauriceraybaud@hotmail.fr>2017-01-29 23:28:41 +0300
committerMaurice Raybaud <mauriceraybaud@hotmail.fr>2017-01-29 23:28:41 +0300
commit6f40579d5bd29e235b8aa372297de5eabf23aab7 (patch)
treeaf9e95de45d0feb630600712e111ef8e2a9351fc /render_povray
parentbafb8d353d64aa62be4dfeb1892aab4e2625053d (diff)
Added Basic Nodes support by Lanuhum
Diffstat (limited to 'render_povray')
-rw-r--r--render_povray/__init__.py577
-rw-r--r--render_povray/nodes.py1299
-rw-r--r--render_povray/primitives.py84
-rw-r--r--render_povray/render.py42
-rw-r--r--render_povray/shading.py520
-rw-r--r--render_povray/ui.py151
6 files changed, 2609 insertions, 64 deletions
diff --git a/render_povray/__init__.py b/render_povray/__init__.py
index 31b7671b..85c4e608 100644
--- a/render_povray/__init__.py
+++ b/render_povray/__init__.py
@@ -1,4 +1,4 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
+# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -19,7 +19,7 @@
# <pep8 compliant>
bl_info = {
- "name": "POV-Ray 3.7",
+ "name": "POVRAY-3.7",
"author": "Campbell Barton, Silvio Falcinelli, Maurice Raybaud, "
"Constantin Rahn, Bastien Montagne, Leonid Desyatkov",
"version": (0, 0, 9),
@@ -41,10 +41,12 @@ if "bpy" in locals():
else:
import bpy
import addon_utils # To use some other addons
+ import nodeitems_utils #for Nodes
+ from nodeitems_utils import NodeCategory, NodeItem #for Nodes
from bpy.types import (
AddonPreferences,
PropertyGroup,
- Operator,
+ #Operator,
)
from bpy.props import (
StringProperty,
@@ -450,6 +452,548 @@ class RenderPovSettingsMaterial(PropertyGroup):
default="")
+
+ # NODES
+
+ def use_material_nodes_callback(self, context):
+ if hasattr(context.space_data, "tree_type"):
+ context.space_data.tree_type = 'ObjectNodeTree'
+ mat=context.object.active_material
+ if mat.pov.material_use_nodes:
+ mat.use_nodes=True
+ tree = mat.node_tree
+ tree.name=mat.name
+ links = tree.links
+ default = True
+ if len(tree.nodes) == 2:
+ o = 0
+ m = 0
+ for node in tree.nodes:
+ if node.type in {"OUTPUT","MATERIAL"}:
+ tree.nodes.remove(node)
+ default = True
+ for node in tree.nodes:
+ if node.bl_idname == 'PovrayOutputNode':
+ o+=1
+ if node.bl_idname == 'PovrayTextureNode':
+ m+=1
+ if o == 1 and m == 1:
+ default = False
+ elif len(tree.nodes) == 0:
+ default = True
+ else:
+ default = False
+ if default:
+ output = tree.nodes.new('PovrayOutputNode')
+ output.location = 200,200
+ tmap = tree.nodes.new('PovrayTextureNode')
+ tmap.location = 0,200
+ links.new(tmap.outputs[0],output.inputs[0])
+ tmap.select = True
+ tree.nodes.active = tmap
+ else:
+ mat.use_nodes=False
+
+
+ def use_texture_nodes_callback(self, context):
+ tex=context.object.active_material.active_texture
+ if tex.pov.texture_use_nodes:
+ tex.use_nodes=True
+ if len(tex.node_tree.nodes)==2:
+ for node in tex.node_tree.nodes:
+ if node.type in {"OUTPUT","CHECKER"}:
+ tex.node_tree.nodes.remove(node)
+ else:
+ tex.use_nodes=False
+
+ def node_active_callback(self, context):
+ items = []
+ mat=context.material
+ mat.node_tree.nodes
+ for node in mat.node_tree.nodes:
+ node.select=False
+ for node in mat.node_tree.nodes:
+ if node.name==mat.pov.material_active_node:
+ node.select=True
+ mat.node_tree.nodes.active=node
+
+ return node
+
+ def node_enum_callback(self, context):
+ items = []
+ mat=context.material
+ nodes=mat.node_tree.nodes
+ for node in nodes:
+ items.append(("%s"%node.name,"%s"%node.name,""))
+ return items
+
+ def pigment_normal_callback(self, context):
+ render = context.scene.pov.render
+ items = [("pigment", "Pigment", ""),("normal", "Normal", "")]
+ if render == 'hgpovray':
+ items = [("pigment", "Pigment", ""),("normal", "Normal", ""),("modulation", "Modulation", "")]
+ return items
+
+ def glow_callback(self, context):
+ scene = context.scene
+ ob = context.object
+ ob.pov.mesh_write_as_old = ob.pov.mesh_write_as
+ if scene.pov.render == 'uberpov' and ob.pov.glow:
+ ob.pov.mesh_write_as = 'NONE'
+ else:
+ ob.pov.mesh_write_as = ob.pov.mesh_write_as_old
+
+ material_use_nodes = BoolProperty(name="Use nodes", description="", update=use_material_nodes_callback, default=False)
+ material_active_node = EnumProperty(name="Active node", description="", items=node_enum_callback, update=node_active_callback)
+ preview_settings = BoolProperty(name="Preview Settings", description="",default=False)
+ object_preview_transform = BoolProperty(name="Transform object", description="",default=False)
+ object_preview_scale = FloatProperty(name="XYZ", min=0.5, max=2.0, default=1.0)
+ object_preview_rotate = FloatVectorProperty(name="Rotate", description="", min=-180.0, max=180.0,default=(0.0,0.0,0.0), subtype='XYZ')
+ object_preview_bgcontrast = FloatProperty(name="Contrast", min=0.0, max=1.0, default=0.5)
+
+
+###############################################################################
+# Povray Nodes
+###############################################################################
+class PovraySocketUniversal(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketUniversal'
+ bl_label = 'Povray Socket'
+ value_unlimited = bpy.props.FloatProperty(default=0.0)
+ value_0_1 = bpy.props.FloatProperty(min=0.0,max=1.0,default=0.0)
+ value_0_10 = bpy.props.FloatProperty(min=0.0,max=10.0,default=0.0)
+ value_000001_10 = bpy.props.FloatProperty(min=0.000001,max=10.0,default=0.0)
+ value_1_9 = bpy.props.IntProperty(min=1,max=9,default=1)
+ value_0_255 = bpy.props.IntProperty(min=0,max=255,default=0)
+ percent = bpy.props.FloatProperty(min=0.0,max=100.0,default=0.0)
+ def draw(self, context, layout, node, text):
+ space = context.space_data
+ tree = space.edit_tree
+ links=tree.links
+ if self.is_linked:
+ value=[]
+ for link in links:
+ if link.from_node==node:
+ inps=link.to_node.inputs
+ for inp in inps:
+ if inp.bl_idname=="PovraySocketFloat_0_1" and inp.is_linked:
+ prop="value_0_1"
+ if prop not in value:
+ value.append(prop)
+ if inp.bl_idname=="PovraySocketFloat_000001_10" and inp.is_linked:
+ prop="value_000001_10"
+ if prop not in value:
+ value.append(prop)
+ if inp.bl_idname=="PovraySocketFloat_0_10" and inp.is_linked:
+ prop="value_0_10"
+ if prop not in value:
+ value.append(prop)
+ if inp.bl_idname=="PovraySocketInt_1_9" and inp.is_linked:
+ prop="value_1_9"
+ if prop not in value:
+ value.append(prop)
+ if inp.bl_idname=="PovraySocketInt_0_255" and inp.is_linked:
+ prop="value_0_255"
+ if prop not in value:
+ value.append(prop)
+ if inp.bl_idname=="PovraySocketFloatUnlimited" and inp.is_linked:
+ prop="value_unlimited"
+ if prop not in value:
+ value.append(prop)
+ if len(value)==1:
+ layout.prop(self, "%s"%value[0], text=text)
+ else:
+ layout.prop(self, "percent", text="Percent")
+ else:
+ layout.prop(self, "percent", text=text)
+ def draw_color(self, context, node):
+ return (1, 0, 0, 1)
+
+class PovraySocketFloat_0_1(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketFloat_0_1'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.FloatProperty(description="Input node Value_0_1",min=0,max=1,default=0)
+ def draw(self, context, layout, node, text):
+ if self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text, slider=True)
+
+ def draw_color(self, context, node):
+ return (0.5, 0.7, 0.7, 1)
+
+class PovraySocketFloat_0_10(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketFloat_0_10'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.FloatProperty(description="Input node Value_0_10",min=0,max=10,default=0)
+ def draw(self, context, layout, node, text):
+ if node.bl_idname == 'ShaderNormalMapNode' and node.inputs[2].is_linked:
+ layout.label('')
+ self.hide_value=True
+ if self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text, slider=True)
+ def draw_color(self, context, node):
+ return (0.65, 0.65, 0.65, 1)
+
+class PovraySocketFloat_10(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketFloat_10'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.FloatProperty(description="Input node Value_10",min=-10,max=10,default=0)
+ def draw(self, context, layout, node, text):
+ if node.bl_idname == 'ShaderNormalMapNode' and node.inputs[2].is_linked:
+ layout.label('')
+ self.hide_value=True
+ if self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text, slider=True)
+ def draw_color(self, context, node):
+ return (0.65, 0.65, 0.65, 1)
+
+class PovraySocketFloatPositive(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketFloatPositive'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.FloatProperty(description="Input Node Value Positive", min=0.0, default=0)
+ def draw(self, context, layout, node, text):
+ if self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text, slider=True)
+ def draw_color(self, context, node):
+ return (0.045, 0.005, 0.136, 1)
+
+class PovraySocketFloat_000001_10(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketFloat_000001_10'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.FloatProperty(min=0.000001,max=10,default=0.000001)
+ def draw(self, context, layout, node, text):
+ if self.is_output or self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text, slider=True)
+ def draw_color(self, context, node):
+ return (1, 0, 0, 1)
+
+class PovraySocketFloatUnlimited(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketFloatUnlimited'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.FloatProperty(default = 0.0)
+ def draw(self, context, layout, node, text):
+ if self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text, slider=True)
+ def draw_color(self, context, node):
+ return (0.7, 0.7, 1, 1)
+
+class PovraySocketInt_1_9(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketInt_1_9'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.IntProperty(description="Input node Value_1_9",min=1,max=9,default=6)
+ def draw(self, context, layout, node, text):
+ if self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text)
+ def draw_color(self, context, node):
+ return (1, 0.7, 0.7, 1)
+
+class PovraySocketInt_0_256(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketInt_0_256'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.IntProperty(min=0,max=255,default=0)
+ def draw(self, context, layout, node, text):
+ if self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text)
+ def draw_color(self, context, node):
+ return (0.5, 0.5, 0.5, 1)
+
+
+class PovraySocketPattern(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketPattern'
+ bl_label = 'Povray Socket'
+
+ default_value = bpy.props.EnumProperty(
+ name="Pattern",
+ description="Select the pattern",
+ items=(('boxed', "Boxed", ""),('brick', "Brick", ""),('cells', "Cells", ""), ('checker', "Checker", ""),
+ ('granite', "Granite", ""),('leopard', "Leopard", ""),('marble', "Marble", ""),
+ ('onion', "Onion", ""),('planar', "Planar", ""), ('quilted', "Quilted", ""),
+ ('ripples', "Ripples", ""), ('radial', "Radial", ""),('spherical', "Spherical", ""),
+ ('spotted', "Spotted", ""), ('waves', "Waves", ""), ('wood', "Wood", ""),
+ ('wrinkles', "Wrinkles", "")),
+ default='granite')
+
+ def draw(self, context, layout, node, text):
+ if self.is_output or self.is_linked:
+ layout.label("Pattern")
+ else:
+ layout.prop(self, "default_value", text=text)
+
+ def draw_color(self, context, node):
+ return (1, 1, 1, 1)
+
+class PovraySocketColor(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketColor'
+ bl_label = 'Povray Socket'
+
+ default_value = bpy.props.FloatVectorProperty(
+ precision=4, step=0.01, min=0, soft_max=1,
+ default=(0.0, 0.0, 0.0), options={'ANIMATABLE'}, subtype='COLOR')
+
+ def draw(self, context, layout, node, text):
+ if self.is_output or self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text)
+
+ def draw_color(self, context, node):
+ return (1, 1, 0, 1)
+
+class PovraySocketColorRGBFT(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketColorRGBFT'
+ bl_label = 'Povray Socket'
+
+ default_value = bpy.props.FloatVectorProperty(
+ precision=4, step=0.01, min=0, soft_max=1,
+ default=(0.0, 0.0, 0.0), options={'ANIMATABLE'}, subtype='COLOR')
+ f = bpy.props.FloatProperty(default = 0.0,min=0.0,max=1.0)
+ t = bpy.props.FloatProperty(default = 0.0,min=0.0,max=1.0)
+ def draw(self, context, layout, node, text):
+ if self.is_output or self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self, "default_value", text=text)
+
+ def draw_color(self, context, node):
+ return (1, 1, 0, 1)
+
+class PovraySocketTexture(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketTexture'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.IntProperty()
+ def draw(self, context, layout, node, text):
+ layout.label(text)
+
+ def draw_color(self, context, node):
+ return (0, 1, 0, 1)
+
+
+
+class PovraySocketTransform(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketTransform'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.IntProperty(min=0,max=255,default=0)
+ def draw(self, context, layout, node, text):
+ layout.label(text)
+
+ def draw_color(self, context, node):
+ return (99/255, 99/255, 199/255, 1)
+
+class PovraySocketNormal(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketNormal'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.IntProperty(min=0,max=255,default=0)
+ def draw(self, context, layout, node, text):
+ layout.label(text)
+
+ def draw_color(self, context, node):
+ return (0.65, 0.65, 0.65, 1)
+
+class PovraySocketSlope(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketSlope'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.FloatProperty(min = 0.0, max = 1.0)
+ height = bpy.props.FloatProperty(min = 0.0, max = 10.0)
+ slope = bpy.props.FloatProperty(min = -10.0, max = 10.0)
+ def draw(self, context, layout, node, text):
+ if self.is_output or self.is_linked:
+ layout.label(text)
+ else:
+ layout.prop(self,'default_value',text='')
+ layout.prop(self,'height',text='')
+ layout.prop(self,'slope',text='')
+ def draw_color(self, context, node):
+ return (0, 0, 0, 1)
+
+class PovraySocketMap(bpy.types.NodeSocket):
+ bl_idname = 'PovraySocketMap'
+ bl_label = 'Povray Socket'
+ default_value = bpy.props.StringProperty()
+ def draw(self, context, layout, node, text):
+ layout.label(text)
+ def draw_color(self, context, node):
+ return (0.2, 0, 0.2, 1)
+
+class PovrayShaderNodeCategory(NodeCategory):
+ @classmethod
+ def poll(cls, context):
+ return context.space_data.tree_type == 'ObjectNodeTree'
+
+class PovrayTextureNodeCategory(NodeCategory):
+ @classmethod
+ def poll(cls, context):
+ return context.space_data.tree_type == 'TextureNodeTree'
+
+class PovraySceneNodeCategory(NodeCategory):
+ @classmethod
+ def poll(cls, context):
+ return context.space_data.tree_type == 'CompositorNodeTree'
+
+node_categories = [
+
+ PovrayShaderNodeCategory("SHADEROUTPUT", "Output", items=[
+ NodeItem("PovrayOutputNode"),
+ ]),
+
+ PovrayShaderNodeCategory("SIMPLE", "Simple texture", items=[
+ NodeItem("PovrayTextureNode"),
+ ]),
+
+ PovrayShaderNodeCategory("MAPS", "Maps", items=[
+ NodeItem("PovrayBumpMapNode"),
+ NodeItem("PovrayColorImageNode"),
+ NodeItem("ShaderNormalMapNode"),
+ NodeItem("PovraySlopeNode"),
+ NodeItem("ShaderTextureMapNode"),
+ NodeItem("ShaderNodeValToRGB"),
+ ]),
+
+ PovrayShaderNodeCategory("OTHER", "Other patterns", items=[
+ NodeItem("PovrayImagePatternNode"),
+ NodeItem("ShaderPatternNode"),
+ ]),
+
+ PovrayShaderNodeCategory("COLOR", "Color", items=[
+ NodeItem("PovrayPigmentNode"),
+ ]),
+
+ PovrayShaderNodeCategory("TRANSFORM", "Transform", items=[
+ NodeItem("PovrayMappingNode"),
+ NodeItem("PovrayMultiplyNode"),
+ NodeItem("PovrayModifierNode"),
+ NodeItem("PovrayTransformNode"),
+ NodeItem("PovrayValueNode"),
+ ]),
+
+ PovrayShaderNodeCategory("FINISH", "Finish", items=[
+ NodeItem("PovrayFinishNode"),
+ NodeItem("PovrayDiffuseNode"),
+ NodeItem("PovraySpecularNode"),
+ NodeItem("PovrayPhongNode"),
+ NodeItem("PovrayAmbientNode"),
+ NodeItem("PovrayMirrorNode"),
+ NodeItem("PovrayIridescenceNode"),
+ NodeItem("PovraySubsurfaceNode"),
+ ]),
+
+ PovrayShaderNodeCategory("CYCLES", "Cycles", items=[
+ NodeItem("ShaderNodeAddShader"),
+ NodeItem("ShaderNodeAmbientOcclusion"),
+ NodeItem("ShaderNodeAttribute"),
+ NodeItem("ShaderNodeBackground"),
+ NodeItem("ShaderNodeBlackbody"),
+ NodeItem("ShaderNodeBrightContrast"),
+ NodeItem("ShaderNodeBsdfAnisotropic"),
+ NodeItem("ShaderNodeBsdfDiffuse"),
+ NodeItem("ShaderNodeBsdfGlass"),
+ NodeItem("ShaderNodeBsdfGlossy"),
+ NodeItem("ShaderNodeBsdfHair"),
+ NodeItem("ShaderNodeBsdfRefraction"),
+ NodeItem("ShaderNodeBsdfToon"),
+ NodeItem("ShaderNodeBsdfTranslucent"),
+ NodeItem("ShaderNodeBsdfTransparent"),
+ NodeItem("ShaderNodeBsdfVelvet"),
+ NodeItem("ShaderNodeBump"),
+ NodeItem("ShaderNodeCameraData"),
+ NodeItem("ShaderNodeCombineHSV"),
+ NodeItem("ShaderNodeCombineRGB"),
+ NodeItem("ShaderNodeCombineXYZ"),
+ NodeItem("ShaderNodeEmission"),
+ NodeItem("ShaderNodeExtendedMaterial"),
+ NodeItem("ShaderNodeFresnel"),
+ NodeItem("ShaderNodeGamma"),
+ NodeItem("ShaderNodeGeometry"),
+ NodeItem("ShaderNodeGroup"),
+ NodeItem("ShaderNodeHairInfo"),
+ NodeItem("ShaderNodeHoldout"),
+ NodeItem("ShaderNodeHueSaturation"),
+ NodeItem("ShaderNodeInvert"),
+ NodeItem("ShaderNodeLampData"),
+ NodeItem("ShaderNodeLayerWeight"),
+ NodeItem("ShaderNodeLightFalloff"),
+ NodeItem("ShaderNodeLightPath"),
+ NodeItem("ShaderNodeMapping"),
+ NodeItem("ShaderNodeMaterial"),
+ NodeItem("ShaderNodeMath"),
+ NodeItem("ShaderNodeMixRGB"),
+ NodeItem("ShaderNodeMixShader"),
+ NodeItem("ShaderNodeNewGeometry"),
+ NodeItem("ShaderNodeNormal"),
+ NodeItem("ShaderNodeNormalMap"),
+ NodeItem("ShaderNodeObjectInfo"),
+ NodeItem("ShaderNodeOutput"),
+ NodeItem("ShaderNodeOutputLamp"),
+ NodeItem("ShaderNodeOutputLineStyle"),
+ NodeItem("ShaderNodeOutputMaterial"),
+ NodeItem("ShaderNodeOutputWorld"),
+ NodeItem("ShaderNodeParticleInfo"),
+ NodeItem("ShaderNodeRGB"),
+ NodeItem("ShaderNodeRGBCurve"),
+ NodeItem("ShaderNodeRGBToBW"),
+ NodeItem("ShaderNodeScript"),
+ NodeItem("ShaderNodeSeparateHSV"),
+ NodeItem("ShaderNodeSeparateRGB"),
+ NodeItem("ShaderNodeSeparateXYZ"),
+ NodeItem("ShaderNodeSqueeze"),
+ NodeItem("ShaderNodeSubsurfaceScattering"),
+ NodeItem("ShaderNodeTangent"),
+ NodeItem("ShaderNodeTexBrick"),
+ NodeItem("ShaderNodeTexChecker"),
+ NodeItem("ShaderNodeTexCoord"),
+ NodeItem("ShaderNodeTexEnvironment"),
+ NodeItem("ShaderNodeTexGradient"),
+ NodeItem("ShaderNodeTexImage"),
+ NodeItem("ShaderNodeTexMagic"),
+ NodeItem("ShaderNodeTexMusgrave"),
+ NodeItem("ShaderNodeTexNoise"),
+ NodeItem("ShaderNodeTexPointDensity"),
+ NodeItem("ShaderNodeTexSky"),
+ NodeItem("ShaderNodeTexVoronoi"),
+ NodeItem("ShaderNodeTexWave"),
+ NodeItem("ShaderNodeTexture"),
+ NodeItem("ShaderNodeUVAlongStroke"),
+ NodeItem("ShaderNodeUVMap"),
+ NodeItem("ShaderNodeValToRGB"),
+ NodeItem("ShaderNodeValue"),
+ NodeItem("ShaderNodeVectorCurve"),
+ NodeItem("ShaderNodeVectorMath"),
+ NodeItem("ShaderNodeVectorTransform"),
+ NodeItem("ShaderNodeVolumeAbsorption"),
+ NodeItem("ShaderNodeVolumeScatter"),
+ NodeItem("ShaderNodeWavelength"),
+ NodeItem("ShaderNodeWireframe"),
+ ]),
+
+ PovrayTextureNodeCategory("TEXTUREOUTPUT", "Output", items=[
+ NodeItem("TextureNodeValToRGB"),
+ NodeItem("TextureOutputNode"),
+ ]),
+
+ PovraySceneNodeCategory("ISOSURFACE", "Isosurface", items=[
+ NodeItem("IsoPropsNode"),
+ ]),
+
+ PovraySceneNodeCategory("FOG", "Fog", items=[
+ NodeItem("PovrayFogNode"),
+
+ ]),
+ ]
+############### end nodes
+
###############################################################################
# Texture POV properties.
###############################################################################
@@ -1017,11 +1561,12 @@ class RenderPovSettingsObject(PropertyGroup):
("grid", "Grid", ""),
("mesh", "Mesh", "")),
default="mesh")
- # shape_as_light = StringProperty(name="Light",maxlen=1024)
- # object_ior = FloatProperty(
- # name="IOR", description="IOR",
- # min=1.0, max=10.0,default=1.0)
+ object_ior = FloatProperty(
+ name="IOR", description="IOR",
+ min=1.0, max=10.0,default=1.0)
+
+ # shape_as_light = StringProperty(name="Light",maxlen=1024)
# fake_caustics_power = FloatProperty(
# name="Power", description="Fake caustics power",
# min=0.0, max=10.0,default=0.0)
@@ -1482,7 +2027,16 @@ class PovrayPreferences(AddonPreferences):
layout.prop(self, "branch_feature_set_povray")
layout.prop(self, "filepath_povray")
-
+
+
+
+
+
+
+
+
+
+
def register():
bpy.utils.register_module(__name__)
@@ -1492,6 +2046,9 @@ def register():
addon_utils.enable("add_mesh_extra_objects", default_set=False, persistent=True)
#bpy.types.TEXTURE_PT_context_texture.prepend(TEXTURE_PT_povray_type)
+
+ bpy.types.NODE_HT_header.append(ui.menu_func_nodes)
+ nodeitems_utils.register_node_categories("POVRAYNODES", node_categories)
bpy.types.Scene.pov = PointerProperty(type=RenderPovSettingsScene)
bpy.types.Material.pov = PointerProperty(type=RenderPovSettingsMaterial)
bpy.types.Texture.pov = PointerProperty(type=RenderPovSettingsTexture)
@@ -1502,14 +2059,16 @@ def register():
def unregister():
- #bpy.types.TEXTURE_PT_context_texture.remove(TEXTURE_PT_povray_type)
del bpy.types.Scene.pov
del bpy.types.Material.pov
del bpy.types.Texture.pov
del bpy.types.Object.pov
del bpy.types.Camera.pov
del bpy.types.Text.pov
+ nodeitems_utils.unregister_node_categories("POVRAYNODES")
+ bpy.types.NODE_HT_header.remove(ui.menu_func_nodes)
+ #bpy.types.TEXTURE_PT_context_texture.remove(TEXTURE_PT_povray_type)
addon_utils.disable("add_mesh_extra_objects", default_set=False)
bpy.types.INFO_MT_file_import.remove(ui.menu_func_import)
bpy.types.INFO_MT_add.remove(ui.menu_func_add)
diff --git a/render_povray/nodes.py b/render_povray/nodes.py
new file mode 100644
index 00000000..41b0caf1
--- /dev/null
+++ b/render_povray/nodes.py
@@ -0,0 +1,1299 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import bpy
+
+from bpy.types import Node, ShaderNodeTree, CompositorNodeTree, TextureNodeTree#, NodeSocket
+
+
+from bpy.props import (
+ StringProperty,
+ BoolProperty,
+ IntProperty,
+ FloatProperty,
+ FloatVectorProperty,
+ EnumProperty,
+ #PointerProperty,
+ #CollectionProperty,
+ )
+
+
+
+############### object
+
+class ObjectNodeTree(bpy.types.NodeTree):
+ '''Povray Material Nodes'''
+
+ bl_idname = 'ObjectNodeTree'
+ bl_label = 'Povray Object Nodes'
+ bl_icon = 'PLUGIN'
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene.render.engine == 'POVRAY_RENDER'
+
+ @classmethod
+ def get_from_context(cls, context):
+ ob = context.active_object
+ if ob and ob.type not in {'LAMP'}:
+ ma = ob.active_material
+ if ma != None:
+ nt_name = ma.node_tree
+ if nt_name != '':
+ return nt_name, ma, ma
+ return (None, None, None)
+
+ def update(self):
+ self.refresh = True
+################### output #############################################################################################
+
+class PovrayOutputNode(Node, ObjectNodeTree):
+ '''Output'''
+ bl_idname = 'PovrayOutputNode'
+ bl_label = 'Output'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ self.inputs.new('PovraySocketTexture', "Texture")
+
+ def draw_buttons(self, context, layout):
+
+ ob=context.object
+ layout.prop(ob.pov, "object_ior",slider=True)
+
+ def draw_buttons_ext(self, context, layout):
+
+ ob=context.object
+ layout.prop(ob.pov, "object_ior",slider=True)
+
+ def draw_label(self):
+ return "Output"
+
+
+
+################### material ###########################################################################################
+class PovrayTextureNode(Node, ObjectNodeTree):
+ '''Texture'''
+ bl_idname = 'PovrayTextureNode'
+ bl_label = 'Simple texture'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ color=self.inputs.new('PovraySocketColor', "Pigment")
+ color.default_value=(1,1,1)
+ normal=self.inputs.new('NodeSocketFloat', "Normal")
+ normal.hide_value=True
+ finish=self.inputs.new('NodeSocketVector', "Finish")
+ finish.hide_value=True
+
+ self.outputs.new('PovraySocketTexture', "Texture")
+
+ def draw_label(self):
+ return "Simple texture"
+
+class PovrayFinishNode(Node, ObjectNodeTree):
+ '''Finish'''
+ bl_idname = 'PovrayFinishNode'
+ bl_label = 'Finish'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ self.inputs.new('PovraySocketFloat_0_1', "Emission")
+ ambient=self.inputs.new('NodeSocketVector', "Ambient")
+ ambient.hide_value=True
+ diffuse=self.inputs.new('NodeSocketVector', "Diffuse")
+ diffuse.hide_value=True
+ specular=self.inputs.new('NodeSocketVector', "Highlight")
+ specular.hide_value=True
+ mirror=self.inputs.new('NodeSocketVector', "Mirror")
+ mirror.hide_value=True
+ iridescence=self.inputs.new('NodeSocketVector', "Iridescence")
+ iridescence.hide_value=True
+ subsurface=self.inputs.new('NodeSocketVector', "Translucency")
+ subsurface.hide_value=True
+ self.outputs.new('NodeSocketVector', "Finish")
+
+ def draw_label(self):
+ return "Finish"
+
+class PovrayDiffuseNode(Node, ObjectNodeTree):
+ '''Diffuse'''
+ bl_idname = 'PovrayDiffuseNode'
+ bl_label = 'Diffuse'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ intensity=self.inputs.new('PovraySocketFloat_0_1', "Intensity")
+ intensity.default_value=0.8
+ albedo=self.inputs.new('NodeSocketBool', "Albedo")
+ albedo.default_value=False
+ brilliance=self.inputs.new('PovraySocketFloat_0_10', "Brilliance")
+ brilliance.default_value=1.8
+ self.inputs.new('PovraySocketFloat_0_1', "Crand")
+ self.outputs.new('NodeSocketVector', "Diffuse")
+
+ def draw_label(self):
+ return "Diffuse"
+
+class PovrayPhongNode(Node, ObjectNodeTree):
+ '''Phong'''
+ bl_idname = 'PovrayPhongNode'
+ bl_label = 'Phong'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ albedo=self.inputs.new('NodeSocketBool', "Albedo")
+ intensity=self.inputs.new('PovraySocketFloat_0_1', "Intensity")
+ intensity.default_value=0.8
+ phong_size=self.inputs.new('PovraySocketInt_0_256', "Size")
+ phong_size.default_value=60
+ metallic=self.inputs.new('PovraySocketFloat_0_1', "Metallic")
+
+ self.outputs.new('NodeSocketVector', "Phong")
+
+ def draw_label(self):
+ return "Phong"
+
+class PovraySpecularNode(Node, ObjectNodeTree):
+ '''Specular'''
+ bl_idname = 'PovraySpecularNode'
+ bl_label = 'Specular'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ albedo=self.inputs.new('NodeSocketBool', "Albedo")
+ intensity=self.inputs.new('PovraySocketFloat_0_1', "Intensity")
+ intensity.default_value=0.8
+ roughness=self.inputs.new('PovraySocketFloat_0_1', "Roughness")
+ roughness.default_value=0.02
+ metallic=self.inputs.new('PovraySocketFloat_0_1', "Metallic")
+
+ self.outputs.new('NodeSocketVector', "Specular")
+
+ def draw_label(self):
+ return "Specular"
+
+class PovrayMirrorNode(Node, ObjectNodeTree):
+ '''Mirror'''
+ bl_idname = 'PovrayMirrorNode'
+ bl_label = 'Mirror'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ color=self.inputs.new('PovraySocketColor', "Color")
+ color.default_value=(1,1,1)
+ metallic=self.inputs.new('PovraySocketFloat_0_1', "Metallic")
+ metallic.default_value=1.0
+ exponent=self.inputs.new('PovraySocketFloat_0_1', "Exponent")
+ exponent.default_value=1.0
+ self.inputs.new('PovraySocketFloat_0_1', "Falloff")
+ self.inputs.new('NodeSocketBool', "Fresnel")
+ self.inputs.new('NodeSocketBool', "Conserve energy")
+ self.outputs.new('NodeSocketVector', "Mirror")
+
+ def draw_label(self):
+ return "Mirror"
+
+class PovrayAmbientNode(Node, ObjectNodeTree):
+ '''Ambient'''
+ bl_idname = 'PovrayAmbientNode'
+ bl_label = 'Ambient'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ self.inputs.new('PovraySocketColor', "Ambient")
+
+ self.outputs.new('NodeSocketVector', "Ambient")
+
+ def draw_label(self):
+ return "Ambient"
+
+class PovrayIridescenceNode(Node, ObjectNodeTree):
+ '''Iridescence'''
+ bl_idname = 'PovrayIridescenceNode'
+ bl_label = 'Iridescence'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ amount=self.inputs.new('NodeSocketFloat', "Amount")
+ amount.default_value=0.25
+ thickness=self.inputs.new('NodeSocketFloat', "Thickness")
+ thickness.default_value=1
+ self.inputs.new('NodeSocketFloat', "Turbulence")
+
+ self.outputs.new('NodeSocketVector', "Iridescence")
+
+ def draw_label(self):
+ return "Iridescence"
+
+class PovraySubsurfaceNode(Node, ObjectNodeTree):
+ '''Subsurface'''
+ bl_idname = 'PovraySubsurfaceNode'
+ bl_label = 'Subsurface'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ translucency=self.inputs.new('NodeSocketColor', "Translucency")
+ translucency.default_value=(0,0,0,1)
+ energy=self.inputs.new('PovraySocketInt_0_256', "Energy")
+ energy.default_value=20
+ self.outputs.new('NodeSocketVector', "Translucency")
+
+ def draw_buttons(self, context, layout):
+ scene=context.scene
+ layout.prop(scene.pov, "sslt_enable",text="SSLT")
+
+
+ def draw_buttons_ext(self, context, layout):
+ scene=context.scene
+ layout.prop(scene.pov, "sslt_enable",text="SSLT")
+
+ def draw_label(self):
+ return "Subsurface"
+
+#####################################################################################################
+
+class PovrayMappingNode(Node, ObjectNodeTree):
+ '''Mapping'''
+ bl_idname = 'PovrayMappingNode'
+ bl_label = 'Mapping'
+ bl_icon = 'SOUND'
+
+ warp_type = EnumProperty(
+ name="Warp Types",
+ description="Select the type of warp",
+ items=( ('cubic', "Cubic", ""), ('cylindrical', "Cylindrical", ""),('planar', "Planar", ""),
+ ('spherical', "Spherical", ""),('toroidal', "Toroidal", ""),
+ ('uv_mapping', "UV", ""),
+ ('NONE', "None", "No indentation")),
+ default='NONE')
+
+ warp_orientation = EnumProperty(
+ name="Warp Orientation",
+ description="Select the orientation of warp",
+ items=(('x', "X", ""), ('y', "Y", ""), ('z', "Z", "")),
+ default='y')
+
+ warp_dist_exp = FloatProperty(
+ name="Distance exponent",
+ description="Distance exponent",
+ min=0.0, max=100.0, default=1.0)
+
+ warp_tor_major_radius = FloatProperty(
+ name="Major radius",
+ description="Torus is distance from major radius",
+ min=0.0, max=5.0, default=1.0)
+
+ def init(self, context):
+ self.outputs.new('NodeSocketVector', "Mapping")
+
+ def draw_buttons(self, context, layout):
+
+ column=layout.column()
+ column.prop(self,"warp_type",text="Warp type")
+ if self.warp_type in {'toroidal','spherical','cylindrical','planar'}:
+ column.prop(self,"warp_orientation",text="Orientation")
+ column.prop(self,"warp_dist_exp",text="Exponent")
+ if self.warp_type=='toroidal':
+ column.prop(self,"warp_tor_major_radius",text="Major R")
+
+ def draw_buttons_ext(self, context, layout):
+
+ column=layout.column()
+ column.prop(self,"warp_type",text="Warp type")
+ if self.warp_type in {'toroidal','spherical','cylindrical','planar'}:
+ column.prop(self,"warp_orientation",text="Orientation")
+ column.prop(self,"warp_dist_exp",text="Exponent")
+ if self.warp_type=='toroidal':
+ column.prop(self,"warp_tor_major_radius",text="Major R")
+
+ def draw_label(self):
+ return "Mapping"
+
+class PovrayMultiplyNode(Node, ObjectNodeTree):
+ '''Multiply'''
+ bl_idname = 'PovrayMultiplyNode'
+ bl_label = 'Multiply'
+ bl_icon = 'SOUND'
+
+ amount_x = FloatProperty(
+ name="X",
+ description="Number of repeats",
+ min=1.0, max=10000.0, default=1.0)
+
+ amount_y = FloatProperty(
+ name="Y",
+ description="Number of repeats",
+ min=1.0, max=10000.0, default=1.0)
+
+ amount_z = FloatProperty(
+ name="Z",
+ description="Number of repeats",
+ min=1.0, max=10000.0, default=1.0)
+
+
+ def init(self, context):
+ self.outputs.new('NodeSocketVector', "Amount")
+
+ def draw_buttons(self, context, layout):
+
+ column=layout.column()
+ column.label("Amount")
+ row=column.row(align=True)
+ row.prop(self,"amount_x")
+ row.prop(self,"amount_y")
+ row.prop(self,"amount_z")
+
+ def draw_buttons_ext(self, context, layout):
+
+ column=layout.column()
+ column.label("Amount")
+ row=column.row(align=True)
+ row.prop(self,"amount_x")
+ row.prop(self,"amount_y")
+ row.prop(self,"amount_z")
+
+ def draw_label(self):
+ return "Multiply"
+
+class PovrayTransformNode(Node, ObjectNodeTree):
+ '''Transform'''
+ bl_idname = 'PovrayTransformNode'
+ bl_label = 'Transform'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ self.inputs.new('PovraySocketFloatUnlimited', "Translate x")
+ self.inputs.new('PovraySocketFloatUnlimited', "Translate y")
+ self.inputs.new('PovraySocketFloatUnlimited', "Translate z")
+ self.inputs.new('PovraySocketFloatUnlimited', "Rotate x")
+ self.inputs.new('PovraySocketFloatUnlimited', "Rotate y")
+ self.inputs.new('PovraySocketFloatUnlimited', "Rotate z")
+ sX = self.inputs.new('PovraySocketFloatUnlimited', "Scale x")
+ sX.default_value = 1.0
+ sY = self.inputs.new('PovraySocketFloatUnlimited', "Scale y")
+ sY.default_value = 1.0
+ sZ = self.inputs.new('PovraySocketFloatUnlimited', "Scale z")
+ sZ.default_value = 1.0
+
+ self.outputs.new('NodeSocketVector', "Transform")
+
+ def draw_label(self):
+ return "Transform"
+
+class PovrayValueNode(Node, ObjectNodeTree):
+ '''Value'''
+ bl_idname = 'PovrayValueNode'
+ bl_label = 'Value'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ self.outputs.new('PovraySocketUniversal', "Value")
+
+ def draw_label(self):
+ return "Value"
+
+class PovrayModifierNode(Node, ObjectNodeTree):
+ '''Modifier'''
+ bl_idname = 'PovrayModifierNode'
+ bl_label = 'Modifier'
+ bl_icon = 'SOUND'
+
+ def init(self, context):
+
+ turb_x=self.inputs.new('PovraySocketFloat_0_10', "Turb X")
+ turb_x.default_value=0.1
+ turb_y=self.inputs.new('PovraySocketFloat_0_10', "Turb Y")
+ turb_y.default_value=0.1
+ turb_z=self.inputs.new('PovraySocketFloat_0_10', "Turb Z")
+ turb_z.default_value=0.1
+ octaves=self.inputs.new('PovraySocketInt_1_9', "Octaves")
+ octaves.default_value=1
+ lambat=self.inputs.new('PovraySocketFloat_0_10', "Lambda")
+ lambat.default_value=2.0
+ omega=self.inputs.new('PovraySocketFloat_0_10', "Omega")
+ omega.default_value=0.5
+ freq=self.inputs.new('PovraySocketFloat_0_10', "Frequency")
+ freq.default_value=2.0
+ self.inputs.new('PovraySocketFloat_0_10', "Phase")
+
+ self.outputs.new('NodeSocketVector', "Modifier")
+
+ def draw_label(self):
+ return "Modifier"
+
+class PovrayPigmentNode(Node, ObjectNodeTree):
+ '''Pigment'''
+ bl_idname = 'PovrayPigmentNode'
+ bl_label = 'Color'
+
+ def init(self, context):
+
+ color = self.inputs.new('PovraySocketColor', "Color")
+ color.default_value = (1,1,1)
+ povfilter = self.inputs.new('PovraySocketFloat_0_1', "Filter")
+ transmit = self.inputs.new('PovraySocketFloat_0_1', "Transmit")
+ self.outputs.new('NodeSocketColor', "Pigment")
+
+ def draw_label(self):
+ return "Color"
+
+class PovrayColorImageNode(Node, ObjectNodeTree):
+ '''ColorImage'''
+ bl_idname = 'PovrayColorImageNode'
+ bl_label = 'Image map'
+
+ map_type = bpy.props.EnumProperty(
+ name="Map type",
+ description="",
+ items=( ('uv_mapping', "UV", ""),
+ ('0', "Planar", "Default planar mapping."),
+ ('1', "Spherical", "Spherical mapping."),
+ ('2', "Cylindrical", "Cylindrical mapping."),
+ ('5', "Torroidal", "Torus or donut shaped mapping.")),
+ default='0')
+ image = StringProperty(maxlen=1024) # , subtype="FILE_PATH"
+ interpolate = EnumProperty(
+ name="Interpolate",
+ description="Adding the interpolate keyword can smooth the jagged look of a bitmap.",
+ items=(('2', "Bilinear", "Gives bilinear interpolation."),
+ ('4', "Normalized", "Gives normalized distance.")),
+ default='2')
+ premultiplied = BoolProperty(default=False)
+ once = BoolProperty(description="Not to repeat.", default=False)
+
+ def init(self, context):
+
+ gamma=self.inputs.new('PovraySocketFloat_000001_10', "Gamma")
+ gamma.default_value=2.0
+ transmit=self.inputs.new('PovraySocketFloat_0_1', "Transmit")
+ povfilter=self.inputs.new('PovraySocketFloat_0_1', "Filter")
+ mapping=self.inputs.new('NodeSocketVector', "Mapping")
+ mapping.hide_value=True
+ transform=self.inputs.new('NodeSocketVector', "Transform")
+ transform.hide_value=True
+ modifier=self.inputs.new('NodeSocketVector', "Modifier")
+ modifier.hide_value=True
+
+ self.outputs.new('NodeSocketColor', "Pigment")
+
+ def draw_buttons(self, context, layout):
+
+ column=layout.column()
+ im=None
+ for image in bpy.data.images:
+ if image.name == self.image:
+ im=image
+ split = column.split(percentage=0.8,align=True)
+ split.prop_search(self,"image",context.blend_data,"images",text="")
+ split.operator("pov.imageopen",text="",icon="FILESEL")
+ if im != None:
+ column.prop(im,"source",text="")
+ column.prop(self,"map_type",text="")
+ column.prop(self,"interpolate",text="")
+ row=column.row()
+ row.prop(self,"premultiplied",text="Premul")
+ row.prop(self,"once",text="Once")
+
+ def draw_buttons_ext(self, context, layout):
+
+ column=layout.column()
+ im=None
+ for image in bpy.data.images:
+ if image.name == self.image:
+ im=image
+ split = column.split(percentage=0.8,align=True)
+ split.prop_search(self,"image",context.blend_data,"images",text="")
+ split.operator("pov.imageopen",text="",icon="FILESEL")
+ if im != None:
+ column.prop(im,"source",text="")
+ column.prop(self,"map_type",text="")
+ column.prop(self,"interpolate",text="")
+ row=column.row()
+ row.prop(self,"premultiplied",text="Premul")
+ row.prop(self,"once",text="Once")
+
+ def draw_label(self):
+ return "Image map"
+
+class PovrayBumpMapNode(Node, ObjectNodeTree):
+ '''BumpMap'''
+ bl_idname = 'PovrayBumpMapNode'
+ bl_label = 'Bump map'
+ bl_icon = 'SOUND'
+
+ map_type = bpy.props.EnumProperty(
+ name="Map type",
+ description="",
+ items=( ('uv_mapping', "UV", ""),
+ ('0', "Planar", "Default planar mapping."),
+ ('1', "Spherical", "Spherical mapping."),
+ ('2', "Cylindrical", "Cylindrical mapping."),
+ ('5', "Torroidal", "Torus or donut shaped mapping.")),
+ default='0')
+ image = StringProperty(maxlen=1024) # , subtype="FILE_PATH"
+ interpolate = EnumProperty(
+ name="Interpolate",
+ description="Adding the interpolate keyword can smooth the jagged look of a bitmap.",
+ items=(('2', "Bilinear", "Gives bilinear interpolation."),
+ ('4', "Normalized", "Gives normalized distance.")),
+ default='2')
+ once = BoolProperty(description="Not to repeat.", default=False)
+
+ def init(self, context):
+
+ self.inputs.new('PovraySocketFloat_0_10', "Normal")
+ mapping=self.inputs.new('NodeSocketVector', "Mapping")
+ mapping.hide_value=True
+ transform=self.inputs.new('NodeSocketVector', "Transform")
+ transform.hide_value=True
+ modifier=self.inputs.new('NodeSocketVector', "Modifier")
+ modifier.hide_value=True
+
+ normal=self.outputs.new('NodeSocketFloat', "Normal")
+ normal.hide_value=True
+
+ def draw_buttons(self, context, layout):
+
+ column=layout.column()
+ im=None
+ for image in bpy.data.images:
+ if image.name == self.image:
+ im=image
+ split = column.split(percentage=0.8,align=True)
+ split.prop_search(self,"image",context.blend_data,"images",text="")
+ split.operator("pov.imageopen",text="",icon="FILESEL")
+ if im != None:
+ column.prop(im,"source",text="")
+ column.prop(self,"map_type",text="")
+ column.prop(self,"interpolate",text="")
+ column.prop(self,"once",text="Once")
+
+ def draw_buttons_ext(self, context, layout):
+
+ column=layout.column()
+ im=None
+ for image in bpy.data.images:
+ if image.name == self.image:
+ im=image
+ split = column.split(percentage=0.8,align=True)
+ split.prop_search(self,"image",context.blend_data,"images",text="")
+ split.operator("pov.imageopen",text="",icon="FILESEL")
+ if im != None:
+ column.prop(im,"source",text="")
+ column.prop(self,"map_type",text="")
+ column.prop(self,"interpolate",text="")
+ column.prop(self,"once",text="Once")
+
+ def draw_label(self):
+ return "Bump Map"
+
+class PovrayImagePatternNode(Node, ObjectNodeTree):
+ '''ImagePattern'''
+ bl_idname = 'PovrayImagePatternNode'
+ bl_label = 'Image pattern'
+ bl_icon = 'SOUND'
+
+ map_type = bpy.props.EnumProperty(
+ name="Map type",
+ description="",
+ items=( ('uv_mapping', "UV", ""),
+ ('0', "Planar", "Default planar mapping."),
+ ('1', "Spherical", "Spherical mapping."),
+ ('2', "Cylindrical", "Cylindrical mapping."),
+ ('5', "Torroidal", "Torus or donut shaped mapping.")),
+ default='0')
+ image = StringProperty(maxlen=1024) # , subtype="FILE_PATH"
+ interpolate = EnumProperty(
+ name="Interpolate",
+ description="Adding the interpolate keyword can smooth the jagged look of a bitmap.",
+ items=(('2', "Bilinear", "Gives bilinear interpolation."),
+ ('4', "Normalized", "Gives normalized distance.")),
+ default='2')
+ premultiplied = BoolProperty(default=False)
+ once = BoolProperty(description="Not to repeat.", default=False)
+ use_alpha = BoolProperty(default=True)
+ def init(self, context):
+
+ gamma=self.inputs.new('PovraySocketFloat_000001_10', "Gamma")
+ gamma.default_value=2.0
+
+ self.outputs.new('PovraySocketPattern', "Pattern")
+
+ def draw_buttons(self, context, layout):
+
+ column=layout.column()
+ im=None
+ for image in bpy.data.images:
+ if image.name == self.image:
+ im=image
+ split = column.split(percentage=0.8,align=True)
+ split.prop_search(self,"image",context.blend_data,"images",text="")
+ split.operator("pov.imageopen",text="",icon="FILESEL")
+ if im != None:
+ column.prop(im,"source",text="")
+ column.prop(self,"map_type",text="")
+ column.prop(self,"interpolate",text="")
+ row=column.row()
+ row.prop(self,"premultiplied",text="Premul")
+ row.prop(self,"once",text="Once")
+ column.prop(self,"use_alpha",text="Use alpha")
+
+ def draw_buttons_ext(self, context, layout):
+
+ column=layout.column()
+ im=None
+ for image in bpy.data.images:
+ if image.name == self.image:
+ im=image
+ split = column.split(percentage=0.8,align=True)
+ split.prop_search(self,"image",context.blend_data,"images",text="")
+ split.operator("pov.imageopen",text="",icon="FILESEL")
+ if im != None:
+ column.prop(im,"source",text="")
+ column.prop(self,"map_type",text="")
+ column.prop(self,"interpolate",text="")
+ row=column.row()
+ row.prop(self,"premultiplied",text="Premul")
+ row.prop(self,"once",text="Once")
+
+ def draw_label(self):
+ return "Image pattern"
+
+class ShaderPatternNode(Node, ObjectNodeTree):
+ '''Pattern'''
+ bl_idname = 'ShaderPatternNode'
+ bl_label = 'Other patterns'
+
+ pattern = EnumProperty(
+ name="Pattern",
+ description="Agate, Crackle, Gradient, Pavement, Spiral, Tiling",
+ items=(('agate', "Agate", ""),('crackle', "Crackle", ""),('gradient', "Gradient", ""),
+ ('pavement', "Pavement", ""),
+ ('spiral1', "Spiral 1", ""),
+ ('spiral2', "Spiral 2", ""),
+ ('tiling', "Tiling", "")),
+ default='agate')
+
+ agate_turb = FloatProperty(
+ name="Agate turb",
+ description="Agate turbulence",
+ min=0.0, max=100.0, default=0.5)
+
+ crackle_form_x = FloatProperty(
+ name="X",
+ description="Form vector X",
+ min=-150.0, max=150.0, default=-1)
+
+ crackle_form_y = FloatProperty(
+ name="Y",
+ description="Form vector Y",
+ min=-150.0, max=150.0, default=1)
+
+ crackle_form_z = FloatProperty(
+ name="Z",
+ description="Form vector Z",
+ min=-150.0, max=150.0, default=0)
+
+ crackle_metric = FloatProperty(
+ name="Metric",
+ description="Crackle metric",
+ min=0.0, max=150.0, default=1)
+
+ crackle_solid = BoolProperty(
+ name="Solid",
+ description="Crackle solid",
+ default=False)
+
+ spiral_arms = FloatProperty(
+ name="Number",
+ description="",
+ min=0.0, max=256.0, default=2.0)
+
+ tiling_number = IntProperty(
+ name="Number",
+ description="",
+ min=1, max=27, default=1)
+
+ gradient_orient = EnumProperty(
+ name="Orient",
+ description="",
+ items=(('x', "X", ""),
+ ('y', "Y", ""),
+ ('z', "Z", "")),
+ default='x')
+
+ def init(self, context):
+
+ pat = self.outputs.new('PovraySocketPattern', "Pattern")
+
+ def draw_buttons(self, context, layout):
+
+ layout.prop(self, "pattern",text="")
+ if self.pattern=='agate':
+ layout.prop(self, "agate_turb")
+ if self.pattern=='crackle':
+ layout.prop(self, "crackle_metric")
+ layout.prop(self, "crackle_solid")
+ layout.label("Form:")
+ layout.prop(self, "crackle_form_x")
+ layout.prop(self, "crackle_form_y")
+ layout.prop(self, "crackle_form_z")
+ if self.pattern in {"spiral1","spiral2"}:
+ layout.prop(self, "spiral_arms")
+ if self.pattern in {'tiling'}:
+ layout.prop(self, "tiling_number")
+ if self.pattern in {'gradient'}:
+ layout.prop(self, "gradient_orient")
+ def draw_buttons_ext(self, context, layout):
+ pass
+
+ def draw_label(self):
+ return "Other patterns"
+
+class ShaderTextureMapNode(Node, ObjectNodeTree):
+ '''Texture Map'''
+ bl_idname = 'ShaderTextureMapNode'
+ bl_label = 'Texture map'
+
+ brick_size_x = FloatProperty(
+ name="X",
+ description="",
+ min=0.0000, max=1.0000, default=0.2500)
+
+ brick_size_y = FloatProperty(
+ name="Y",
+ description="",
+ min=0.0000, max=1.0000, default=0.0525)
+
+ brick_size_z = FloatProperty(
+ name="Z",
+ description="",
+ min=0.0000, max=1.0000, default=0.1250)
+
+ brick_mortar = FloatProperty(
+ name="Mortar",
+ description="Mortar",
+ min=0.000, max=1.500, default=0.01)
+
+ def init(self, context):
+ mat = bpy.context.object.active_material
+ self.inputs.new('PovraySocketPattern', "")
+ color = self.inputs.new('NodeSocketColor', "Color ramp")
+ color.hide_value = True
+ for i in range(0,4):
+ transform=self.inputs.new('PovraySocketTransform', "Transform")
+ transform.hide_value=True
+ number = mat.pov.inputs_number
+ for i in range(number):
+ self.inputs.new('PovraySocketTexture', "%s"%i)
+
+
+ self.outputs.new('PovraySocketTexture', "Texture")
+
+ def draw_buttons(self, context, layout):
+
+ if self.inputs[0].default_value =='brick':
+ layout.prop(self, "brick_mortar")
+ layout.label("Brick size:")
+ layout.prop(self, "brick_size_x")
+ layout.prop(self, "brick_size_y")
+ layout.prop(self, "brick_size_z")
+
+ def draw_buttons_ext(self, context, layout):
+
+ if self.inputs[0].default_value =='brick':
+ layout.prop(self, "brick_mortar")
+ layout.label("Brick size:")
+ layout.prop(self, "brick_size_x")
+ layout.prop(self, "brick_size_y")
+ layout.prop(self, "brick_size_z")
+
+ def draw_label(self):
+ return "Texture map"
+
+
+class ShaderNormalMapNode(Node, ObjectNodeTree):
+ '''Normal Map'''
+ bl_idname = 'ShaderNormalMapNode'
+ bl_label = 'Normal map'
+
+ brick_size_x = FloatProperty(
+ name="X",
+ description="",
+ min=0.0000, max=1.0000, default=0.2500)
+
+ brick_size_y = FloatProperty(
+ name="Y",
+ description="",
+ min=0.0000, max=1.0000, default=0.0525)
+
+ brick_size_z = FloatProperty(
+ name="Z",
+ description="",
+ min=0.0000, max=1.0000, default=0.1250)
+
+ brick_mortar = FloatProperty(
+ name="Mortar",
+ description="Mortar",
+ min=0.000, max=1.500, default=0.01)
+
+ def init(self, context):
+ self.inputs.new('PovraySocketPattern', "")
+ normal = self.inputs.new('PovraySocketFloat_10', "Normal")
+ slope = self.inputs.new('PovraySocketMap', "Slope map")
+ for i in range(0,4):
+ transform=self.inputs.new('PovraySocketTransform', "Transform")
+ transform.hide_value=True
+ self.outputs.new('PovraySocketNormal', "Normal")
+
+ def draw_buttons(self, context, layout):
+ #for i, inp in enumerate(self.inputs):
+
+ if self.inputs[0].default_value =='brick':
+ layout.prop(self, "brick_mortar")
+ layout.label("Brick size:")
+ layout.prop(self, "brick_size_x")
+ layout.prop(self, "brick_size_y")
+ layout.prop(self, "brick_size_z")
+
+ def draw_buttons_ext(self, context, layout):
+
+ if self.inputs[0].default_value =='brick':
+ layout.prop(self, "brick_mortar")
+ layout.label("Brick size:")
+ layout.prop(self, "brick_size_x")
+ layout.prop(self, "brick_size_y")
+ layout.prop(self, "brick_size_z")
+
+ def draw_label(self):
+ return "Normal map"
+
+class ShaderNormalMapEntryNode(Node, ObjectNodeTree):
+ '''Normal Map Entry'''
+ bl_idname = 'ShaderNormalMapEntryNode'
+ bl_label = 'Normal map entry'
+
+ def init(self, context):
+ self.inputs.new('PovraySocketFloat_0_1', "Stop")
+ self.inputs.new('PovraySocketFloat_0_1', "Gray")
+ def draw_label(self):
+ return "Normal map entry"
+
+class IsoPropsNode(Node, CompositorNodeTree):
+ '''ISO Props'''
+ bl_idname = 'IsoPropsNode'
+ bl_label = 'Iso'
+ node_label = StringProperty(maxlen=1024)
+ def init(self, context):
+ ob = bpy.context.object
+ self.node_label = ob.name
+ textName = ob.pov.function_text
+ if textName:
+ text = bpy.data.texts[textName]
+ for line in text.lines:
+ split = line.body.split()
+ if split[0] == "#declare":
+ socket = self.inputs.new('NodeSocketFloat', "%s"%split[1])
+ value = split[3].split(";")
+ value = value[0]
+ socket.default_value=float(value)
+ def draw_label(self):
+ return self.node_label
+
+class PovrayFogNode(Node, CompositorNodeTree):
+ '''Fog settings'''
+ bl_idname = 'PovrayFogNode'
+ bl_label = 'Fog'
+ def init(self, context):
+ color=self.inputs.new('NodeSocketColor', "Color")
+ color.default_value=(0.7,0.7,0.7,0.25)
+ self.inputs.new('PovraySocketFloat_0_1', "Filter")
+ distance = self.inputs.new('NodeSocketInt', "Distance")
+ distance.default_value=150
+ self.inputs.new('NodeSocketBool', "Ground")
+ fog_offset=self.inputs.new('NodeSocketFloat', "Offset")
+ fog_alt=self.inputs.new('NodeSocketFloat', "Altitude")
+ turb = self.inputs.new('NodeSocketVector', "Turbulence")
+ turb_depth=self.inputs.new('PovraySocketFloat_0_10', "Depth")
+ turb_depth.default_value=0.5
+ octaves=self.inputs.new('PovraySocketInt_1_9', "Octaves")
+ octaves.default_value=5
+ lambdat=self.inputs.new('PovraySocketFloat_0_10', "Lambda")
+ lambdat.default_value=1.25
+ omega=self.inputs.new('PovraySocketFloat_0_10', "Omega")
+ omega.default_value=0.35
+ translate = self.inputs.new('NodeSocketVector', "Translate")
+ rotate = self.inputs.new('NodeSocketVector', "Rotate")
+ scale = self.inputs.new('NodeSocketVector', "Scale")
+ scale.default_value=(1,1,1)
+ def draw_label(self):
+ return "Fog"
+
+class PovraySlopeNode(Node, TextureNodeTree):
+ '''Output'''
+ bl_idname = 'PovraySlopeNode'
+ bl_label = 'Slope Map'
+
+ def init(self, context):
+ self.use_custom_color = True
+ self.color = (0,0.2,0)
+ slope = self.inputs.new('PovraySocketSlope', "0")
+ slope = self.inputs.new('PovraySocketSlope', "1")
+ slopemap = self.outputs.new('PovraySocketMap', "Slope map")
+ output.hide_value = True
+ def draw_buttons(self, context, layout):
+
+ layout.operator("pov.nodeinputadd")
+ row = layout.row()
+ row.label('Value')
+ row.label('Height')
+ row.label('Slope')
+
+ def draw_buttons_ext(self, context, layout):
+
+ layout.operator("pov.nodeinputadd")
+ row = layout.row()
+ row.label('Value')
+ row.label('Height')
+ row.label('Slope')
+
+ def draw_label(self):
+ return "Slope Map"
+
+######################################## Texture nodes ###############################
+class TextureOutputNode(Node, TextureNodeTree):
+ '''Output'''
+ bl_idname = 'TextureOutputNode'
+ bl_label = 'Color Map'
+
+ def init(self, context):
+ tex = bpy.context.object.active_material.active_texture
+ num_sockets = int(tex.pov.density_lines/32)
+ for i in range(num_sockets):
+ color = self.inputs.new('NodeSocketColor', "%s"%i)
+ color.hide_value = True
+
+ def draw_buttons(self, context, layout):
+
+ layout.label("Color Ramps:")
+
+ def draw_label(self):
+ return "Color Map"
+
+
+##################################################################################
+#################################Operators########################################
+##################################################################################
+
+
+class NODE_OT_iso_add(bpy.types.Operator):
+ bl_idname = "pov.nodeisoadd"
+ bl_label = "Create iso props"
+
+ def execute(self, context):
+ ob = bpy.context.object
+ if bpy.context.scene.use_nodes == False:
+ bpy.context.scene.use_nodes = True
+ tree = bpy.context.scene.node_tree
+ for node in tree.nodes:
+ if node.bl_idname == "IsoPropsNode" and node.label == ob.name:
+ tree.nodes.remove(node)
+ isonode = tree.nodes.new('IsoPropsNode')
+ isonode.location = (0,0)
+ isonode.label = ob.name
+ return {'FINISHED'}
+
+class NODE_OT_map_create(bpy.types.Operator):
+ bl_idname = "node.map_create"
+ bl_label = "Create map"
+
+ def execute(self, context):
+ x = y = 0
+ space = context.space_data
+ tree = space.edit_tree
+ for node in tree.nodes:
+ if node.select == True:
+ x,y = node.location
+ node.select=False
+ tmap = tree.nodes.new('ShaderTextureMapNode')
+ tmap.location = (x - 200,y)
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ return wm.invoke_props_dialog(self)
+
+ def draw(self, context):
+ layout = self.layout
+ mat = context.object.active_material
+ layout.prop(mat.pov,"inputs_number")
+
+class NODE_OT_povray_node_texture_map_add(bpy.types.Operator):
+ bl_idname = "pov.nodetexmapadd"
+ bl_label = "Texture map"
+
+ def execute(self, context):
+ tree=bpy.context.object.active_material.node_tree
+ tmap = tree.nodes.active
+ bpy.context.object.active_material.node_tree.nodes.active=tmap
+ el=tmap.color_ramp.elements.new(0.5)
+ for el in tmap.color_ramp.elements:
+ el.color=(0,0,0,1)
+ for inp in tmap.inputs:
+ tmap.inputs.remove(inp)
+ for outp in tmap.outputs:
+ tmap.outputs.remove(outp)
+ pattern=tmap.inputs.new('NodeSocketVector', "Pattern")
+ pattern.hide_value=True
+ for i in range(0,3):
+ tmap.inputs.new('NodeSocketColor', "Shader")
+ tmap.outputs.new('NodeSocketShader', "BSDF")
+ tmap.label="Texture Map"
+ return {'FINISHED'}
+
+
+class NODE_OT_povray_node_output_add(bpy.types.Operator):
+ bl_idname = "pov.nodeoutputadd"
+ bl_label = "Output"
+
+ def execute(self, context):
+ tree=bpy.context.object.active_material.node_tree
+ tmap = tree.nodes.new('ShaderNodeOutputMaterial')
+ bpy.context.object.active_material.node_tree.nodes.active=tmap
+ for inp in tmap.inputs:
+ tmap.inputs.remove(inp)
+ tmap.inputs.new('NodeSocketShader', "Surface")
+ tmap.label="Output"
+ return {'FINISHED'}
+
+class NODE_OT_povray_node_layered_add(bpy.types.Operator):
+ bl_idname = "pov.nodelayeredadd"
+ bl_label = "Layered material"
+
+ def execute(self, context):
+ tree=bpy.context.object.active_material.node_tree
+ tmap = tree.nodes.new('ShaderNodeAddShader')
+ bpy.context.object.active_material.node_tree.nodes.active=tmap
+ tmap.label="Layered material"
+ return {'FINISHED'}
+
+class NODE_OT_povray_input_add(bpy.types.Operator):
+ bl_idname = "pov.nodeinputadd"
+ bl_label = "Add entry"
+
+ def execute(self, context):
+ node=bpy.context.object.active_material.node_tree.nodes.active
+ if node.type in {'VALTORGB'}:
+ number=1
+ for inp in node.inputs:
+ if inp.type=='SHADER':
+ number+=1
+ node.inputs.new('NodeSocketShader', "%s"%number)
+ els=node.color_ramp.elements
+ pos1=els[len(els)-1].position
+ pos2=els[len(els)-2].position
+ pos=(pos1-pos2)/2+pos2
+ el=els.new(pos)
+
+ if node.bl_idname == 'PovraySlopeNode':
+ number=len(node.inputs)
+ node.inputs.new('PovraySocketSlope', "%s"%number)
+
+
+ return {'FINISHED'}
+
+class NODE_OT_povray_input_remove(bpy.types.Operator):
+ bl_idname = "pov.nodeinputremove"
+ bl_label = "Remove input"
+
+ def execute(self, context):
+ node=bpy.context.object.active_material.node_tree.nodes.active
+ if node.type in {'VALTORGB','ADD_SHADER'}:
+ number=len(node.inputs)-1
+ if number > 5:
+ inp=node.inputs[number]
+ node.inputs.remove(inp)
+ if node.type in {'VALTORGB'}:
+ els=node.color_ramp.elements
+ number=len(els)-2
+ el=els[number]
+ els.remove(el)
+ return {'FINISHED'}
+
+class NODE_OT_povray_image_open(bpy.types.Operator):
+ bl_idname = "pov.imageopen"
+ bl_label = "Open"
+
+ filepath = StringProperty(
+ name="File Path",
+ description="Open image",
+ maxlen=1024,
+ subtype='FILE_PATH',
+ )
+
+ def invoke(self, context, event):
+ context.window_manager.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+ def execute(self, context):
+ im=bpy.data.images.load(self.filepath)
+ node=context.object.active_material.node_tree.nodes.active
+ node.image = im.name
+ return {'FINISHED'}
+
+
+# class TEXTURE_OT_povray_open_image(bpy.types.Operator):
+ # bl_idname = "pov.openimage"
+ # bl_label = "Open Image"
+
+ # filepath = StringProperty(
+ # name="File Path",
+ # description="Open image",
+ # maxlen=1024,
+ # subtype='FILE_PATH',
+ # )
+
+ # def invoke(self, context, event):
+ # context.window_manager.fileselect_add(self)
+ # return {'RUNNING_MODAL'}
+
+ # def execute(self, context):
+ # im=bpy.data.images.load(self.filepath)
+ # tex = context.texture
+ # tex.pov.image = im.name
+ # scene = context.scene
+ # scene.update()
+ # return {'FINISHED'}
+
+class PovrayPatternNode(bpy.types.Operator):
+ bl_idname = "pov.patternnode"
+ bl_label = "Pattern"
+
+ add=True
+
+ def execute(self, context):
+ space = context.space_data
+ tree = space.edit_tree
+ for node in tree.nodes:
+ node.select=False
+ if self.add==True:
+ tmap = tree.nodes.new('ShaderNodeValToRGB')
+ tmap.label="Pattern"
+ for inp in tmap.inputs:
+ tmap.inputs.remove(inp)
+ for outp in tmap.outputs:
+ tmap.outputs.remove(outp)
+ pattern = tmap.inputs.new('PovraySocketPattern', "Pattern")
+ pattern.hide_value = True
+ mapping=tmap.inputs.new('NodeSocketVector', "Mapping")
+ mapping.hide_value=True
+ transform=tmap.inputs.new('NodeSocketVector', "Transform")
+ transform.hide_value=True
+ modifier=tmap.inputs.new('NodeSocketVector', "Modifier")
+ modifier.hide_value=True
+ for i in range(0,2):
+ tmap.inputs.new('NodeSocketShader', "%s"%(i+1))
+ tmap.outputs.new('NodeSocketShader', "Material")
+ tmap.outputs.new('NodeSocketColor', "Color")
+ tree.nodes.active=tmap
+ self.add=False
+ aNode=tree.nodes.active
+ aNode.select=True
+ v2d = context.region.view2d
+ x, y = v2d.region_to_view(self.x, self.y)
+ aNode.location = (x, y)
+
+ def modal(self, context, event):
+ if event.type == 'MOUSEMOVE':
+ self.x = event.mouse_region_x
+ self.y = event.mouse_region_y
+ self.execute(context)
+ return {'RUNNING_MODAL'}
+ elif event.type == 'LEFTMOUSE':
+ return {'FINISHED'}
+ elif event.type in ('RIGHTMOUSE', 'ESC'):
+ return {'CANCELLED'}
+
+ return {'RUNNING_MODAL'}
+
+ def invoke(self, context, event):
+ context.window_manager.modal_handler_add(self)
+ return {'RUNNING_MODAL'}
+
+class UpdatePreviewMaterial(bpy.types.Operator):
+ '''Operator update preview material'''
+ bl_idname = "node.updatepreview"
+ bl_label = "Update preview"
+
+ def execute(self, context):
+ scene=context.scene
+ ob=context.object
+ for obj in scene.objects:
+ if obj != ob:
+ scene.objects.active=obj
+ break
+ scene.objects.active=ob
+
+ def modal(self, context, event):
+ if event.type == 'RIGHTMOUSE':
+ self.execute(context)
+ return {'FINISHED'}
+ return {'PASS_THROUGH'}
+
+ def invoke(self, context, event):
+ context.window_manager.modal_handler_add(self)
+ return {'RUNNING_MODAL'}
+
+class UpdatePreviewKey(bpy.types.Operator):
+ '''Operator update preview keymap'''
+ bl_idname = "wm.updatepreviewkey"
+ bl_label = "Activate RMB"
+ @classmethod
+ def poll(cls, context):
+ conf = context.window_manager.keyconfigs.active
+ mapstr = "Node Editor"
+ map = conf.keymaps[mapstr]
+ try:
+ map.keymap_items["node.updatepreview"]
+ return False
+ except:
+ return True
+
+ def execute(self, context):
+ conf = context.window_manager.keyconfigs.active
+ mapstr = "Node Editor"
+ map = conf.keymaps[mapstr]
+ map.keymap_items.new("node.updatepreview",type='RIGHTMOUSE',value="PRESS")
+ return {'FINISHED'}
+
+ \ No newline at end of file
diff --git a/render_povray/primitives.py b/render_povray/primitives.py
index c7fd6999..f053f29f 100644
--- a/render_povray/primitives.py
+++ b/render_povray/primitives.py
@@ -1,6 +1,27 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
############ To get POV-Ray specific objects In and Out of Blender ###########
import bpy
+import os.path
from bpy_extras.io_utils import ImportHelper
from bpy_extras import object_utils
from math import atan, pi, degrees, sqrt, cos, sin
@@ -1505,36 +1526,8 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
#filepov = bpy.path.abspath(self.filepath) #was used for single files
def mat_search(cache):
- r = g = b = 0.5
- f = t = 0
- color = None
-
- for item, value in enumerate(cache):
-
- if value == 'texture':
- pass
-
- if value == 'pigment':
-
- if cache[item+2] in {'rgb','srgb'}:
- pass
-
- elif cache[item+2] in {'rgbf','srgbf'}:
- pass
-
- elif cache[item+2] in {'rgbt','srgbt'}:
- try:
- r,g,b,t = float(cache[item+3]),float(cache[item+4]),float(cache[item+5]),float(cache[item+6])
- except:
- r = g = b = t = float(cache[item+2])
- color = (r,g,b,t)
-
- elif cache[item+2] in {'rgbft','srgbft'}:
- pass
-
- else:
- pass
-
+ r,g,b,t = float(cache[-5]),float(cache[-4]),float(cache[-3]),float(cache[-2])
+ color = (r,g,b,t)
if colors == [] or (colors != [] and color not in colors):
colors.append(color)
name = ob.name+"_mat"
@@ -1542,11 +1535,13 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
mat = bpy.data.materials.new(name)
mat.diffuse_color = (r,g,b)
mat.alpha = 1-t
+ if mat.alpha != 1:
+ mat.use_transparency=True
ob.data.materials.append(mat)
-
+ print (colors)
else:
- for i, value in enumerate(colors):
- if color == value:
+ for i in range(len(colors)):
+ if color == colors[i]:
ob.data.materials.append(bpy.data.materials[matNames[i]])
for file in self.files:
print ("Importing file: "+ file.name)
@@ -1693,36 +1688,27 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
pass
cache = []
cylinder_search = False
-
-
-
-
if word == 'sphere':
sphere_search = True
name_search = False
if sphere_search:
cache.append(word)
if cache[-1] == '}':
- x = y = z = r = 0
try:
x = float(cache[2])
y = float(cache[3])
z = float(cache[4])
r = float(cache[5])
+ bpy.ops.pov.addsphere(R=r, imported_loc=(x, y, z))
+ ob = context.object
+ ob.location = (x,y,z)
+ #ob.scale = (r,r,r)
+ mat_search(cache)
except (ValueError):
pass
- except:
- x = y = z = float(cache[2])
- r = float(cache[3])
- bpy.ops.pov.addsphere(R=r, imported_loc=(x, y, z))
- ob = context.object
- ob.location = (x,y,z)
- ob.scale = (r,r,r)
- mat_search(cache)
cache = []
- sphere_search = False
-
-##################End Primitives Import##################
+ sphere_search = False
+ ##################End Primitives Import##################
if word == '#declare':
name_search = True
if name_search:
diff --git a/render_povray/render.py b/render_povray/render.py
index e08fdf3d..ae23dd27 100644
--- a/render_povray/render.py
+++ b/render_povray/render.py
@@ -34,6 +34,7 @@ from imghdr import what #imghdr is a python lib to identify image file types
from . import df3 # for smoke rendering
from . import shading # for BI POV haders emulation
from . import primitives # for import and export of POV specific primitives
+from . import nodes # for POV specific nodes
##############################SF###########################
##############find image texture
def imageFormat(imgF):
@@ -2856,10 +2857,15 @@ def write_pov(filename, scene=None, info_callback=None):
tabWrite("}\n") # End of mesh block
else:
+ facesMaterials = [] # WARNING!!!!!!!!!!!!!!!!!!!!!!
+ if me_materials:
+ for f in me_faces:
+ if f.material_index not in facesMaterials:
+ facesMaterials.append(f.material_index)
# No vertex colors, so write material colors as vertex colors
for i, material in enumerate(me_materials):
- if material:
+ if material and material.pov.material_use_nodes == False: # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Multiply diffuse with SSS Color
if material.subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
@@ -2914,8 +2920,8 @@ def write_pov(filename, scene=None, info_callback=None):
#when no material slot exists,
material=None
-
- if material and ob.active_material is not None:
+ # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ if material and ob.active_material is not None and material.pov.material_use_nodes == False:
if material.pov.replacement_text != "":
file.write("\n")
file.write(" texture{%s}\n" % material.pov.replacement_text)
@@ -2927,6 +2933,11 @@ def write_pov(filename, scene=None, info_callback=None):
file.write("\n texture{MAT_%s}\n" % cMN)
#use string_strip_hyphen(materialNames[material]))
#or Something like that to clean up the above?
+ elif material and material.pov.material_use_nodes:
+ for index in facesMaterials:
+ faceMaterial = string_strip_hyphen(bpy.path.clean_name(me_materials[index].name))
+ file.write("\n texture{%s}\n" % faceMaterial)
+ # END!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
else:
file.write(" texture{}\n")
tabWrite("}\n")
@@ -2964,6 +2975,7 @@ def write_pov(filename, scene=None, info_callback=None):
else:
material = me_materials[material_index]
for i1, i2, i3 in indices:
+ ci1 = ci2 = ci3 = f.material_index
if me.vertex_colors: #and material.use_vertex_color_paint:
# Color per vertex - vertex color
@@ -2974,6 +2986,8 @@ def write_pov(filename, scene=None, info_callback=None):
ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
+ elif material.pov.material_use_nodes:
+ ci1 = ci2 = ci3 = 0
else:
# Color per material - flat material color
if material.subsurface_scattering.use:
@@ -3408,7 +3422,25 @@ def write_pov(filename, scene=None, info_callback=None):
shading.writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, None) # default material
for material in bpy.data.materials:
if material.users > 0:
- shading.writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, material)
+ if material.pov.material_use_nodes:
+ ntree = material.node_tree
+ povMatName=string_strip_hyphen(bpy.path.clean_name(material.name))
+ if len(ntree.nodes)==0:
+ file.write('#declare %s = texture {%s}\n'%(povMatName,color))
+ else:
+ shading.write_nodes(scene,povMatName,ntree,file)
+
+ for node in ntree.nodes:
+ if node:
+ if node.bl_idname == "PovrayOutputNode":
+ if node.inputs["Texture"].is_linked:
+ for link in ntree.links:
+ if link.to_node.bl_idname == "PovrayOutputNode":
+ povMatName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ else:
+ file.write('#declare %s = texture {%s}\n'%(povMatName,color))
+ else:
+ shading.writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, material)
# attributes are all the variables needed by the other python file...
if comments:
file.write("\n")
@@ -3926,7 +3958,7 @@ class PovrayRender(bpy.types.RenderEngine):
else:
print("***POV FILE NOT FOUND***")
- print("***POV FINISHED***")
+ print("***POV FILE FINISHED***")
#print(filename_log) #bring the pov log to blender console with proper path?
with open(self._temp_file_log) as f: # The with keyword automatically closes the file when you are done
diff --git a/render_povray/shading.py b/render_povray/shading.py
index 9ced6000..81fd2376 100644
--- a/render_povray/shading.py
+++ b/render_povray/shading.py
@@ -1179,3 +1179,523 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image,
mappingNor))
tabWrite("}\n") # THEN IT CAN CLOSE LAST LAYER OF TEXTURE
+
+def string_strip_hyphen(name):
+ return name.replace("-", "")
+# WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+def write_nodes(scene,povMatName,ntree,file):
+ declareNodes=[]
+ scene=bpy.context.scene
+ for node in ntree.nodes:
+ povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName
+ if node.bl_idname == "PovrayFinishNode" and node.outputs["Finish"].is_linked:
+ file.write('#declare %s = finish {\n'%povNodeName)
+ emission=node.inputs["Emission"].default_value
+ if node.inputs["Emission"].is_linked:
+ pass
+ file.write(' emission %.4g\n'%emission)
+ for link in ntree.links:
+ if link.to_node == node:
+
+ if link.from_node.bl_idname == 'PovrayDiffuseNode':
+ intensity=0
+ albedo=""
+ brilliance=0
+ crand=0
+ if link.from_node.inputs["Intensity"].is_linked:
+ pass
+ else:
+ intensity=link.from_node.inputs["Intensity"].default_value
+ if link.from_node.inputs["Albedo"].is_linked:
+ pass
+ else:
+ if link.from_node.inputs["Albedo"].default_value == True:
+ albedo = "albedo"
+ file.write(' diffuse %s %.4g\n'%(albedo,intensity))
+ if link.from_node.inputs["Brilliance"].is_linked:
+ pass
+ else:
+ brilliance=link.from_node.inputs["Brilliance"].default_value
+ file.write(' brilliance %.4g\n'%brilliance)
+ if link.from_node.inputs["Crand"].is_linked:
+ pass
+ else:
+ crand=link.from_node.inputs["Crand"].default_value
+ if crand > 0:
+ file.write(' crand %.4g\n'%crand)
+
+
+ if link.from_node.bl_idname == 'PovraySubsurfaceNode':
+ if scene.povray.sslt_enable:
+ energy = 0
+ r = g = b = 0
+ if link.from_node.inputs["Translucency"].is_linked:
+ pass
+ else:
+ r,g,b,a=link.from_node.inputs["Translucency"].default_value[:]
+ if link.from_node.inputs["Energy"].is_linked:
+ pass
+ else:
+ energy=link.from_node.inputs["Energy"].default_value
+ file.write(' subsurface { translucency <%.4g,%.4g,%.4g>*%s }\n'%(r,g,b,energy))
+
+
+
+ if link.from_node.bl_idname in {'PovraySpecularNode','PovrayPhongNode'}:
+ intensity=0
+ albedo=""
+ roughness=0
+ metallic=0
+ phong_size=0
+ highlight="specular"
+ if link.from_node.inputs["Intensity"].is_linked:
+ pass
+ else:
+ intensity=link.from_node.inputs["Intensity"].default_value
+
+ if link.from_node.inputs["Albedo"].is_linked:
+ pass
+ else:
+ if link.from_node.inputs["Albedo"].default_value == True:
+ albedo = "albedo"
+ if link.from_node.bl_idname in {'PovrayPhongNode'}:
+ highlight="phong"
+ file.write(' %s %s %.4g\n'%(highlight,albedo,intensity))
+
+ if link.from_node.bl_idname in {'PovraySpecularNode'}:
+ if link.from_node.inputs["Roughness"].is_linked:
+ pass
+ else:
+ roughness=link.from_node.inputs["Roughness"].default_value
+ file.write(' roughness %.6g\n'%roughness)
+
+ if link.from_node.bl_idname in {'PovrayPhongNode'}:
+ if link.from_node.inputs["Size"].is_linked:
+ pass
+ else:
+ phong_size=link.from_node.inputs["Size"].default_value
+ file.write(' phong_size %s\n'%phong_size)
+
+ if link.from_node.inputs["Metallic"].is_linked:
+ pass
+ else:
+ metallic=link.from_node.inputs["Metallic"].default_value
+ file.write(' metallic %.4g\n'%metallic)
+
+ if link.from_node.bl_idname in {'PovrayMirrorNode'}:
+ file.write(' reflection {\n')
+ color=None
+ exponent=0
+ metallic=0
+ falloff=0
+ fresnel=""
+ conserve=""
+ if link.from_node.inputs["Color"].is_linked:
+ pass
+ else:
+ color=link.from_node.inputs["Color"].default_value[:]
+ file.write(' <%.4g,%.4g,%.4g>\n'%color)
+
+ if link.from_node.inputs["Exponent"].is_linked:
+ pass
+ else:
+ exponent=link.from_node.inputs["Exponent"].default_value
+ file.write(' exponent %.4g\n'%exponent)
+
+ if link.from_node.inputs["Falloff"].is_linked:
+ pass
+ else:
+ falloff=link.from_node.inputs["Falloff"].default_value
+ file.write(' falloff %.4g\n'%falloff)
+
+ if link.from_node.inputs["Metallic"].is_linked:
+ pass
+ else:
+ metallic=link.from_node.inputs["Metallic"].default_value
+ file.write(' metallic %.4g'%metallic)
+
+ if link.from_node.inputs["Fresnel"].is_linked:
+ pass
+ else:
+ if link.from_node.inputs["Fresnel"].default_value==True:
+ fresnel="fresnel"
+
+ if link.from_node.inputs["Conserve energy"].is_linked:
+ pass
+ else:
+ if link.from_node.inputs["Conserve energy"].default_value==True:
+ conserve="conserve_energy"
+
+ file.write(' %s}\n %s\n'%(fresnel,conserve))
+
+ if link.from_node.bl_idname == 'PovrayAmbientNode':
+ ambient=(0,0,0)
+ if link.from_node.inputs["Ambient"].is_linked:
+ pass
+ else:
+ ambient=link.from_node.inputs["Ambient"].default_value[:]
+ file.write(' ambient <%.4g,%.4g,%.4g>\n'%ambient)
+
+ if link.from_node.bl_idname in {'PovrayIridescenceNode'}:
+ file.write(' irid {\n')
+ amount=0
+ thickness=0
+ turbulence=0
+ if link.from_node.inputs["Amount"].is_linked:
+ pass
+ else:
+ amount=link.from_node.inputs["Amount"].default_value
+ file.write(' %.4g\n'%amount)
+
+ if link.from_node.inputs["Thickness"].is_linked:
+ pass
+ else:
+ exponent=link.from_node.inputs["Thickness"].default_value
+ file.write(' thickness %.4g\n'%thickness)
+
+ if link.from_node.inputs["Turbulence"].is_linked:
+ pass
+ else:
+ falloff=link.from_node.inputs["Turbulence"].default_value
+ file.write(' turbulence %.4g}\n'%turbulence)
+
+ file.write('}\n')
+
+ for node in ntree.nodes:
+ povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName
+ if node.bl_idname == "PovrayTransformNode" and node.outputs["Transform"].is_linked:
+ tx=node.inputs["Translate x"].default_value
+ ty=node.inputs["Translate y"].default_value
+ tz=node.inputs["Translate z"].default_value
+ rx=node.inputs["Rotate x"].default_value
+ ry=node.inputs["Rotate y"].default_value
+ rz=node.inputs["Rotate z"].default_value
+ sx=node.inputs["Scale x"].default_value
+ sy=node.inputs["Scale y"].default_value
+ sz=node.inputs["Scale z"].default_value
+ file.write('#declare %s = transform {\n translate<%.4g,%.4g,%.4g>\n rotate<%.4g,%.4g,%.4g>\n scale<%.4g,%.4g,%.4g>}\n'%(povNodeName,tx,ty,tz,rx,ry,rz,sx,sy,sz))
+
+ for node in ntree.nodes:
+ povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName
+ if node.bl_idname == "PovrayColorImageNode" and node.outputs["Pigment"].is_linked:
+ declareNodes.append(node.name)
+ if node.image == "":
+ file.write('#declare %s = pigment { color rgb 0.8}\n'%(povNodeName))
+ else:
+ im=bpy.data.images[node.image]
+ if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)):
+ transform = ""
+ for link in ntree.links:
+ if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node:
+ povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ transform="transform {%s}"%povTransName
+ uv=""
+ if node.map_type=="uv_mapping":
+ uv="uv_mapping"
+ filepath=bpy.path.abspath(im.filepath)
+ file.write('#declare %s = pigment {%s image_map {\n'%(povNodeName,uv))
+ premul="off"
+ if node.premultiplied:
+ premul="on"
+ once=""
+ if node.once:
+ once="once"
+ file.write(' "%s"\n gamma %.6g\n premultiplied %s\n'%(filepath,node.inputs["Gamma"].default_value,premul))
+ file.write(' %s\n'%once)
+ if node.map_type!="uv_mapping":
+ file.write(' map_type %s\n'%(node.map_type))
+ file.write(' interpolate %s\n filter all %.4g\n transmit all %.4g\n'%
+ (node.interpolate,node.inputs["Filter"].default_value,node.inputs["Transmit"].default_value))
+ file.write(' }\n')
+ file.write(' %s\n'%transform)
+ file.write(' }\n')
+
+ for node in ntree.nodes:
+ povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName
+ if node.bl_idname == "PovrayImagePatternNode" and node.outputs["Pattern"].is_linked:
+ declareNodes.append(node.name)
+ if node.image != "":
+ im=bpy.data.images[node.image]
+ if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)):
+ transform = ""
+ for link in ntree.links:
+ if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node:
+ povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ transform="transform {%s}"%povTransName
+ uv=""
+ if node.map_type=="uv_mapping":
+ uv="uv_mapping"
+ filepath=bpy.path.abspath(im.filepath)
+ file.write('#macro %s() %s image_pattern {\n'%(povNodeName,uv))
+ premul="off"
+ if node.premultiplied:
+ premul="on"
+ once=""
+ if node.once:
+ once="once"
+ file.write(' "%s"\n gamma %.6g\n premultiplied %s\n'%(filepath,node.inputs["Gamma"].default_value,premul))
+ file.write(' %s\n'%once)
+ if node.map_type!="uv_mapping":
+ file.write(' map_type %s\n'%(node.map_type))
+ file.write(' interpolate %s\n'%node.interpolate)
+ file.write(' }\n')
+ file.write(' %s\n'%transform)
+ file.write('#end\n')
+
+ for node in ntree.nodes:
+ povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName
+ if node.bl_idname == "PovrayBumpMapNode" and node.outputs["Normal"].is_linked:
+ if node.image != "":
+ im=bpy.data.images[node.image]
+ if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)):
+ transform = ""
+ for link in ntree.links:
+ if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node:
+ povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ transform="transform {%s}"%povTransName
+ uv=""
+ if node.map_type=="uv_mapping":
+ uv="uv_mapping"
+ filepath=bpy.path.abspath(im.filepath)
+ file.write('#declare %s = normal {%s bump_map {\n'%(povNodeName,uv))
+ once=""
+ if node.once:
+ once="once"
+ file.write(' "%s"\n'%filepath)
+ file.write(' %s\n'%once)
+ if node.map_type!="uv_mapping":
+ file.write(' map_type %s\n'%(node.map_type))
+ bump_size=node.inputs["Normal"].default_value
+ if node.inputs["Normal"].is_linked:
+ pass
+ file.write(' interpolate %s\n bump_size %.4g\n'%(node.interpolate,bump_size))
+ file.write(' }\n')
+ file.write(' %s\n'%transform)
+ file.write(' }\n')
+ declareNodes.append(node.name)
+
+
+
+ for node in ntree.nodes:
+ povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName
+ if node.bl_idname == "PovrayPigmentNode" and node.outputs["Pigment"].is_linked:
+ declareNodes.append(node.name)
+ r,g,b=node.inputs["Color"].default_value[:]
+ f=node.inputs["Filter"].default_value
+ t=node.inputs["Transmit"].default_value
+ if node.inputs["Color"].is_linked:
+ pass
+ file.write('#declare %s = pigment{color srgbft <%.4g,%.4g,%.4g,%.4g,%.4g>}\n'%(povNodeName,r,g,b,f,t))
+
+
+ for node in ntree.nodes:
+ povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName
+ if node.bl_idname == "PovrayTextureNode" and node.outputs["Texture"].is_linked:
+ declareNodes.append(node.name)
+ r,g,b=node.inputs["Pigment"].default_value[:]
+ povColName="color rgb <%.4g,%.4g,%.4g>"%(r,g,b)
+ if node.inputs["Pigment"].is_linked:
+ for link in ntree.links:
+ if link.to_node==node and link.to_socket.name=="Pigment":
+ povColName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ file.write('#declare %s = texture{\n pigment{%s}\n'%(povNodeName,povColName))
+ if node.inputs["Normal"].is_linked:
+ for link in ntree.links:
+ if link.to_node==node and link.to_socket.name=="Normal" and link.from_node.name in declareNodes:
+ povNorName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ file.write(' normal{%s}\n'%povNorName)
+ if node.inputs["Finish"].is_linked:
+ for link in ntree.links:
+ if link.to_node==node and link.to_socket.name=="Finish":
+ povFinName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ file.write(' finish{%s}\n'%povFinName)
+ file.write('}\n')
+ declareNodes.append(node.name)
+
+ for i in range(0,len(ntree.nodes)):
+ for node in ntree.nodes:
+ if node.bl_idname in {"ShaderNodeGroup","ShaderTextureMapNode"}:
+ for output in node.outputs:
+ if output.name=="Texture" and output.is_linked and (node.name not in declareNodes):
+ declare=True
+ for link in ntree.links:
+ if link.to_node==node and link.to_socket.name not in {"","Color ramp","Mapping","Transform","Modifier"}:
+ if link.from_node.name not in declareNodes:
+ declare=False
+ if declare:
+ povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName
+ uv=""
+ warp=""
+ for link in ntree.links:
+ if link.to_node==node and link.from_node.bl_idname=='PovrayMappingNode' and link.from_node.warp_type!="NONE":
+ w_type = link.from_node.warp_type
+ if w_type=="uv_mapping":
+ uv="uv_mapping"
+ else:
+ tor=""
+ if w_type=="toroidal":
+ tor="major_radius %.4g"%link.from_node.warp_tor_major_radius
+ orient=link.from_node.warp_orientation
+ exp=link.from_node.warp_dist_exp
+ warp="warp{%s orientation %s dist_exp %.4g %s}"%(w_type,orient,exp,tor)
+ if link.from_node.warp_type=="planar":
+ warp="warp{%s %s %.4g}"%(w_type,orient,exp)
+ if link.from_node.warp_type=="cubic":
+ warp="warp{%s}"%w_type
+ file.write('#declare %s = texture {%s\n'%(povNodeName,uv))
+ pattern=node.inputs[0].default_value
+ advanced=""
+ if node.inputs[0].is_linked:
+ for link in ntree.links:
+ if link.to_node==node and link.from_node.bl_idname=='ShaderPatternNode':
+ ########### advanced ###############################################
+ lfn=link.from_node
+ pattern=lfn.pattern
+ if pattern == 'agate':
+ advanced = 'agate_turb %.4g'%lfn.agate_turb
+ if pattern == 'crackle':
+ advanced="form <%.4g,%.4g,%.4g>"%(lfn.crackle_form_x,lfn.crackle_form_y,lfn.crackle_form_z)
+ advanced+=" metric %.4g"%lfn.crackle_metric
+ if lfn.crackle_solid:
+ advanced+=" solid"
+ if pattern in {'spiral1', 'spiral2'}:
+ advanced='%.4g'%lfn.spiral_arms
+ if pattern in {'tiling'}:
+ advanced='%.4g'%lfn.tiling_number
+ if pattern in {'gradient'}:
+ advanced='%s'%lfn.gradient_orient
+ if link.to_node==node and link.from_node.bl_idname=='PovrayImagePatternNode':
+ povMacroName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ pattern = "%s()"%povMacroName
+ file.write(' %s %s %s\n'%(pattern,advanced,warp))
+
+ repeat=""
+ for link in ntree.links:
+ if link.to_node==node and link.from_node.bl_idname=='PovrayMultiplyNode':
+ if link.from_node.amount_x > 1:
+ repeat+="warp{repeat %.4g * x}"%link.from_node.amount_x
+ if link.from_node.amount_y > 1:
+ repeat+=" warp{repeat %.4g * y}"%link.from_node.amount_y
+ if link.from_node.amount_z > 1:
+ repeat+=" warp{repeat %.4g * z}"%link.from_node.amount_z
+
+ transform=""
+ for link in ntree.links:
+ if link.to_node==node and link.from_node.bl_idname=='PovrayTransformNode':
+ povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ transform="transform {%s}"%povTransName
+ x=0
+ y=0
+ z=0
+ d=0
+ e=0
+ f=0
+ g=0
+ h=0
+ modifier=False
+ for link in ntree.links:
+ if link.to_node==node and link.from_node.bl_idname=='PovrayModifierNode':
+ modifier=True
+ if link.from_node.inputs["Turb X"].is_linked:
+ pass
+ else:
+ x = link.from_node.inputs["Turb X"].default_value
+
+ if link.from_node.inputs["Turb Y"].is_linked:
+ pass
+ else:
+ y = link.from_node.inputs["Turb Y"].default_value
+
+ if link.from_node.inputs["Turb Z"].is_linked:
+ pass
+ else:
+ z = link.from_node.inputs["Turb Z"].default_value
+
+ if link.from_node.inputs["Octaves"].is_linked:
+ pass
+ else:
+ d = link.from_node.inputs["Octaves"].default_value
+
+ if link.from_node.inputs["Lambda"].is_linked:
+ pass
+ else:
+ e = link.from_node.inputs["Lambda"].default_value
+
+ if link.from_node.inputs["Omega"].is_linked:
+ pass
+ else:
+ f = link.from_node.inputs["Omega"].default_value
+
+ if link.from_node.inputs["Frequency"].is_linked:
+ pass
+ else:
+ g = link.from_node.inputs["Frequency"].default_value
+
+ if link.from_node.inputs["Phase"].is_linked:
+ pass
+ else:
+ h = link.from_node.inputs["Phase"].default_value
+
+ turb = "turbulence <%.4g,%.4g,%.4g>"%(x,y,z)
+ octv = "octaves %s"%d
+ lmbd = "lambda %.4g"%e
+ omg = "omega %.4g"%f
+ freq = "frequency %.4g"%g
+ pha = "phase %.4g"%h
+
+
+ file.write('\n')
+ if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}:
+ file.write(' texture_map {\n')
+ if node.inputs["Color ramp"].is_linked:
+ for link in ntree.links:
+ if link.to_node==node and link.from_node.bl_idname=="ShaderNodeValToRGB":
+ els = link.from_node.color_ramp.elements
+ n=-1
+ for el in els:
+ n+=1
+ povInMatName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s_%s"%(n,povMatName)
+ default=True
+ for ilink in ntree.links:
+ if ilink.to_node==node and ilink.to_socket.name == str(n):
+ default=False
+ povInMatName=string_strip_hyphen(bpy.path.clean_name(ilink.from_node.name))+"_%s"%povMatName
+ if default:
+ r,g,b,a=el.color[:]
+ file.write(' #declare %s = texture{pigment{color srgbt <%.4g,%.4g,%.4g,%.4g>}};\n'%(povInMatName,r,g,b,1-a))
+ file.write(' [%s %s]\n'%(el.position,povInMatName))
+ else:
+ els=[[0,0,0,0],[1,1,1,1]]
+ for i in range(0,2):
+ povInMatName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s_%s"%(i,povMatName)
+ default=True
+ for ilink in ntree.links:
+ if ilink.to_node==node and ilink.to_socket.name == str(i):
+ default=False
+ povInMatName=string_strip_hyphen(bpy.path.clean_name(ilink.from_node.name))+"_%s"%povMatName
+ if default:
+ r,g,b=els[i][1],els[i][2],els[i][3]
+ if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}:
+ file.write(' #declare %s = texture{pigment{color rgb <%.4g,%.4g,%.4g>}};\n'%(povInMatName,r,g,b))
+ else:
+ file.write(' texture{pigment{color rgb <%.4g,%.4g,%.4g>}}\n'%(r,g,b))
+ if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}:
+ file.write(' [%s %s]\n'%(els[i][0],povInMatName))
+ else:
+ if default==False:
+ file.write(' texture{%s}\n'%povInMatName)
+ if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}:
+ file.write('}\n')
+ if pattern == 'brick':
+ file.write("brick_size <%.4g, %.4g, %.4g> mortar %.4g \n"%(node.brick_size_x,
+ node.brick_size_y, node.brick_size_z, node.brick_mortar))
+ file.write(' %s %s'%(repeat,transform))
+ if modifier:
+ file.write(' %s %s %s %s %s %s'%(turb,octv,lmbd,omg,freq,pha))
+ file.write('}\n')
+ declareNodes.append(node.name)
+
+ for link in ntree.links:
+ if link.to_node.bl_idname == "PovrayOutputNode" and link.from_node.name in declareNodes:
+ povMatNodeName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
+ file.write('#declare %s = %s\n'%(povMatName,povMatNodeName))
diff --git a/render_povray/ui.py b/render_povray/ui.py
index f0c361d9..fcdb25a9 100644
--- a/render_povray/ui.py
+++ b/render_povray/ui.py
@@ -59,6 +59,8 @@ for member in dir(properties_material):
properties_material.MATERIAL_PT_game_settings,
properties_material.MATERIAL_PT_physics):
try:
+ #mat=context.material
+ #if mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes):
subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
except:
pass
@@ -86,6 +88,7 @@ for member in dir(properties_particle): # add all "particle" panels from blende
pass
del properties_particle
+
class RenderButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -611,11 +614,90 @@ class RENDER_PT_povray_media(WorldButtonsPanel, bpy.types.Panel):
##
## layout.active = scene.pov.baking_enable
+class MATERIAL_PT_povray_activate_node(MaterialButtonsPanel, bpy.types.Panel):
+ bl_label = "Activate Node Settings"
+ bl_context = "material"
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ mat=context.material
+ ob = context.object
+ return mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes)
+
+ def draw(self, context):
+ layout = self.layout
+ # layout.operator("pov.material_use_nodes", icon='SOUND')#'NODETREE')
+ # the above replaced with a context hook below:
+ layout.operator("WM_OT_context_toggle", text="Use POV-Ray Nodes", icon='NODETREE').data_path = \
+ "material.pov.material_use_nodes"
+
+class MATERIAL_PT_povray_active_node(MaterialButtonsPanel, bpy.types.Panel):
+ bl_label = "Active Node Settings"
+ bl_context = "material"
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ mat=context.material
+ ob = context.object
+ return mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and mat.pov.material_use_nodes
+
+
+ def draw(self, context):
+ layout = self.layout
+ mat = context.material
+ node_tree = mat.node_tree
+ if node_tree:
+ node = node_tree.nodes.active
+ if mat.use_nodes:
+ if node:
+ layout.prop(mat.pov,"material_active_node")
+ if node.bl_idname=="PovrayMaterialNode":
+ layout.context_pointer_set("node", node)
+ if hasattr(node, "draw_buttons_ext"):
+ node.draw_buttons_ext(context, layout)
+ elif hasattr(node, "draw_buttons"):
+ node.draw_buttons(context, layout)
+ value_inputs = [socket for socket in node.inputs if socket.enabled and not socket.is_linked]
+ if value_inputs:
+ layout.separator()
+ layout.label("Inputs:")
+ for socket in value_inputs:
+ row = layout.row()
+ socket.draw(context, row, node, socket.name)
+ else:
+ layout.context_pointer_set("node", node)
+ if hasattr(node, "draw_buttons_ext"):
+ node.draw_buttons_ext(context, layout)
+ elif hasattr(node, "draw_buttons"):
+ node.draw_buttons(context, layout)
+ value_inputs = [socket for socket in node.inputs if socket.enabled and not socket.is_linked]
+ if value_inputs:
+ layout.separator()
+ layout.label("Inputs:")
+ for socket in value_inputs:
+ row = layout.row()
+ socket.draw(context, row, node, socket.name)
+ else:
+ layout.label("No active nodes!")
+
class MATERIAL_PT_povray_reflection(MaterialButtonsPanel, bpy.types.Panel):
bl_label = "POV-Ray Reflection"
COMPAT_ENGINES = {'POVRAY_RENDER'}
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ mat=context.material
+ ob = context.object
+ return mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes)
+
def draw(self, context):
layout = self.layout
mat = context.material
@@ -644,6 +726,14 @@ class MATERIAL_PT_povray_fade_color(MaterialButtonsPanel, bpy.types.Panel):
bl_label = "POV-Ray Absorption"
COMPAT_ENGINES = {'POVRAY_RENDER'}
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ mat=context.material
+ ob = context.object
+ return mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes)
+
+
def draw_header(self, context):
mat = context.material
@@ -665,6 +755,15 @@ class MATERIAL_PT_povray_caustics(MaterialButtonsPanel, bpy.types.Panel):
bl_label = "Caustics"
COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ mat=context.material
+ ob = context.object
+ return mat and mat.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes)
+
+
def draw_header(self, context):
mat = context.material
if mat.pov.caustics_enable:
@@ -702,6 +801,7 @@ class MATERIAL_PT_povray_replacement_text(MaterialButtonsPanel, bpy.types.Panel)
bl_label = "Custom POV Code"
COMPAT_ENGINES = {'POVRAY_RENDER'}
+
def draw(self, context):
layout = self.layout
@@ -1377,6 +1477,55 @@ def menu_func_import(self, context):
self.layout.operator("import_scene.pov",icon="FORCE_LENNARDJONES")
+##############Nodes
+
+# def find_node_input(node, name):
+ # for input in node.inputs:
+ # if input.name == name:
+ # return input
+
+# def panel_node_draw(layout, id_data, output_type, input_name):
+ # if not id_data.use_nodes:
+ # #layout.operator("pov.material_use_nodes", icon='SOUND')#'NODETREE')
+ # #layout.operator("pov.use_shading_nodes", icon='NODETREE')
+ # layout.operator("WM_OT_context_toggle", icon='NODETREE').data_path = \
+ # "material.pov.material_use_nodes"
+ # return False
+
+ # ntree = id_data.node_tree
+
+ # node = find_node(id_data, output_type)
+ # if not node:
+ # layout.label(text="No output node")
+ # else:
+ # input = find_node_input(node, input_name)
+ # layout.template_node_view(ntree, node, input)
+
+ # return True
+
+class Node_map_create_menu(bpy.types.Menu):
+ """Create maps"""
+ bl_idname = "Node_map_create_menu"
+ bl_label = "Create map"
+
+ def draw(self,context):
+ layout = self.layout
+ layout.operator("node.map_create")
+
+def menu_func_nodes(self, context):
+ ob = context.object
+ if hasattr(ob,'active_material'):
+ mat=context.object.active_material
+ if mat and context.space_data.tree_type == 'ObjectNodeTree':
+ self.layout.prop(mat.pov,"material_use_nodes")
+ self.layout.menu("Node_map_create_menu")
+ self.layout.operator("wm.updatepreviewkey")
+ if hasattr(mat,'active_texture') and context.scene.render.engine == 'POVRAY_RENDER':
+ tex=mat.active_texture
+ if tex and context.space_data.tree_type == 'TextureNodeTree':
+ self.layout.prop(tex.pov,"texture_use_nodes")
+
+
###############################################################################
# Camera Povray Settings
###############################################################################
@@ -1424,7 +1573,7 @@ class CAMERA_PT_povray_replacement_text(CameraDataButtonsPanel, bpy.types.Panel)
class TEXT_PT_povray_custom_code(TextButtonsPanel, bpy.types.Panel):
- bl_label = "P.O.V-Ray"
+ bl_label = "POV-Ray"
COMPAT_ENGINES = {'POVRAY_RENDER'}
def draw(self, context):