mirror of
https://github.com/blender/blender-addons.git
synced 2025-07-25 16:05:20 +00:00
1363 lines
44 KiB
Python
1363 lines
44 KiB
Python
# ##### 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.utils import register_class
|
|
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 {'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 = '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(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 = '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(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 = '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="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(percentage=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 = '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(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
|
|
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(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(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
|
|
# view_layer = context.view_layer
|
|
# view_layer.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.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(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'}
|
|
|
|
classes = (
|
|
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
|
|
|
|
for cls in classes:
|
|
register_class(cls)
|
|
|
|
|
|
def unregister():
|
|
from bpy.utils import unregister_class
|
|
|
|
for cls in classes:
|
|
unregister_class(cls)
|