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

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Raybaud <mauriceraybaud@hotmail.fr>2021-05-26 02:34:50 +0300
committerMaurice Raybaud <mauriceraybaud@hotmail.fr>2021-05-26 02:34:50 +0300
commitfad5186bb6880aadbb0cd9d983035c7890801aa7 (patch)
tree60e57ddcefbf423cde567e296e9128ace77e6ed3 /render_povray/texturing_gui.py
parent051d4f7d5951924015d7c2e6bddeb28fac229f1c (diff)
Formatting and fixes
* Moved: some existing functions into new separate files to improve code readability (detailed in __init__.py docstring) * Remove: max_intersections deprecated in pov 3.8 * Add: Validate utf-8 characters with specific API function at session's first script init * Add : Icons to some text fields and inviting labels * Change default camera normal perturbation value to non zero since its use is first driven by a boolean toggle * Change: lists (vectors and indices) are now exported in one line by default for better manual scene overview and debugging * Change: a couple of tooltips corrections * Change : renamed many variables and functions to snake_case according to recommanded style guides * Fix : Heightfield primitive (forward slashes were expected for displacement texture path) * Fix : Text nippet insertion operator * Fix : added console print tip to check executable path on failure to process * Fix : tweaked finished render say command for Linux * Fix : interface of some shader nodes broken since 2.8 api changes * Fix : export hair particles
Diffstat (limited to 'render_povray/texturing_gui.py')
-rwxr-xr-xrender_povray/texturing_gui.py1255
1 files changed, 1255 insertions, 0 deletions
diff --git a/render_povray/texturing_gui.py b/render_povray/texturing_gui.py
new file mode 100755
index 00000000..6d12fb62
--- /dev/null
+++ b/render_povray/texturing_gui.py
@@ -0,0 +1,1255 @@
+# ##### 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 texturing tools."""
+
+import bpy
+from bpy.utils import register_class, unregister_class
+from bpy.types import (
+ Operator,
+ Menu,
+ UIList,
+ Panel,
+ Brush,
+ Material,
+ Light,
+ World,
+ ParticleSettings,
+ FreestyleLineStyle,
+)
+
+# from .ui import TextureButtonsPanel
+
+from .shading_properties import pov_context_tex_datablock
+from bl_ui.properties_paint_common import brush_texture_settings
+
+# Example of wrapping every class 'as is'
+from bl_ui import properties_texture
+
+# unused, replaced by pov_context_tex_datablock (no way to use?):
+# from bl_ui.properties_texture import context_tex_datablock
+# from bl_ui.properties_texture import texture_filter_common #unused yet?
+
+for member in dir(properties_texture):
+ subclass = getattr(properties_texture, member)
+ try:
+ subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
+ except BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
+ pass
+del properties_texture
+
+
+class TextureButtonsPanel:
+ """Use this class to define buttons from the texture tab properties."""
+
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "texture"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ tex = context.texture
+ rd = context.scene.render
+ return tex and (rd.engine in cls.COMPAT_ENGINES)
+
+
+class TEXTURE_MT_POV_specials(Menu):
+ """Use this class to define pov texture slot operations buttons."""
+
+ bl_label = "Texture Specials"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("texture.slot_copy", icon='COPYDOWN')
+ layout.operator("texture.slot_paste", icon='PASTEDOWN')
+
+
+class WORLD_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
+ """Use this class to show pov texture slots list.""" # XXX Not used yet
+
+ index: bpy.props.IntProperty(name='index')
+ # should active_propname be index or..?
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
+ world = context.scene.world # .pov
+ active_data = world.pov
+ # tex = context.texture #may be needed later?
+
+ # We could write some code to decide which icon to use here...
+ # custom_icon = 'TEXTURE'
+
+ # ob = data
+ slot = item
+ # ma = slot.name
+ # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ # You should always start your row layout by a label (icon + text), or a non-embossed text field,
+ # this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
+ # We use icon_value of label, as our given icon is an integer value, not an enum ID.
+ # Note "data" names should never be translated!
+ if slot:
+ layout.prop(item, "texture", text="", emboss=False, icon='TEXTURE')
+ else:
+ layout.label(text="New", translate=False, icon_value=icon)
+ # 'GRID' layout type should be as compact as possible (typically a single icon!).
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
+ """Use this class to show pov texture slots list."""
+
+ # texture_slots:
+ index: bpy.props.IntProperty(name='index')
+ # foo = random prop
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
+ # ob = data
+ slot = item
+ # ma = slot.name
+ # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ # You should always start your row layout by a label (icon + text), or a non-embossed text field,
+ # this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
+ # We use icon_value of label, as our given icon is an integer value, not an enum ID.
+ # Note "data" names should never be translated!
+ if slot:
+ layout.prop(item, "texture", text="", emboss=False, icon='TEXTURE')
+ else:
+ layout.label(text="New", translate=False, icon_value=icon)
+ # 'GRID' layout type should be as compact as possible (typically a single icon!).
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class TEXTURE_PT_context(TextureButtonsPanel, Panel):
+ """Rewrite of this existing class to modify it."""
+
+ bl_label = ""
+ bl_context = "texture"
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'POVRAY_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
+ # register but not unregistered because
+ # the modified parts concern only POVRAY_RENDER
+ @classmethod
+ def poll(cls, context):
+ return (
+ context.scene.texture_context
+ not in ('MATERIAL', 'WORLD', 'LIGHT', 'PARTICLES', 'LINESTYLE')
+ or context.scene.render.engine != 'POVRAY_RENDER'
+ )
+
+ def draw(self, context):
+ layout = self.layout
+ tex = context.texture
+ space = context.space_data
+ pin_id = space.pin_id
+ use_pin_id = space.use_pin_id
+ user = context.texture_user
+
+ col = layout.column()
+
+ if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
+ pin_id = None
+
+ if not pin_id:
+ col.template_texture_user()
+
+ if user or pin_id:
+ col.separator()
+
+ if pin_id:
+ col.template_ID(space, "pin_id")
+ else:
+ propname = context.texture_user_property.identifier
+ col.template_ID(user, propname, new="texture.new")
+
+ if tex:
+ col.separator()
+
+ split = col.split(factor=0.2)
+ split.label(text="Type")
+ split.prop(tex, "type", text="")
+
+
+class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
+ """Use this class to show pov texture context buttons."""
+
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ return engine in cls.COMPAT_ENGINES
+ # if not (hasattr(context, "pov_texture_slot") or hasattr(context, "texture_node")):
+ # return False
+ return (
+ context.material
+ or context.scene.world
+ or context.light
+ or context.texture
+ or context.line_style
+ or context.particle_system
+ or isinstance(context.space_data.pin_id, ParticleSettings)
+ or context.texture_user
+ ) and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ mat = context.view_layer.objects.active.active_material
+ wld = context.scene.world
+
+ layout.prop(scene, "texture_context", expand=True)
+ if scene.texture_context == 'MATERIAL' and mat is not None:
+
+ row = layout.row()
+ row.template_list(
+ "MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist",
+ "",
+ mat,
+ "pov_texture_slots",
+ mat.pov,
+ "active_texture_index",
+ rows=2,
+ maxrows=16,
+ type="DEFAULT",
+ )
+ col = row.column(align=True)
+ col.operator("pov.textureslotadd", icon='ADD', text='')
+ col.operator("pov.textureslotremove", icon='REMOVE', text='')
+ # XXX todo: recreate for pov_texture_slots?
+ # col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
+ # col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
+ col.separator()
+
+ if mat.pov_texture_slots:
+ index = mat.pov.active_texture_index
+ slot = mat.pov_texture_slots[index]
+ povtex = slot.texture # slot.name
+ tex = bpy.data.textures[povtex]
+ col.prop(tex, 'use_fake_user', text='')
+ # layout.label(text='Linked Texture data browser:')
+ # propname = slot.texture_search
+ # if slot.texture was a pointer to texture data rather than just a name string:
+ # layout.template_ID(povtex, "texture", new="texture.new")
+
+ layout.prop_search(
+ slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
+ )
+ try:
+ bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[
+ slot.texture_search
+ ]
+ bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[
+ slot.texture_search
+ ]
+ except KeyError:
+ # texture not hand-linked by user
+ pass
+
+ if tex:
+ layout.separator()
+ split = layout.split(factor=0.2)
+ split.label(text="Type")
+ split.prop(tex, "type", text="")
+
+ # else:
+ # for i in range(18): # length of material texture slots
+ # mat.pov_texture_slots.add()
+ elif scene.texture_context == 'WORLD' and wld is not None:
+
+ row = layout.row()
+ row.template_list(
+ "WORLD_TEXTURE_SLOTS_UL_POV_layerlist",
+ "",
+ wld,
+ "pov_texture_slots",
+ wld.pov,
+ "active_texture_index",
+ rows=2,
+ maxrows=16,
+ type="DEFAULT",
+ )
+ col = row.column(align=True)
+ col.operator("pov.textureslotadd", icon='ADD', text='')
+ col.operator("pov.textureslotremove", icon='REMOVE', text='')
+
+ # todo: recreate for pov_texture_slots?
+ # col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
+ # col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
+ col.separator()
+
+ if wld.pov_texture_slots:
+ index = wld.pov.active_texture_index
+ slot = wld.pov_texture_slots[index]
+ povtex = slot.texture # slot.name
+ tex = bpy.data.textures[povtex]
+ col.prop(tex, 'use_fake_user', text='')
+ # layout.label(text='Linked Texture data browser:')
+ propname = slot.texture_search
+ # if slot.texture was a pointer to texture data rather than just a name string:
+ # layout.template_ID(povtex, "texture", new="texture.new")
+
+ layout.prop_search(
+ slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
+ )
+ try:
+ bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[
+ slot.texture_search
+ ]
+ bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[
+ slot.texture_search
+ ]
+ except KeyError:
+ # texture not hand-linked by user
+ pass
+
+ if tex:
+ layout.separator()
+ split = layout.split(factor=0.2)
+ split.label(text="Type")
+ split.prop(tex, "type", text="")
+
+
+# Commented out below is a reminder of what existed in Blender Internal
+# attributes need to be recreated
+'''
+ slot = getattr(context, "texture_slot", None)
+ node = getattr(context, "texture_node", None)
+ space = context.space_data
+
+ #attempt at replacing removed space_data
+ mtl = getattr(context, "material", None)
+ if mtl != None:
+ spacedependant = mtl
+ wld = getattr(context, "world", None)
+ if wld != None:
+ spacedependant = wld
+ lgt = getattr(context, "light", None)
+ if lgt != None:
+ spacedependant = lgt
+
+
+ #idblock = context.particle_system.settings
+
+ tex = getattr(context, "texture", None)
+ if tex != None:
+ spacedependant = tex
+
+
+
+ scene = context.scene
+ idblock = scene.pov#pov_context_tex_datablock(context)
+ pin_id = space.pin_id
+
+ #spacedependant.use_limited_texture_context = True
+
+ if space.use_pin_id and not isinstance(pin_id, Texture):
+ idblock = id_tex_datablock(pin_id)
+ pin_id = None
+
+ if not space.use_pin_id:
+ layout.row().prop(spacedependant, "texture_context", expand=True)
+ pin_id = None
+
+ if spacedependant.texture_context == 'OTHER':
+ if not pin_id:
+ layout.template_texture_user()
+ user = context.texture_user
+ if user or pin_id:
+ layout.separator()
+
+ row = layout.row()
+
+ if pin_id:
+ row.template_ID(space, "pin_id")
+ else:
+ propname = context.texture_user_property.identifier
+ row.template_ID(user, propname, new="texture.new")
+
+ if tex:
+ split = layout.split(factor=0.2)
+ if tex.use_nodes:
+ if slot:
+ split.label(text="Output:")
+ split.prop(slot, "output_node", text="")
+ else:
+ split.label(text="Type:")
+ split.prop(tex, "type", text="")
+ return
+
+ tex_collection = (pin_id is None) and (node is None) and (spacedependant.texture_context not in ('LINESTYLE','OTHER'))
+
+ if tex_collection:
+
+ pov = getattr(context, "pov", None)
+ active_texture_index = getattr(spacedependant, "active_texture_index", None)
+ print (pov)
+ print(idblock)
+ print(active_texture_index)
+ row = layout.row()
+
+ row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots",
+ idblock, "active_texture_index", rows=2, maxrows=16, type="DEFAULT")
+
+ # row.template_list("WORLD_TEXTURE_SLOTS_UL_List", "texture_slots", world,
+ # world.texture_slots, world, "active_texture_index", rows=2)
+
+ col = row.column(align=True)
+ col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
+ col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
+ col.menu("TEXTURE_MT_POV_specials", icon='DOWNARROW_HLT', text="")
+
+ if tex_collection:
+ layout.template_ID(idblock, "active_texture", new="texture.new")
+ elif node:
+ layout.template_ID(node, "texture", new="texture.new")
+ elif idblock:
+ layout.template_ID(idblock, "texture", new="texture.new")
+
+ if pin_id:
+ layout.template_ID(space, "pin_id")
+
+ if tex:
+ split = layout.split(factor=0.2)
+ if tex.use_nodes:
+ if slot:
+ split.label(text="Output:")
+ split.prop(slot, "output_node", text="")
+ else:
+ split.label(text="Type:")
+'''
+
+
+class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
+ """Use this class to show pov color ramps."""
+
+ bl_label = "Colors"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ tex = context.texture
+
+ layout.prop(tex, "use_color_ramp", text="Ramp")
+ if tex.use_color_ramp:
+ layout.template_color_ramp(tex, "color_ramp", expand=True)
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="RGB Multiply:")
+ sub = col.column(align=True)
+ sub.prop(tex, "factor_red", text="R")
+ sub.prop(tex, "factor_green", text="G")
+ sub.prop(tex, "factor_blue", text="B")
+
+ col = split.column()
+ col.label(text="Adjust:")
+ col.prop(tex, "intensity")
+ col.prop(tex, "contrast")
+ col.prop(tex, "saturation")
+
+ col = layout.column()
+ col.prop(tex, "use_clamp", text="Clamp")
+
+
+# Texture Slot Panels #
+
+
+class TEXTURE_OT_POV_texture_slot_add(Operator):
+ """Use this class for the add texture slot button."""
+
+ bl_idname = "pov.textureslotadd"
+ bl_label = "Add"
+ bl_description = "Add texture_slot"
+ bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def execute(self, context):
+ idblock = pov_context_tex_datablock(context)
+ tex = bpy.data.textures.new(name='Texture', type='IMAGE')
+ # tex.use_fake_user = True
+ # mat = context.view_layer.objects.active.active_material
+ slot = idblock.pov_texture_slots.add()
+ slot.name = tex.name
+ slot.texture = tex.name
+ slot.texture_search = tex.name
+ # Switch paint brush and paint brush mask
+ # to this texture so settings remain contextual
+ bpy.context.tool_settings.image_paint.brush.texture = tex
+ bpy.context.tool_settings.image_paint.brush.mask_texture = tex
+ idblock.pov.active_texture_index = len(idblock.pov_texture_slots) - 1
+
+ # for area in bpy.context.screen.areas:
+ # if area.type in ['PROPERTIES']:
+ # area.tag_redraw()
+
+ return {'FINISHED'}
+
+
+class TEXTURE_OT_POV_texture_slot_remove(Operator):
+ """Use this class for the remove texture slot button."""
+
+ bl_idname = "pov.textureslotremove"
+ bl_label = "Remove"
+ bl_description = "Remove texture_slot"
+ bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def execute(self, context):
+ idblock = pov_context_tex_datablock(context)
+ # mat = context.view_layer.objects.active.active_material
+ # tex_slot = idblock.pov_texture_slots.remove(idblock.pov.active_texture_index) # not used
+ if idblock.pov.active_texture_index > 0:
+ idblock.pov.active_texture_index -= 1
+ try:
+ tex = idblock.pov_texture_slots[idblock.pov.active_texture_index].texture
+ except IndexError:
+ # No more slots
+ return {'FINISHED'}
+ # Switch paint brush to previous texture so settings remain contextual
+ # if 'tex' in locals(): # Would test is the tex variable is assigned / exists
+ bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[tex]
+ bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[tex]
+
+ return {'FINISHED'}
+
+
+class TextureSlotPanel(TextureButtonsPanel):
+ """Use this class to show pov texture slots panel."""
+
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ if not hasattr(context, "pov_texture_slot"):
+ return False
+
+ engine = context.scene.render.engine
+ # return TextureButtonsPanel.poll(cls, context) and (engine in cls.COMPAT_ENGINES)
+ return TextureButtonsPanel.poll(context) and (engine in cls.COMPAT_ENGINES)
+
+
+class TEXTURE_PT_POV_type(TextureButtonsPanel, Panel):
+ """Use this class to define pov texture type buttons."""
+
+ bl_label = "POV Textures"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+ bl_options = {'HIDE_HEADER'}
+
+ def draw(self, context):
+ layout = self.layout
+ # world = context.world # unused
+ tex = context.texture
+
+ split = layout.split(factor=0.2)
+ split.label(text="Pattern")
+ split.prop(tex.pov, "tex_pattern_type", text="")
+
+ # row = layout.row()
+ # row.template_list("WORLD_TEXTURE_SLOTS_UL_List", "texture_slots", world,
+ # world.texture_slots, world, "active_texture_index")
+
+
+class TEXTURE_PT_POV_preview(TextureButtonsPanel, Panel):
+ """Use this class to define pov texture preview panel."""
+
+ bl_label = "Preview"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+ bl_options = {'HIDE_HEADER'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ if not hasattr(context, "pov_texture_slot"):
+ return False
+ tex = context.texture
+ # mat = bpy.context.active_object.active_material #unused
+ return tex and (tex.pov.tex_pattern_type != 'emulator') and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ tex = context.texture
+ slot = getattr(context, "pov_texture_slot", None)
+ # idblock = pov_context_tex_datablock(context) # unused
+ layout = self.layout
+ # if idblock:
+ # layout.template_preview(tex, parent=idblock, slot=slot)
+ if tex.pov.tex_pattern_type != 'emulator':
+ layout.operator("tex.preview_update")
+ else:
+ layout.template_preview(tex, slot=slot)
+
+
+class TEXTURE_PT_POV_parameters(TextureButtonsPanel, Panel):
+ """Use this class to define pov texture pattern buttons."""
+
+ bl_label = "POV Pattern Options"
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def draw(self, context):
+ # mat = bpy.context.active_object.active_material # Unused
+ layout = self.layout
+ tex = context.texture
+ align = True
+ if tex is not None and tex.pov.tex_pattern_type != 'emulator':
+ if tex.pov.tex_pattern_type == 'agate':
+ layout.prop(tex.pov, "modifier_turbulence", text="Agate Turbulence")
+ if tex.pov.tex_pattern_type in {'spiral1', 'spiral2'}:
+ layout.prop(tex.pov, "modifier_numbers", text="Number of arms")
+ if tex.pov.tex_pattern_type == 'tiling':
+ layout.prop(tex.pov, "modifier_numbers", text="Pattern number")
+ if tex.pov.tex_pattern_type == 'magnet':
+ layout.prop(tex.pov, "magnet_style", text="Magnet style")
+ if tex.pov.tex_pattern_type == 'quilted':
+ row = layout.row(align=align)
+ row.prop(tex.pov, "modifier_control0", text="Control0")
+ row.prop(tex.pov, "modifier_control1", text="Control1")
+ if tex.pov.tex_pattern_type == 'brick':
+ col = layout.column(align=align)
+ row = col.row()
+ row.prop(tex.pov, "brick_size_x", text="Brick size X")
+ row.prop(tex.pov, "brick_size_y", text="Brick size Y")
+ row = col.row()
+ row.prop(tex.pov, "brick_size_z", text="Brick size Z")
+ row.prop(tex.pov, "brick_mortar", text="Brick mortar")
+ if tex.pov.tex_pattern_type in {'julia', 'mandel', 'magnet'}:
+ col = layout.column(align=align)
+ if tex.pov.tex_pattern_type == 'julia':
+ row = col.row()
+ row.prop(tex.pov, "julia_complex_1", text="Complex 1")
+ row.prop(tex.pov, "julia_complex_2", text="Complex 2")
+ if tex.pov.tex_pattern_type == 'magnet' and tex.pov.magnet_style == 'julia':
+ row = col.row()
+ row.prop(tex.pov, "julia_complex_1", text="Complex 1")
+ row.prop(tex.pov, "julia_complex_2", text="Complex 2")
+ row = col.row()
+ if tex.pov.tex_pattern_type in {'julia', 'mandel'}:
+ row.prop(tex.pov, "f_exponent", text="Exponent")
+ if tex.pov.tex_pattern_type == 'magnet':
+ row.prop(tex.pov, "magnet_type", text="Type")
+ row.prop(tex.pov, "f_iter", text="Iterations")
+ row = col.row()
+ row.prop(tex.pov, "f_ior", text="Interior")
+ row.prop(tex.pov, "f_ior_fac", text="Factor I")
+ row = col.row()
+ row.prop(tex.pov, "f_eor", text="Exterior")
+ row.prop(tex.pov, "f_eor_fac", text="Factor E")
+ if tex.pov.tex_pattern_type == 'gradient':
+ layout.label(text="Gradient orientation:")
+ column_flow = layout.column_flow(columns=3, align=True)
+ column_flow.prop(tex.pov, "grad_orient_x", text="X")
+ column_flow.prop(tex.pov, "grad_orient_y", text="Y")
+ column_flow.prop(tex.pov, "grad_orient_z", text="Z")
+ if tex.pov.tex_pattern_type == 'pavement':
+ layout.prop(tex.pov, "pave_sides", text="Pavement:number of sides")
+ col = layout.column(align=align)
+ column_flow = col.column_flow(columns=3, align=True)
+ column_flow.prop(tex.pov, "pave_tiles", text="Tiles")
+ if tex.pov.pave_sides == '4' and tex.pov.pave_tiles == 6:
+ column_flow.prop(tex.pov, "pave_pat_35", text="Pattern")
+ if tex.pov.pave_sides == '6' and tex.pov.pave_tiles == 5:
+ column_flow.prop(tex.pov, "pave_pat_22", text="Pattern")
+ if tex.pov.pave_sides == '4' and tex.pov.pave_tiles == 5:
+ column_flow.prop(tex.pov, "pave_pat_12", text="Pattern")
+ if tex.pov.pave_sides == '3' and tex.pov.pave_tiles == 6:
+ column_flow.prop(tex.pov, "pave_pat_12", text="Pattern")
+ if tex.pov.pave_sides == '6' and tex.pov.pave_tiles == 4:
+ column_flow.prop(tex.pov, "pave_pat_7", text="Pattern")
+ if tex.pov.pave_sides == '4' and tex.pov.pave_tiles == 4:
+ column_flow.prop(tex.pov, "pave_pat_5", text="Pattern")
+ if tex.pov.pave_sides == '3' and tex.pov.pave_tiles == 5:
+ column_flow.prop(tex.pov, "pave_pat_4", text="Pattern")
+ if tex.pov.pave_sides == '6' and tex.pov.pave_tiles == 3:
+ column_flow.prop(tex.pov, "pave_pat_3", text="Pattern")
+ if tex.pov.pave_sides == '3' and tex.pov.pave_tiles == 4:
+ column_flow.prop(tex.pov, "pave_pat_3", text="Pattern")
+ if tex.pov.pave_sides == '4' and tex.pov.pave_tiles == 3:
+ column_flow.prop(tex.pov, "pave_pat_2", text="Pattern")
+ if tex.pov.pave_sides == '6' and tex.pov.pave_tiles == 6:
+ column_flow.label(text="!!! 5 tiles!")
+ column_flow.prop(tex.pov, "pave_form", text="Form")
+ if tex.pov.tex_pattern_type == 'function':
+ layout.prop(tex.pov, "func_list", text="Functions")
+ if tex.pov.tex_pattern_type == 'function' and tex.pov.func_list != "NONE":
+ func = None
+ if tex.pov.func_list in {"f_noise3d", "f_ph", "f_r", "f_th"}:
+ func = 0
+ if tex.pov.func_list in {
+ "f_comma",
+ "f_crossed_trough",
+ "f_cubic_saddle",
+ "f_cushion",
+ "f_devils_curve",
+ "f_enneper",
+ "f_glob",
+ "f_heart",
+ "f_hex_x",
+ "f_hex_y",
+ "f_hunt_surface",
+ "f_klein_bottle",
+ "f_kummer_surface_v1",
+ "f_lemniscate_of_gerono",
+ "f_mitre",
+ "f_nodal_cubic",
+ "f_noise_generator",
+ "f_odd",
+ "f_paraboloid",
+ "f_pillow",
+ "f_piriform",
+ "f_quantum",
+ "f_quartic_paraboloid",
+ "f_quartic_saddle",
+ "f_sphere",
+ "f_steiners_roman",
+ "f_torus_gumdrop",
+ "f_umbrella",
+ }:
+ func = 1
+ if tex.pov.func_list in {
+ "f_bicorn",
+ "f_bifolia",
+ "f_boy_surface",
+ "f_superellipsoid",
+ "f_torus",
+ }:
+ func = 2
+ if tex.pov.func_list in {
+ "f_ellipsoid",
+ "f_folium_surface",
+ "f_hyperbolic_torus",
+ "f_kampyle_of_eudoxus",
+ "f_parabolic_torus",
+ "f_quartic_cylinder",
+ "f_torus2",
+ }:
+ func = 3
+ if tex.pov.func_list in {
+ "f_blob2",
+ "f_cross_ellipsoids",
+ "f_flange_cover",
+ "f_isect_ellipsoids",
+ "f_kummer_surface_v2",
+ "f_ovals_of_cassini",
+ "f_rounded_box",
+ "f_spikes_2d",
+ "f_strophoid",
+ }:
+ func = 4
+ if tex.pov.func_list in {
+ "f_algbr_cyl1",
+ "f_algbr_cyl2",
+ "f_algbr_cyl3",
+ "f_algbr_cyl4",
+ "f_blob",
+ "f_mesh1",
+ "f_poly4",
+ "f_spikes",
+ }:
+ func = 5
+ if tex.pov.func_list in {
+ "f_devils_curve_2d",
+ "f_dupin_cyclid",
+ "f_folium_surface_2d",
+ "f_hetero_mf",
+ "f_kampyle_of_eudoxus_2d",
+ "f_lemniscate_of_gerono_2d",
+ "f_polytubes",
+ "f_ridge",
+ "f_ridged_mf",
+ "f_spiral",
+ "f_witch_of_agnesi",
+ }:
+ func = 6
+ if tex.pov.func_list in {"f_helix1", "f_helix2", "f_piriform_2d", "f_strophoid_2d"}:
+ func = 7
+ if tex.pov.func_list == "f_helical_torus":
+ func = 8
+ column_flow = layout.column_flow(columns=3, align=True)
+ column_flow.label(text="X")
+ column_flow.prop(tex.pov, "func_plus_x", text="")
+ column_flow.prop(tex.pov, "func_x", text="Value")
+ column_flow = layout.column_flow(columns=3, align=True)
+ column_flow.label(text="Y")
+ column_flow.prop(tex.pov, "func_plus_y", text="")
+ column_flow.prop(tex.pov, "func_y", text="Value")
+ column_flow = layout.column_flow(columns=3, align=True)
+ column_flow.label(text="Z")
+ column_flow.prop(tex.pov, "func_plus_z", text="")
+ column_flow.prop(tex.pov, "func_z", text="Value")
+ row = layout.row(align=align)
+ if func > 0:
+ row.prop(tex.pov, "func_P0", text="P0")
+ if func > 1:
+ row.prop(tex.pov, "func_P1", text="P1")
+ row = layout.row(align=align)
+ if func > 2:
+ row.prop(tex.pov, "func_P2", text="P2")
+ if func > 3:
+ row.prop(tex.pov, "func_P3", text="P3")
+ row = layout.row(align=align)
+ if func > 4:
+ row.prop(tex.pov, "func_P4", text="P4")
+ if func > 5:
+ row.prop(tex.pov, "func_P5", text="P5")
+ row = layout.row(align=align)
+ if func > 6:
+ row.prop(tex.pov, "func_P6", text="P6")
+ if func > 7:
+ row.prop(tex.pov, "func_P7", text="P7")
+ row = layout.row(align=align)
+ row.prop(tex.pov, "func_P8", text="P8")
+ row.prop(tex.pov, "func_P9", text="P9")
+ ###################################################End Patterns############################
+
+ layout.prop(tex.pov, "warp_types", text="Warp types") # warp
+ if tex.pov.warp_types == "TOROIDAL":
+ layout.prop(tex.pov, "warp_tor_major_radius", text="Major radius")
+ if tex.pov.warp_types not in {"CUBIC", "NONE"}:
+ layout.prop(tex.pov, "warp_orientation", text="Warp orientation")
+ col = layout.column(align=align)
+ row = col.row()
+ row.prop(tex.pov, "warp_dist_exp", text="Distance exponent")
+ row = col.row()
+ row.prop(tex.pov, "modifier_frequency", text="Frequency")
+ row.prop(tex.pov, "modifier_phase", text="Phase")
+
+ row = layout.row()
+
+ row.label(text="Offset:")
+ row.label(text="Scale:")
+ row.label(text="Rotate:")
+ col = layout.column(align=align)
+ row = col.row()
+ row.prop(tex.pov, "tex_mov_x", text="X")
+ row.prop(tex.pov, "tex_scale_x", text="X")
+ row.prop(tex.pov, "tex_rot_x", text="X")
+ row = col.row()
+ row.prop(tex.pov, "tex_mov_y", text="Y")
+ row.prop(tex.pov, "tex_scale_y", text="Y")
+ row.prop(tex.pov, "tex_rot_y", text="Y")
+ row = col.row()
+ row.prop(tex.pov, "tex_mov_z", text="Z")
+ row.prop(tex.pov, "tex_scale_z", text="Z")
+ row.prop(tex.pov, "tex_rot_z", text="Z")
+ row = layout.row()
+
+ row.label(text="Turbulence:")
+ col = layout.column(align=align)
+ row = col.row()
+ row.prop(tex.pov, "warp_turbulence_x", text="X")
+ row.prop(tex.pov, "modifier_octaves", text="Octaves")
+ row = col.row()
+ row.prop(tex.pov, "warp_turbulence_y", text="Y")
+ row.prop(tex.pov, "modifier_lambda", text="Lambda")
+ row = col.row()
+ row.prop(tex.pov, "warp_turbulence_z", text="Z")
+ row.prop(tex.pov, "modifier_omega", text="Omega")
+
+
+class TEXTURE_PT_POV_mapping(TextureSlotPanel, Panel):
+ """Use this class to define POV texture mapping buttons."""
+
+ bl_label = "Mapping"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+
+ @classmethod
+ def poll(cls, context):
+ idblock = pov_context_tex_datablock(context)
+ if isinstance(idblock, Brush) and not context.sculpt_object:
+ return False
+
+ if not getattr(context, "texture_slot", None):
+ return False
+
+ engine = context.scene.render.engine
+ return engine in cls.COMPAT_ENGINES
+
+ def draw(self, context):
+ layout = self.layout
+
+ idblock = pov_context_tex_datablock(context)
+ mat = bpy.context.active_object.active_material
+ # tex = context.texture_slot
+ tex = mat.pov_texture_slots[mat.active_texture_index]
+ if not isinstance(idblock, Brush):
+ split = layout.split(percentage=0.3)
+ col = split.column()
+ col.label(text="Coordinates:")
+ col = split.column()
+ col.prop(tex, "texture_coords", text="")
+
+ if tex.texture_coords == 'ORCO':
+ """
+ ob = context.object
+ if ob and ob.type == 'MESH':
+ split = layout.split(percentage=0.3)
+ split.label(text="Mesh:")
+ split.prop(ob.data, "texco_mesh", text="")
+ """
+ elif tex.texture_coords == 'UV':
+ split = layout.split(percentage=0.3)
+ split.label(text="Map:")
+ ob = context.object
+ if ob and ob.type == 'MESH':
+ split.prop_search(tex, "uv_layer", ob.data, "uv_textures", text="")
+ else:
+ split.prop(tex, "uv_layer", text="")
+
+ elif tex.texture_coords == 'OBJECT':
+ split = layout.split(percentage=0.3)
+ split.label(text="Object:")
+ split.prop(tex, "object", text="")
+
+ elif tex.texture_coords == 'ALONG_STROKE':
+ split = layout.split(percentage=0.3)
+ split.label(text="Use Tips:")
+ split.prop(tex, "use_tips", text="")
+
+ if isinstance(idblock, Brush):
+ if context.sculpt_object or context.image_paint_object:
+ brush_texture_settings(layout, idblock, context.sculpt_object)
+ else:
+ if isinstance(idblock, FreestyleLineStyle):
+ split = layout.split(percentage=0.3)
+ split.label(text="Projection:")
+ split.prop(tex, "mapping", text="")
+
+ split = layout.split(percentage=0.3)
+ split.separator()
+ row = split.row()
+ row.prop(tex, "mapping_x", text="")
+ row.prop(tex, "mapping_y", text="")
+ row.prop(tex, "mapping_z", text="")
+
+ elif isinstance(idblock, Material):
+ split = layout.split(percentage=0.3)
+ split.label(text="Projection:")
+ split.prop(tex, "mapping", text="")
+
+ split = layout.split()
+
+ col = split.column()
+ if tex.texture_coords in {'ORCO', 'UV'}:
+ col.prop(tex, "use_from_dupli")
+ if idblock.type == 'VOLUME' and tex.texture_coords == 'ORCO':
+ col.prop(tex, "use_map_to_bounds")
+ elif tex.texture_coords == 'OBJECT':
+ col.prop(tex, "use_from_original")
+ if idblock.type == 'VOLUME':
+ col.prop(tex, "use_map_to_bounds")
+ else:
+ col.label()
+
+ col = split.column()
+ row = col.row()
+ row.prop(tex, "mapping_x", text="")
+ row.prop(tex, "mapping_y", text="")
+ row.prop(tex, "mapping_z", text="")
+
+ row = layout.row()
+ row.column().prop(tex, "offset")
+ row.column().prop(tex, "scale")
+
+
+class TEXTURE_PT_POV_influence(TextureSlotPanel, Panel):
+ """Use this class to define pov texture influence buttons."""
+
+ bl_label = "Influence"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ # bl_context = 'texture'
+ @classmethod
+ def poll(cls, context):
+ idblock = pov_context_tex_datablock(context)
+ if (
+ # isinstance(idblock, Brush) and # Brush used for everything since 2.8
+ context.scene.texture_context
+ == 'OTHER'
+ ): # XXX replace by isinstance(idblock, bpy.types.Brush) and ...
+ return False
+
+ # Specify below also for pov_world_texture_slots, lights etc.
+ # to display for various types of slots but only when any
+ if not getattr(idblock, "pov_texture_slots", None):
+ return False
+
+ engine = context.scene.render.engine
+ return engine in cls.COMPAT_ENGINES
+
+ def draw(self, context):
+
+ layout = self.layout
+
+ idblock = pov_context_tex_datablock(context)
+ # tex = context.pov_texture_slot
+ # mat = bpy.context.active_object.active_material
+ texslot = idblock.pov_texture_slots[
+ idblock.pov.active_texture_index
+ ] # bpy.data.textures[mat.active_texture_index]
+ # below tex is unused
+ tex = bpy.data.textures[idblock.pov_texture_slots[idblock.pov.active_texture_index].texture]
+
+ def factor_but(layout, toggle, factor, name):
+ row = layout.row(align=True)
+ row.prop(texslot, toggle, text="")
+ sub = row.row(align=True)
+ sub.active = getattr(texslot, toggle)
+ sub.prop(texslot, factor, text=name, slider=True)
+ return sub # XXX, temp. use_map_normal needs to override.
+
+ if isinstance(idblock, Material):
+ split = layout.split()
+
+ col = split.column()
+ if idblock.pov.type in {'SURFACE', 'WIRE'}:
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Diffuse:")
+ factor_but(col, "use_map_diffuse", "diffuse_factor", "Intensity")
+ factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
+ factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
+ factor_but(col, "use_map_translucency", "translucency_factor", "Translucency")
+
+ col.label(text="Specular:")
+ factor_but(col, "use_map_specular", "specular_factor", "Intensity")
+ factor_but(col, "use_map_color_spec", "specular_color_factor", "Color")
+ factor_but(col, "use_map_hardness", "hardness_factor", "Hardness")
+
+ col = split.column()
+ col.label(text="Shading:")
+ factor_but(col, "use_map_ambient", "ambient_factor", "Ambient")
+ factor_but(col, "use_map_emit", "emit_factor", "Emit")
+ factor_but(col, "use_map_mirror", "mirror_factor", "Mirror")
+ factor_but(col, "use_map_raymir", "raymir_factor", "Ray Mirror")
+
+ col.label(text="Geometry:")
+ # XXX replace 'or' when displacement is fixed to not rely on normal influence value.
+ sub_tmp = factor_but(col, "use_map_normal", "normal_factor", "Normal")
+ sub_tmp.active = texslot.use_map_normal or texslot.use_map_displacement
+ # END XXX
+
+ factor_but(col, "use_map_warp", "warp_factor", "Warp")
+ factor_but(col, "use_map_displacement", "displacement_factor", "Displace")
+
+ elif idblock.pov.type == 'HALO':
+ layout.label(text="Halo:")
+
+ split = layout.split()
+
+ col = split.column()
+ factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
+ factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
+
+ col = split.column()
+ factor_but(col, "use_map_raymir", "raymir_factor", "Size")
+ factor_but(col, "use_map_hardness", "hardness_factor", "Hardness")
+ factor_but(col, "use_map_translucency", "translucency_factor", "Add")
+ elif idblock.pov.type == 'VOLUME':
+ layout.label(text="Volume:")
+
+ split = layout.split()
+
+ col = split.column()
+ factor_but(col, "use_map_density", "density_factor", "Density")
+ factor_but(col, "use_map_emission", "emission_factor", "Emission")
+ factor_but(col, "use_map_scatter", "scattering_factor", "Scattering")
+ factor_but(col, "use_map_reflect", "reflection_factor", "Reflection")
+
+ col = split.column()
+ col.label(text=" ")
+ factor_but(col, "use_map_color_emission", "emission_color_factor", "Emission Color")
+ factor_but(
+ col,
+ "use_map_color_transmission",
+ "transmission_color_factor",
+ "Transmission Color",
+ )
+ factor_but(
+ col, "use_map_color_reflection", "reflection_color_factor", "Reflection Color"
+ )
+
+ layout.label(text="Geometry:")
+
+ split = layout.split()
+
+ col = split.column()
+ factor_but(col, "use_map_warp", "warp_factor", "Warp")
+
+ col = split.column()
+ factor_but(col, "use_map_displacement", "displacement_factor", "Displace")
+
+ elif isinstance(idblock, Light):
+ split = layout.split()
+
+ col = split.column()
+ factor_but(col, "use_map_color", "color_factor", "Color")
+
+ col = split.column()
+ factor_but(col, "use_map_shadow", "shadow_factor", "Shadow")
+
+ elif isinstance(idblock, World):
+ split = layout.split()
+
+ col = split.column()
+ factor_but(col, "use_map_blend", "blend_factor", "Blend")
+ factor_but(col, "use_map_horizon", "horizon_factor", "Horizon")
+
+ col = split.column()
+ factor_but(col, "use_map_zenith_up", "zenith_up_factor", "Zenith Up")
+ factor_but(col, "use_map_zenith_down", "zenith_down_factor", "Zenith Down")
+ elif isinstance(idblock, ParticleSettings):
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="General:")
+ factor_but(col, "use_map_time", "time_factor", "Time")
+ factor_but(col, "use_map_life", "life_factor", "Lifetime")
+ factor_but(col, "use_map_density", "density_factor", "Density")
+ factor_but(col, "use_map_size", "size_factor", "Size")
+
+ col = split.column()
+ col.label(text="Physics:")
+ factor_but(col, "use_map_velocity", "velocity_factor", "Velocity")
+ factor_but(col, "use_map_damp", "damp_factor", "Damp")
+ factor_but(col, "use_map_gravity", "gravity_factor", "Gravity")
+ factor_but(col, "use_map_field", "field_factor", "Force Fields")
+
+ layout.label(text="Hair:")
+
+ split = layout.split()
+
+ col = split.column()
+ factor_but(col, "use_map_length", "length_factor", "Length")
+ factor_but(col, "use_map_clump", "clump_factor", "Clump")
+ factor_but(col, "use_map_twist", "twist_factor", "Twist")
+
+ col = split.column()
+ factor_but(col, "use_map_kink_amp", "kink_amp_factor", "Kink Amplitude")
+ factor_but(col, "use_map_kink_freq", "kink_freq_factor", "Kink Frequency")
+ factor_but(col, "use_map_rough", "rough_factor", "Rough")
+
+ elif isinstance(idblock, FreestyleLineStyle):
+ split = layout.split()
+
+ col = split.column()
+ factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
+ col = split.column()
+ factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
+
+ layout.separator()
+
+ if not isinstance(idblock, ParticleSettings):
+ split = layout.split()
+
+ col = split.column()
+ # col.prop(tex, "blend_type", text="Blend") #deprecated since 2.8
+ # col.prop(tex, "use_rgb_to_intensity") #deprecated since 2.8
+ # color is used on gray-scale textures even when use_rgb_to_intensity is disabled.
+ # col.prop(tex, "color", text="") #deprecated since 2.8
+
+ col = split.column()
+ # col.prop(tex, "invert", text="Negative") #deprecated since 2.8
+ # col.prop(tex, "use_stencil") #deprecated since 2.8
+
+ # if isinstance(idblock, (Material, World)):
+ # col.prop(tex, "default_value", text="DVar", slider=True)
+
+
+class TEXTURE_PT_POV_tex_gamma(TextureButtonsPanel, Panel):
+ """Use this class to define pov texture gamma buttons."""
+
+ bl_label = "Image Gamma"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def draw_header(self, context):
+ tex = context.texture
+
+ self.layout.prop(tex.pov, "tex_gamma_enable", text="", icon='SEQ_LUMA_WAVEFORM')
+
+ def draw(self, context):
+ layout = self.layout
+
+ tex = context.texture
+
+ layout.active = tex.pov.tex_gamma_enable
+ layout.prop(tex.pov, "tex_gamma_value", text="Gamma Value")
+
+
+# commented out below UI for texture only custom code inside exported material:
+# class TEXTURE_PT_povray_replacement_text(TextureButtonsPanel, Panel):
+# bl_label = "Custom POV Code"
+# COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+# def draw(self, context):
+# layout = self.layout
+
+# tex = context.texture
+
+# col = layout.column()
+# col.label(text="Replace properties with:")
+# col.prop(tex.pov, "replacement_text", text="")
+
+
+classes = (
+ WORLD_TEXTURE_SLOTS_UL_POV_layerlist,
+ TEXTURE_MT_POV_specials,
+ TEXTURE_PT_POV_context_texture,
+ TEXTURE_PT_colors,
+ TEXTURE_PT_POV_type,
+ TEXTURE_PT_POV_preview,
+ TEXTURE_PT_POV_parameters,
+ TEXTURE_PT_POV_tex_gamma,
+ MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist,
+ TEXTURE_OT_POV_texture_slot_add,
+ TEXTURE_OT_POV_texture_slot_remove,
+ TEXTURE_PT_POV_influence,
+ TEXTURE_PT_POV_mapping,
+)
+
+
+def register():
+
+ for cls in classes:
+ register_class(cls)
+
+
+def unregister():
+
+ for cls in reversed(classes):
+ if cls != TEXTURE_PT_context:
+ unregister_class(cls)