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

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'render_povray/shading_nodes.py')
-rwxr-xr-xrender_povray/shading_nodes.py2011
1 files changed, 2011 insertions, 0 deletions
diff --git a/render_povray/shading_nodes.py b/render_povray/shading_nodes.py
new file mode 100755
index 00000000..2e8484f9
--- /dev/null
+++ b/render_povray/shading_nodes.py
@@ -0,0 +1,2011 @@
+# ##### 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>
+""""Nodes based User interface for shaders exported to POV textures."""
+import bpy
+
+from bpy.utils import register_class, unregister_class
+from bpy.types import Menu, Node, NodeSocket, CompositorNodeTree, TextureNodeTree, Operator
+from bpy.props import (
+ StringProperty,
+ BoolProperty,
+ IntProperty,
+ FloatProperty,
+ FloatVectorProperty,
+ EnumProperty,
+)
+import nodeitems_utils
+from nodeitems_utils import NodeCategory, NodeItem
+
+
+###############################################################################
+# Pov Nodes init
+###############################################################################
+
+
+class PovraySocketUniversal(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(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=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(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(text="")
+ self.hide_value = True
+ if self.is_linked:
+ layout.label(text=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(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(text="")
+ self.hide_value = True
+ if self.is_linked:
+ layout.label(text=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(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=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(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=text)
+ else:
+ layout.prop(self, "default_value", text=text, slider=True)
+
+ def draw_color(self, context, node):
+ return (1, 0, 0, 1)
+
+
+class PovraySocketFloatUnlimited(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=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(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=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(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=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(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(text="Pattern")
+ else:
+ layout.prop(self, "default_value", text=text)
+
+ def draw_color(self, context, node):
+ return (1, 1, 1, 1)
+
+
+class PovraySocketColor(NodeSocket):
+ bl_idname = "PovraySocketColor"
+ bl_label = "Povray Socket"
+
+ default_value: 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=text)
+ else:
+ layout.prop(self, "default_value", text=text)
+
+ def draw_color(self, context, node):
+ return (1, 1, 0, 1)
+
+
+class PovraySocketColorRGBFT(NodeSocket):
+ bl_idname = "PovraySocketColorRGBFT"
+ bl_label = "Povray Socket"
+
+ default_value: 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=text)
+ else:
+ layout.prop(self, "default_value", text=text)
+
+ def draw_color(self, context, node):
+ return (1, 1, 0, 1)
+
+
+class PovraySocketTexture(NodeSocket):
+ bl_idname = "PovraySocketTexture"
+ bl_label = "Povray Socket"
+ default_value: bpy.props.IntProperty()
+
+ def draw(self, context, layout, node, text):
+ layout.label(text=text)
+
+ def draw_color(self, context, node):
+ return (0, 1, 0, 1)
+
+
+class PovraySocketTransform(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=text)
+
+ def draw_color(self, context, node):
+ return (99 / 255, 99 / 255, 199 / 255, 1)
+
+
+class PovraySocketNormal(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=text)
+
+ def draw_color(self, context, node):
+ return (0.65, 0.65, 0.65, 1)
+
+
+class PovraySocketSlope(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=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(NodeSocket):
+ bl_idname = "PovraySocketMap"
+ bl_label = "Povray Socket"
+ default_value: bpy.props.StringProperty()
+
+ def draw(self, context, layout, node, text):
+ layout.label(text=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 init
+############### nodes ui
+##############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_MT_POV_map_create(Menu):
+ """Create maps"""
+
+ bl_idname = "POVRAY_MT_node_map_create"
+ 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_MT_POV_map_create.bl_idname)
+ 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")
+
+
+############### 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 {'LIGHT'}:
+ ma = ob.active_material
+ if ma is not 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 = 'SHADING_TEXTURE'
+
+ 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 = 'SHADING_TEXTURE'
+
+ 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 = 'SHADING_TEXTURE'
+
+ 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 = 'MATSPHERE'
+
+ 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 = 'MESH_UVSPHERE'
+
+ 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 = 'MESH_UVSPHERE'
+
+ 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 = 'SHADING_TEXTURE'
+
+ 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 = 'SHADING_SOLID'
+
+ 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 = 'MESH_UVSPHERE'
+
+ 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 = 'MESH_UVSPHERE'
+
+ 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 = 'NODE_TEXTURE'
+
+ 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 = 'SHADING_SOLID'
+
+ 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(text="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(text="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 = 'NODE_TEXTURE'
+
+ 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 = 'SHADING_SOLID'
+
+ 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 = 'NODE_TEXTURE'
+
+ 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'
+ bl_icon = 'SHADING_SOLID'
+
+ def init(self, context):
+
+ color = self.inputs.new('PovraySocketColor', "Color")
+ color.default_value = (1, 1, 1)
+ pov_filter = 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")
+ pov_filter = 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(factor=0.8, align=True)
+ split.prop_search(self, "image", context.blend_data, "images", text="")
+ split.operator("pov.imageopen", text="", icon="FILEBROWSER")
+ if im is not 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(factor=0.8, align=True)
+ split.prop_search(self, "image", context.blend_data, "images", text="")
+ split.operator("pov.imageopen", text="", icon="FILEBROWSER")
+ if im is not 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 = 'TEXTURE'
+
+ 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(factor=0.8, align=True)
+ split.prop_search(self, "image", context.blend_data, "images", text="")
+ split.operator("pov.imageopen", text="", icon="FILEBROWSER")
+ if im is not 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(factor=0.8, align=True)
+ split.prop_search(self, "image", context.blend_data, "images", text="")
+ split.operator("pov.imageopen", text="", icon="FILEBROWSER")
+ if im is not 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 = 'NODE_TEXTURE'
+
+ 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(factor=0.8, align=True)
+ split.prop_search(self, "image", context.blend_data, "images", text="")
+ split.operator("pov.imageopen", text="", icon="FILEBROWSER")
+ if im is not 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(factor=0.8, align=True)
+ split.prop_search(self, "image", context.blend_data, "images", text="")
+ split.operator("pov.imageopen", text="", icon="FILEBROWSER")
+ if im is not 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(text="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(text="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(text="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(text="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(text="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
+ text_name = ob.pov.function_text
+ if text_name:
+ text = bpy.data.texts[text_name]
+ 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(text='Value')
+ row.label(text='Height')
+ row.label(text='Slope')
+
+ def draw_buttons_ext(self, context, layout):
+
+ layout.operator("pov.nodeinputadd")
+ row = layout.row()
+ row.label(text='Value')
+ row.label(text='Height')
+ row.label(text='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(text="Color Ramps:")
+
+ def draw_label(self):
+ return "Color Map"
+
+
+##################################################################################
+#################################Operators########################################
+##################################################################################
+
+
+class NODE_OT_iso_add(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(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(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(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(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(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(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(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(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
+# view_layer = context.view_layer
+# view_layer.update()
+# return {'FINISHED'}
+
+
+class PovrayPatternNode(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(Operator):
+ '''Operator update preview material'''
+
+ bl_idname = "node.updatepreview"
+ bl_label = "Update preview"
+
+ def execute(self, context):
+ scene = context.view_layer
+ ob = context.object
+ for obj in scene.objects:
+ if obj != ob:
+ scene.objects.active = ob
+ 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(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 BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
+ 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'}
+
+
+classes = (
+ PovraySocketUniversal,
+ PovraySocketFloat_0_1,
+ PovraySocketFloat_0_10,
+ PovraySocketFloat_10,
+ PovraySocketFloatPositive,
+ PovraySocketFloat_000001_10,
+ PovraySocketFloatUnlimited,
+ PovraySocketInt_1_9,
+ PovraySocketInt_0_256,
+ PovraySocketPattern,
+ PovraySocketColor,
+ PovraySocketColorRGBFT,
+ PovraySocketTexture,
+ PovraySocketTransform,
+ PovraySocketNormal,
+ PovraySocketSlope,
+ PovraySocketMap,
+ # PovrayShaderNodeCategory, # XXX SOMETHING BROKEN from 2.8 ?
+ # PovrayTextureNodeCategory, # XXX SOMETHING BROKEN from 2.8 ?
+ # PovraySceneNodeCategory, # XXX SOMETHING BROKEN from 2.8 ?
+ NODE_MT_POV_map_create,
+ ObjectNodeTree,
+ PovrayOutputNode,
+ PovrayTextureNode,
+ PovrayFinishNode,
+ PovrayDiffuseNode,
+ PovrayPhongNode,
+ PovraySpecularNode,
+ PovrayMirrorNode,
+ PovrayAmbientNode,
+ PovrayIridescenceNode,
+ PovraySubsurfaceNode,
+ PovrayMappingNode,
+ PovrayMultiplyNode,
+ PovrayTransformNode,
+ PovrayValueNode,
+ PovrayModifierNode,
+ PovrayPigmentNode,
+ PovrayColorImageNode,
+ PovrayBumpMapNode,
+ PovrayImagePatternNode,
+ ShaderPatternNode,
+ ShaderTextureMapNode,
+ ShaderNormalMapNode,
+ ShaderNormalMapEntryNode,
+ IsoPropsNode,
+ PovrayFogNode,
+ PovraySlopeNode,
+ TextureOutputNode,
+ NODE_OT_iso_add,
+ NODE_OT_map_create,
+ NODE_OT_povray_node_texture_map_add,
+ NODE_OT_povray_node_output_add,
+ NODE_OT_povray_node_layered_add,
+ NODE_OT_povray_input_add,
+ NODE_OT_povray_input_remove,
+ NODE_OT_povray_image_open,
+ PovrayPatternNode,
+ UpdatePreviewMaterial,
+ UpdatePreviewKey,
+)
+
+
+def register():
+ # from bpy.utils import register_class
+ bpy.types.NODE_HT_header.append(menu_func_nodes)
+ nodeitems_utils.register_node_categories("POVRAYNODES", node_categories)
+ for cls in classes:
+ register_class(cls)
+
+
+def unregister():
+ # from bpy.utils import unregister_class
+
+ for cls in reversed(classes):
+ unregister_class(cls)
+ nodeitems_utils.unregister_node_categories("POVRAYNODES")
+ bpy.types.NODE_HT_header.remove(menu_func_nodes)