diff options
Diffstat (limited to 'render_povray/shading_gui.py')
-rwxr-xr-x | render_povray/shading_gui.py | 688 |
1 files changed, 688 insertions, 0 deletions
diff --git a/render_povray/shading_gui.py b/render_povray/shading_gui.py new file mode 100755 index 00000000..3df7f4a9 --- /dev/null +++ b/render_povray/shading_gui.py @@ -0,0 +1,688 @@ +# ##### 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> +""""User interface for shaders exported to POV textures.""" + +import bpy +from bpy.utils import register_class, unregister_class +from bpy.types import Operator, Menu, Panel +from bl_operators.presets import AddPresetBase + +# Example of wrapping every class 'as is' except some +from bl_ui import properties_material + +for member in dir(properties_material): + subclass = getattr(properties_material, member) + try: + # mat=bpy.context.active_object.active_material + # if (mat and mat.pov.type == "SURFACE" + # and not (mat.pov.material_use_nodes or mat.use_nodes)): + # and (engine in cls.COMPAT_ENGINES)) if subclasses were sorted + subclass.COMPAT_ENGINES.add('POVRAY_RENDER') + except BaseException as e: + print(e.__doc__) + print('An exception occurred: {}'.format(e)) + pass +del properties_material + +from .shading_properties import check_material + + +def simple_material(mat): + """Test if a material uses nodes""" + if (mat is not None) and (not mat.use_nodes): + return True + return False + + +class MaterialButtonsPanel: + """Use this class to define buttons from the material tab of + properties window.""" + + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "material" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + mat = context.material + rd = context.scene.render + return mat and (rd.engine in cls.COMPAT_ENGINES) + + +class MATERIAL_MT_POV_sss_presets(Menu): + """Use this class to define pov sss preset menu.""" + + bl_label = "SSS Presets" + preset_subdir = "pov/material/sss" + preset_operator = "script.execute_preset" + draw = bpy.types.Menu.draw_preset + + +class MATERIAL_OT_POV_sss_add_preset(AddPresetBase, Operator): + """Add an SSS Preset""" + + bl_idname = "material.sss_preset_add" + bl_label = "Add SSS Preset" + preset_menu = "MATERIAL_MT_POV_sss_presets" + + # variable used for all preset values + preset_defines = ["material = bpy.context.material"] + + # properties to store in the preset + preset_values = [ + "material.pov_subsurface_scattering.radius", + "material.pov_subsurface_scattering.color", + ] + + # where to store the preset + preset_subdir = "pov/material/sss" + + +class MATERIAL_PT_POV_sss(MaterialButtonsPanel, Panel): + """Use this class to define pov sss buttons panel.""" + + bl_label = "Subsurface Scattering" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + mat = context.material + engine = context.scene.render.engine + return ( + check_material(mat) + and (mat.pov.type in {'SURFACE', 'WIRE'}) + and (engine in cls.COMPAT_ENGINES) + ) + + def draw_header(self, context): + mat = context.material # FORMERLY : #active_node_mat(context.material) + sss = mat.pov_subsurface_scattering + + self.layout.active = not mat.pov.use_shadeless + self.layout.prop(sss, "use", text="") + + def draw(self, context): + layout = self.layout + + mat = context.material # FORMERLY : #active_node_mat(context.material) + sss = mat.pov_subsurface_scattering + + layout.active = (sss.use) and (not mat.pov.use_shadeless) + + row = layout.row().split() + sub = row.row(align=True).split(align=True, factor=0.75) + sub.menu(MATERIAL_MT_POV_sss_presets.__name__, text=MATERIAL_MT_POV_sss_presets.bl_label) + sub.operator(MATERIAL_OT_POV_sss_add_preset.bl_idname, text="", icon='ADD') + sub.operator( + MATERIAL_OT_POV_sss_add_preset.bl_idname, text="", icon='REMOVE' + ).remove_active = True + + split = layout.split() + + col = split.column() + col.prop(sss, "ior") + col.prop(sss, "scale") + col.prop(sss, "color", text="") + col.prop(sss, "radius", text="RGB Radius", expand=True) + + col = split.column() + sub = col.column(align=True) + sub.label(text="Blend:") + sub.prop(sss, "color_factor", text="Color") + sub.prop(sss, "texture_factor", text="Texture") + sub.label(text="Scattering Weight:") + sub.prop(sss, "front") + sub.prop(sss, "back") + col.separator() + col.prop(sss, "error_threshold", text="Error") + + +class MATERIAL_PT_POV_activate_node(MaterialButtonsPanel, Panel): + """Use this class to define an activate pov nodes button.""" + + bl_label = "Activate Node Settings" + bl_context = "material" + bl_options = {'HIDE_HEADER'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + mat = context.material + return ( + mat + and mat.pov.type == "SURFACE" + and (engine in cls.COMPAT_ENGINES) + and not (mat.pov.material_use_nodes or mat.use_nodes) + ) + + def draw(self, context): + layout = self.layout + # layout.operator("pov.material_use_nodes", icon='SOUND')#'NODETREE') + # the above replaced with a context hook below: + layout.operator( + "WM_OT_context_toggle", text="Use POV-Ray Nodes", icon='NODETREE' + ).data_path = "material.pov.material_use_nodes" + + +class MATERIAL_PT_POV_active_node(MaterialButtonsPanel, Panel): + """Use this class to show pov active node properties buttons.""" + + bl_label = "Active Node Settings" + bl_context = "material" + bl_options = {'HIDE_HEADER'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + mat = context.material + return ( + mat + and mat.pov.type == "SURFACE" + and (engine in cls.COMPAT_ENGINES) + and mat.pov.material_use_nodes + ) + + def draw(self, context): + layout = self.layout + mat = context.material + node_tree = mat.node_tree + if node_tree: + node = node_tree.nodes.active + if mat.use_nodes: + if node: + layout.prop(mat.pov, "material_active_node") + if node.bl_idname == "PovrayMaterialNode": + layout.context_pointer_set("node", node) + if hasattr(node, "draw_buttons_ext"): + node.draw_buttons_ext(context, layout) + elif hasattr(node, "draw_buttons"): + node.draw_buttons(context, layout) + value_inputs = [ + socket + for socket in node.inputs + if socket.enabled and not socket.is_linked + ] + if value_inputs: + layout.separator() + layout.label(text="Inputs:") + for socket in value_inputs: + row = layout.row() + socket.draw(context, row, node, socket.name) + else: + layout.context_pointer_set("node", node) + if hasattr(node, "draw_buttons_ext"): + node.draw_buttons_ext(context, layout) + elif hasattr(node, "draw_buttons"): + node.draw_buttons(context, layout) + value_inputs = [ + socket + for socket in node.inputs + if socket.enabled and not socket.is_linked + ] + if value_inputs: + layout.separator() + layout.label(text="Inputs:") + for socket in value_inputs: + row = layout.row() + socket.draw(context, row, node, socket.name) + else: + layout.label(text="No active nodes!") + + +class MATERIAL_PT_POV_specular(MaterialButtonsPanel, Panel): + """Use this class to define standard material specularity (highlights) buttons.""" + + bl_label = "Specular" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + mat = context.material + engine = context.scene.render.engine + return ( + check_material(mat) + and (mat.pov.type in {'SURFACE', 'WIRE'}) + and (engine in cls.COMPAT_ENGINES) + ) + + def draw(self, context): + layout = self.layout + + mat = context.material.pov + + layout.active = not mat.use_shadeless + + split = layout.split() + + col = split.column() + col.prop(mat, "specular_color", text="") + col.prop(mat, "specular_intensity", text="Intensity") + + col = split.column() + col.prop(mat, "specular_shader", text="") + col.prop(mat, "use_specular_ramp", text="Ramp") + + col = layout.column() + if mat.specular_shader in {'COOKTORR', 'PHONG'}: + col.prop(mat, "specular_hardness", text="Hardness") + elif mat.specular_shader == 'BLINN': + row = col.row() + row.prop(mat, "specular_hardness", text="Hardness") + row.prop(mat, "specular_ior", text="IOR") + elif mat.specular_shader == 'WARDISO': + col.prop(mat, "specular_slope", text="Slope") + elif mat.specular_shader == 'TOON': + row = col.row() + row.prop(mat, "specular_toon_size", text="Size") + row.prop(mat, "specular_toon_smooth", text="Smooth") + + if mat.use_specular_ramp: + layout.separator() + layout.template_color_ramp(mat, "specular_ramp", expand=True) + layout.separator() + + row = layout.row() + row.prop(mat, "specular_ramp_input", text="Input") + row.prop(mat, "specular_ramp_blend", text="Blend") + + layout.prop(mat, "specular_ramp_factor", text="Factor") + + +class MATERIAL_PT_POV_mirror(MaterialButtonsPanel, Panel): + """Use this class to define standard material reflectivity (mirror) buttons.""" + + bl_label = "Mirror" + bl_options = {'DEFAULT_CLOSED'} + bl_idname = "MATERIAL_PT_POV_raytrace_mirror" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + mat = context.material + engine = context.scene.render.engine + return ( + check_material(mat) + and (mat.pov.type in {'SURFACE', 'WIRE'}) + and (engine in cls.COMPAT_ENGINES) + ) + + def draw_header(self, context): + mat = context.material + raym = mat.pov_raytrace_mirror + + self.layout.prop(raym, "use", text="") + + def draw(self, context): + layout = self.layout + + mat = context.material # Formerly : #mat = active_node_mat(context.material) + raym = mat.pov_raytrace_mirror + + layout.active = raym.use + + split = layout.split() + + col = split.column() + col.prop(raym, "reflect_factor") + col.prop(raym, "mirror_color", text="") + + col = split.column() + col.prop(raym, "fresnel") + sub = col.column() + sub.active = raym.fresnel > 0.0 + sub.prop(raym, "fresnel_factor", text="Blend") + + split = layout.split() + + col = split.column() + col.separator() + col.prop(raym, "depth") + col.prop(raym, "distance", text="Max Dist") + col.separator() + sub = col.split(factor=0.4) + sub.active = raym.distance > 0.0 + sub.label(text="Fade To:") + sub.prop(raym, "fade_to", text="") + + col = split.column() + col.label(text="Gloss:") + col.prop(raym, "gloss_factor", text="Amount") + sub = col.column() + sub.active = raym.gloss_factor < 1.0 + sub.prop(raym, "gloss_threshold", text="Threshold") + sub.prop(raym, "gloss_samples", text="Noise") + sub.prop(raym, "gloss_anisotropic", text="Anisotropic") + + +class MATERIAL_PT_POV_transp(MaterialButtonsPanel, Panel): + """Use this class to define pov material transparency (alpha) buttons.""" + + bl_label = "Transparency" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + mat = context.material + engine = context.scene.render.engine + return ( + check_material(mat) + and (mat.pov.type in {'SURFACE', 'WIRE'}) + and (engine in cls.COMPAT_ENGINES) + ) + + def draw_header(self, context): + mat = context.material + + if simple_material(mat): + self.layout.prop(mat.pov, "use_transparency", text="") + + def draw(self, context): + layout = self.layout + + base_mat = context.material + mat = context.material # FORMERLY active_node_mat(context.material) + rayt = mat.pov_raytrace_transparency + + if simple_material(base_mat): + row = layout.row() + row.active = mat.pov.use_transparency + row.prop(mat.pov, "transparency_method", expand=True) + + split = layout.split() + split.active = base_mat.pov.use_transparency + + col = split.column() + col.prop(mat.pov, "alpha") + row = col.row() + row.active = (base_mat.pov.transparency_method != 'MASK') and (not mat.pov.use_shadeless) + row.prop(mat.pov, "specular_alpha", text="Specular") + + col = split.column() + col.active = not mat.pov.use_shadeless + col.prop(rayt, "fresnel") + sub = col.column() + sub.active = rayt.fresnel > 0.0 + sub.prop(rayt, "fresnel_factor", text="Blend") + + if base_mat.pov.transparency_method == 'RAYTRACE': + layout.separator() + split = layout.split() + split.active = base_mat.pov.use_transparency + + col = split.column() + col.prop(rayt, "ior") + col.prop(rayt, "filter") + col.prop(rayt, "falloff") + col.prop(rayt, "depth_max") + col.prop(rayt, "depth") + + col = split.column() + col.label(text="Gloss:") + col.prop(rayt, "gloss_factor", text="Amount") + sub = col.column() + sub.active = rayt.gloss_factor < 1.0 + sub.prop(rayt, "gloss_threshold", text="Threshold") + sub.prop(rayt, "gloss_samples", text="Samples") + + +class MATERIAL_PT_POV_reflection(MaterialButtonsPanel, Panel): + """Use this class to define more pov specific reflectivity buttons.""" + + bl_label = "POV-Ray Reflection" + bl_parent_id = "MATERIAL_PT_POV_raytrace_mirror" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + mat = context.material + return ( + mat + and mat.pov.type == "SURFACE" + and (engine in cls.COMPAT_ENGINES) + and not (mat.pov.material_use_nodes or mat.use_nodes) + ) + + def draw(self, context): + layout = self.layout + mat = context.material + col = layout.column() + col.prop(mat.pov, "irid_enable") + if mat.pov.irid_enable: + col = layout.column() + col.prop(mat.pov, "irid_amount", slider=True) + col.prop(mat.pov, "irid_thickness", slider=True) + col.prop(mat.pov, "irid_turbulence", slider=True) + col.prop(mat.pov, "conserve_energy") + col2 = col.split().column() + + if not mat.pov_raytrace_mirror.use: + col2.label(text="Please Check Mirror settings :") + col2.active = mat.pov_raytrace_mirror.use + col2.prop(mat.pov, "mirror_use_IOR") + if mat.pov.mirror_use_IOR: + col2.alignment = 'CENTER' + col2.label(text="The current Raytrace ") + col2.label(text="Transparency IOR is: " + str(mat.pov_raytrace_transparency.ior)) + col2.prop(mat.pov, "mirror_metallic") + + +''' +#group some native Blender (SSS) and POV (Fade)settings under such a parent panel? +class MATERIAL_PT_POV_interior(MaterialButtonsPanel, Panel): + bl_label = "POV-Ray Interior" + bl_idname = "material.pov_interior" + #bl_parent_id = "material.absorption" + COMPAT_ENGINES = {'POVRAY_RENDER'} + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + mat=context.material + return mat and mat.pov.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes) + + + def draw_header(self, context): + mat = context.material +''' + + +class MATERIAL_PT_POV_fade_color(MaterialButtonsPanel, Panel): + """Use this class to define pov fading (absorption) color buttons.""" + + bl_label = "POV-Ray Absorption" + COMPAT_ENGINES = {'POVRAY_RENDER'} + # bl_parent_id = "material.pov_interior" + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + mat = context.material + return ( + mat + and mat.pov.type == "SURFACE" + and (engine in cls.COMPAT_ENGINES) + and not (mat.pov.material_use_nodes or mat.use_nodes) + ) + + def draw_header(self, context): + mat = context.material + + self.layout.prop(mat.pov, "interior_fade_color", text="") + + def draw(self, context): + layout = self.layout + mat = context.material + # layout.active = mat.pov.interior_fade_color + if mat.pov.interior_fade_color != (0.0, 0.0, 0.0): + layout.label(text="Raytrace transparency") + layout.label(text="depth max Limit needs") + layout.label(text="to be non zero to fade") + + +class MATERIAL_PT_POV_caustics(MaterialButtonsPanel, Panel): + """Use this class to define pov caustics buttons.""" + + bl_label = "Caustics" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + engine = context.scene.render.engine + mat = context.material + return ( + mat + and mat.pov.type == "SURFACE" + and (engine in cls.COMPAT_ENGINES) + and not (mat.pov.material_use_nodes or mat.use_nodes) + ) + + def draw_header(self, context): + mat = context.material + if mat.pov.caustics_enable: + self.layout.prop(mat.pov, "caustics_enable", text="", icon="PMARKER_SEL") + else: + self.layout.prop(mat.pov, "caustics_enable", text="", icon="PMARKER") + + def draw(self, context): + + layout = self.layout + + mat = context.material + layout.active = mat.pov.caustics_enable + col = layout.column() + if mat.pov.caustics_enable: + col.prop(mat.pov, "refraction_caustics") + if mat.pov.refraction_caustics: + + col.prop(mat.pov, "refraction_type", text="") + + if mat.pov.refraction_type == "1": + col.prop(mat.pov, "fake_caustics_power", slider=True) + elif mat.pov.refraction_type == "2": + col.prop(mat.pov, "photons_dispersion", slider=True) + col.prop(mat.pov, "photons_dispersion_samples", slider=True) + col.prop(mat.pov, "photons_reflection") + + if not mat.pov.refraction_caustics and not mat.pov.photons_reflection: + col = layout.column() + col.alignment = 'CENTER' + col.label(text="Caustics override is on, ") + col.label(text="but you didn't chose any !") + + +class MATERIAL_PT_strand(MaterialButtonsPanel, Panel): + """Use this class to define Blender strand antialiasing buttons.""" + + bl_label = "Strand" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'POVRAY_RENDER'} + + @classmethod + def poll(cls, context): + mat = context.material + engine = context.scene.render.engine + return ( + mat and (mat.pov.type in {'SURFACE', 'WIRE', 'HALO'}) and (engine in cls.COMPAT_ENGINES) + ) + + def draw(self, context): + layout = self.layout + + mat = context.material # don't use node material + tan = mat.strand + + split = layout.split() + + col = split.column() + sub = col.column(align=True) + sub.label(text="Size:") + sub.prop(tan, "root_size", text="Root") + sub.prop(tan, "tip_size", text="Tip") + sub.prop(tan, "size_min", text="Minimum") + sub.prop(tan, "use_blender_units") + sub = col.column() + sub.active = not mat.pov.use_shadeless + sub.prop(tan, "use_tangent_shading") + col.prop(tan, "shape") + + col = split.column() + col.label(text="Shading:") + col.prop(tan, "width_fade") + ob = context.object + if ob and ob.type == 'MESH': + col.prop_search(tan, "uv_layer", ob.data, "uv_layers", text="") + else: + col.prop(tan, "uv_layer", text="") + col.separator() + sub = col.column() + sub.active = not mat.pov.use_shadeless + sub.label(text="Surface diffuse:") + sub = col.column() + sub.prop(tan, "blend_distance", text="Distance") + + +class MATERIAL_PT_POV_replacement_text(MaterialButtonsPanel, Panel): + """Use this class to define pov custom code declared name field.""" + + bl_label = "Custom POV Code" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + def draw(self, context): + layout = self.layout + mat = context.material + col = layout.column() + col.alignment = 'RIGHT' + col.label(text="Override properties with this") + col.label(text="text editor {pov code} block") + layout.prop(mat.pov, "replacement_text", text="#declare name", icon='SYNTAX_ON') + + +classes = ( + MATERIAL_PT_POV_sss, + MATERIAL_MT_POV_sss_presets, + MATERIAL_OT_POV_sss_add_preset, + MATERIAL_PT_strand, + MATERIAL_PT_POV_activate_node, + MATERIAL_PT_POV_active_node, + MATERIAL_PT_POV_specular, + MATERIAL_PT_POV_mirror, + MATERIAL_PT_POV_transp, + MATERIAL_PT_POV_reflection, + ## MATERIAL_PT_POV_interior, + MATERIAL_PT_POV_fade_color, + MATERIAL_PT_POV_caustics, + MATERIAL_PT_POV_replacement_text, +) + + +def register(): + + for cls in classes: + register_class(cls) + + +def unregister(): + + for cls in reversed(classes): + unregister_class(cls) |