1# ##### BEGIN GPL LICENSE BLOCK #####
2#
3#  This program is free software; you can redistribute it and/or
4#  modify it under the terms of the GNU General Public License
5#  as published by the Free Software Foundation; either version 2
6#  of the License, or (at your option) any later version.
7#
8#  This program is distributed in the hope that it will be useful,
9#  but WITHOUT ANY WARRANTY; without even the implied warranty of
10#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11#  GNU General Public License for more details.
12#
13#  You should have received a copy of the GNU General Public License
14#  along with this program; if not, write to the Free Software Foundation,
15#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16#
17# ##### END GPL LICENSE BLOCK #####
18
19# <pep8 compliant>
20"""User interface for the POV tools"""
21
22import bpy
23import sys  # really import here and in render.py?
24import os  # really import here and in render.py?
25import addon_utils
26from time import sleep
27from os.path import isfile
28from bpy.app.handlers import persistent
29from bl_operators.presets import AddPresetBase
30from bpy.utils import register_class, unregister_class
31from bpy.types import (
32    Operator,
33    Menu,
34    UIList,
35    Panel,
36    Brush,
37    Material,
38    Light,
39    World,
40    ParticleSettings,
41    FreestyleLineStyle,
42)
43
44# Example of wrapping every class 'as is'
45from bl_ui import properties_output
46
47for member in dir(properties_output):
48    subclass = getattr(properties_output, member)
49    try:
50        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
51    except:
52        pass
53del properties_output
54
55from bl_ui import properties_freestyle
56for member in dir(properties_freestyle):
57    subclass = getattr(properties_freestyle, member)
58    try:
59        if not (subclass.bl_space_type == 'PROPERTIES'
60            and subclass.bl_context == "render"):
61            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
62            #subclass.bl_parent_id = "RENDER_PT_POV_filter"
63    except:
64        pass
65del properties_freestyle
66
67from bl_ui import properties_view_layer
68
69for member in dir(properties_view_layer):
70    subclass = getattr(properties_view_layer, member)
71    try:
72        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
73    except:
74        pass
75del properties_view_layer
76
77# Use some of the existing buttons.
78from bl_ui import properties_render
79
80# DEPRECATED#properties_render.RENDER_PT_render.COMPAT_ENGINES.add('POVRAY_RENDER')
81# DEPRECATED#properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('POVRAY_RENDER')
82# properties_render.RENDER_PT_antialiasing.COMPAT_ENGINES.add('POVRAY_RENDER')
83# TORECREATE##DEPRECATED#properties_render.RENDER_PT_shading.COMPAT_ENGINES.add('POVRAY_RENDER')
84# DEPRECATED#properties_render.RENDER_PT_output.COMPAT_ENGINES.add('POVRAY_RENDER')
85del properties_render
86
87
88# Use only a subset of the world panels
89from bl_ui import properties_world
90
91# TORECREATE##DEPRECATED#properties_world.WORLD_PT_preview.COMPAT_ENGINES.add('POVRAY_RENDER')
92properties_world.WORLD_PT_context_world.COMPAT_ENGINES.add('POVRAY_RENDER')
93# TORECREATE##DEPRECATED#properties_world.WORLD_PT_world.COMPAT_ENGINES.add('POVRAY_RENDER')
94# TORECREATE##DEPRECATED#properties_world.WORLD_PT_mist.COMPAT_ENGINES.add('POVRAY_RENDER')
95del properties_world
96
97
98# Example of wrapping every class 'as is'
99from bl_ui import properties_texture
100from bl_ui.properties_texture import context_tex_datablock
101from bl_ui.properties_texture import texture_filter_common
102
103for member in dir(properties_texture):
104    subclass = getattr(properties_texture, member)
105    try:
106        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
107    except:
108        pass
109del properties_texture
110
111# Physics Main wrapping every class 'as is'
112from bl_ui import properties_physics_common
113
114for member in dir(properties_physics_common):
115    subclass = getattr(properties_physics_common, member)
116    try:
117        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
118    except:
119        pass
120del properties_physics_common
121
122# Physics Rigid Bodies wrapping every class 'as is'
123from bl_ui import properties_physics_rigidbody
124
125for member in dir(properties_physics_rigidbody):
126    subclass = getattr(properties_physics_rigidbody, member)
127    try:
128        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
129    except:
130        pass
131del properties_physics_rigidbody
132
133# Physics Rigid Body Constraint wrapping every class 'as is'
134from bl_ui import properties_physics_rigidbody_constraint
135
136for member in dir(properties_physics_rigidbody_constraint):
137    subclass = getattr(properties_physics_rigidbody_constraint, member)
138    try:
139        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
140    except:
141        pass
142del properties_physics_rigidbody_constraint
143
144# Physics Smoke wrapping every class 'as is'
145from bl_ui import properties_physics_fluid
146
147for member in dir(properties_physics_fluid):
148    subclass = getattr(properties_physics_fluid, member)
149    try:
150        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
151    except:
152        pass
153del properties_physics_fluid
154
155# Physics softbody wrapping every class 'as is'
156from bl_ui import properties_physics_softbody
157
158for member in dir(properties_physics_softbody):
159    subclass = getattr(properties_physics_softbody, member)
160    try:
161        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
162    except:
163        pass
164del properties_physics_softbody
165
166# Physics Fluid wrapping every class 'as is'
167from bl_ui import properties_physics_fluid
168
169for member in dir(properties_physics_fluid):
170    subclass = getattr(properties_physics_fluid, member)
171    try:
172        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
173    except:
174        pass
175del properties_physics_fluid
176
177# Physics Field wrapping every class 'as is'
178from bl_ui import properties_physics_field
179
180for member in dir(properties_physics_field):
181    subclass = getattr(properties_physics_field, member)
182    try:
183        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
184    except:
185        pass
186del properties_physics_field
187
188# Physics Cloth wrapping every class 'as is'
189from bl_ui import properties_physics_cloth
190
191for member in dir(properties_physics_cloth):
192    subclass = getattr(properties_physics_cloth, member)
193    try:
194        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
195    except:
196        pass
197del properties_physics_cloth
198
199# Physics Dynamic Paint wrapping every class 'as is'
200from bl_ui import properties_physics_dynamicpaint
201
202for member in dir(properties_physics_dynamicpaint):
203    subclass = getattr(properties_physics_dynamicpaint, member)
204    try:
205        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
206    except:
207        pass
208del properties_physics_dynamicpaint
209
210
211# Example of wrapping every class 'as is'
212from bl_ui import properties_data_modifier
213
214for member in dir(properties_data_modifier):
215    subclass = getattr(properties_data_modifier, member)
216    try:
217        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
218    except:
219        pass
220del properties_data_modifier
221
222# Example of wrapping every class 'as is' except some
223from bl_ui import properties_material
224
225for member in dir(properties_material):
226    subclass = getattr(properties_material, member)
227    try:
228        # mat=bpy.context.active_object.active_material
229        # if (mat and mat.pov.type == "SURFACE"
230        # and not (mat.pov.material_use_nodes or mat.use_nodes)):
231        # and (engine in cls.COMPAT_ENGINES)) if subclasses were sorted
232        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
233    except:
234        pass
235del properties_material
236
237
238from bl_ui import properties_data_camera
239
240for member in dir(properties_data_camera):
241    subclass = getattr(properties_data_camera, member)
242    try:
243        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
244    except:
245        pass
246del properties_data_camera
247
248
249from bl_ui import properties_particle as properties_particle
250
251for member in dir(
252    properties_particle
253):  # add all "particle" panels from blender
254    subclass = getattr(properties_particle, member)
255    try:
256        subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
257    except:
258        pass
259del properties_particle
260
261
262############# POV-Centric WORSPACE #############
263@persistent
264def povCentricWorkspace(dummy):
265    """Set up a POV centric Workspace if addon was activated and saved as default renderer
266
267    This would bring a ’_RestrictData’ error because UI needs to be fully loaded before
268    workspace changes so registering this function in bpy.app.handlers is needed.
269    By default handlers are freed when loading new files, but here we want the handler
270    to stay running across multiple files as part of this add-on. That is why the the
271    bpy.app.handlers.persistent decorator is used (@persistent) above.
272    """
273
274    wsp = bpy.data.workspaces.get('Scripting')
275    context = bpy.context
276    if wsp is not None and context.scene.render.engine == 'POVRAY_RENDER':
277        new_wsp = bpy.ops.workspace.duplicate({'workspace': wsp})
278        bpy.data.workspaces['Scripting.001'].name='POV'
279        # Already done it would seem, but explicitly make this workspaces the active one
280        context.window.workspace = bpy.data.workspaces['POV']
281        pov_screen = bpy.data.workspaces['POV'].screens[0]
282        pov_workspace = pov_screen.areas
283
284
285        override = bpy.context.copy()
286
287        for area in pov_workspace:
288            if area.type == 'VIEW_3D':
289                for region in [r for r in area.regions if r.type == 'WINDOW']:
290                    for space in area.spaces:
291                        if space.type == 'VIEW_3D':
292                            #override['screen'] = pov_screen
293                            override['area'] = area
294                            override['region']= region
295                            #bpy.data.workspaces['POV'].screens[0].areas[6].spaces[0].width = 333 # Read only, how do we set ?
296                            #This has a glitch:
297                            #bpy.ops.screen.area_move(override, x=(area.x + area.width), y=(area.y + 5), delta=100)
298                            #bpy.ops.screen.area_move(override, x=(area.x + 5), y=area.y, delta=-100)
299
300                            bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'TEXT_EDITOR')
301                            space.show_region_ui = True
302                            #bpy.ops.screen.region_scale(override)
303                            #bpy.ops.screen.region_scale()
304                            break
305
306            elif area.type == 'CONSOLE':
307                for region in [r for r in area.regions if r.type == 'WINDOW']:
308                    for space in area.spaces:
309                        if space.type == 'CONSOLE':
310                            #override['screen'] = pov_screen
311                            override['area'] = area
312                            override['region']= region
313                            bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'INFO')
314
315                            break
316            elif area.type == 'INFO':
317                for region in [r for r in area.regions if r.type == 'WINDOW']:
318                    for space in area.spaces:
319                        if space.type == 'INFO':
320                            #override['screen'] = pov_screen
321                            override['area'] = area
322                            override['region']= region
323                            bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'CONSOLE')
324
325                            break
326
327            elif area.type == 'TEXT_EDITOR':
328                for region in [r for r in area.regions if r.type == 'WINDOW']:
329                    for space in area.spaces:
330                        if space.type == 'TEXT_EDITOR':
331                            #override['screen'] = pov_screen
332                            override['area'] = area
333                            override['region']= region
334                            #bpy.ops.screen.space_type_set_or_cycle(space_type='VIEW_3D')
335                            #space.type = 'VIEW_3D'
336                            bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'VIEW_3D')
337
338                            #bpy.ops.screen.area_join(override, cursor=(area.x, area.y + area.height))
339
340                            break
341
342
343            if area.type == 'VIEW_3D':
344                for region in [r for r in area.regions if r.type == 'WINDOW']:
345                    for space in area.spaces:
346                        if space.type == 'VIEW_3D':
347                            #override['screen'] = pov_screen
348                            override['area'] = area
349                            override['region']= region
350                            bpy.ops.screen.region_quadview(override)
351                            space.region_3d.view_perspective = 'CAMERA'
352                            #bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'TEXT_EDITOR')
353                            #bpy.ops.screen.region_quadview(override)
354
355
356
357
358
359
360        bpy.data.workspaces.update()
361        # Already outliners but invert both types
362        pov_workspace[1].spaces[0].display_mode = 'LIBRARIES'
363        pov_workspace[3].spaces[0].display_mode = 'VIEW_LAYER'
364
365        '''
366        for window in bpy.context.window_manager.windows:
367            for area in [a for a in window.screen.areas if a.type == 'VIEW_3D']:
368                for region in [r for r in area.regions if r.type == 'WINDOW']:
369                    context_override = {
370                        'window': window,
371                        'screen': window.screen,
372                        'area': area,
373                        'region': region,
374                        'space_data': area.spaces.active,
375                        'scene': bpy.context.scene
376                        }
377                    bpy.ops.view3d.camera_to_view(context_override)
378        '''
379
380
381    else:
382        print("default 'Scripting' workspace needed for POV centric Workspace")
383
384
385
386
387
388
389
390class WORLD_MT_POV_presets(Menu):
391    bl_label = "World Presets"
392    preset_subdir = "pov/world"
393    preset_operator = "script.execute_preset"
394    draw = bpy.types.Menu.draw_preset
395
396
397class WORLD_OT_POV_add_preset(AddPresetBase, Operator):
398    """Add a World Preset"""
399
400    bl_idname = "object.world_preset_add"
401    bl_label = "Add World Preset"
402    preset_menu = "WORLD_MT_POV_presets"
403
404    # variable used for all preset values
405    preset_defines = ["scene = bpy.context.scene"]
406
407    # properties to store in the preset
408    preset_values = [
409        "scene.world.use_sky_blend",
410        "scene.world.horizon_color",
411        "scene.world.zenith_color",
412        "scene.world.ambient_color",
413        "scene.world.mist_settings.use_mist",
414        "scene.world.mist_settings.intensity",
415        "scene.world.mist_settings.depth",
416        "scene.world.mist_settings.start",
417        "scene.pov.media_enable",
418        "scene.pov.media_scattering_type",
419        "scene.pov.media_samples",
420        "scene.pov.media_diffusion_scale",
421        "scene.pov.media_diffusion_color",
422        "scene.pov.media_absorption_scale",
423        "scene.pov.media_absorption_color",
424        "scene.pov.media_eccentricity",
425    ]
426
427    # where to store the preset
428    preset_subdir = "pov/world"
429
430
431def check_material(mat):
432    if mat is not None:
433        if mat.use_nodes:
434            if (
435                not mat.node_tree
436            ):  # FORMERLY : #mat.active_node_material is not None:
437                return True
438            return False
439        return True
440    return False
441
442
443def simple_material(mat):
444    """Test if a material uses nodes"""
445    if (mat is not None) and (not mat.use_nodes):
446        return True
447    return False
448
449
450def check_add_mesh_extra_objects():
451    """Test if Add mesh extra objects addon is activated
452
453    This addon is currently used to generate the proxy for POV parametric
454    surface which is almost the same priciple as its Math xyz surface
455    """
456    if "add_mesh_extra_objects" in bpy.context.preferences.addons.keys():
457        return True
458    return False
459
460def check_render_freestyle_svg():
461    """Test if Freestyle SVG Exporter addon is activated
462
463    This addon is currently used to generate the SVG lines file
464    when Freestyle is enabled alongside POV
465    """
466    if "render_freestyle_svg" in bpy.context.preferences.addons.keys():
467        return True
468    return False
469
470def locate_docpath():
471    """POV can be installed with some include files.
472
473    Get their path as defined in user preferences or registry keys for
474    the user to be able to invoke them."""
475
476    addon_prefs = bpy.context.preferences.addons[__package__].preferences
477    # Use the system preference if its set.
478    pov_documents = addon_prefs.docpath_povray
479    if pov_documents:
480        if os.path.exists(pov_documents):
481            return pov_documents
482        else:
483            print(
484                "User Preferences path to povray documents %r NOT FOUND, checking $PATH"
485                % pov_documents
486            )
487
488    # Windows Only
489    if sys.platform[:3] == "win":
490        import winreg
491
492        try:
493            win_reg_key = winreg.OpenKey(
494                winreg.HKEY_CURRENT_USER, "Software\\POV-Ray\\v3.7\\Windows"
495            )
496            win_docpath = winreg.QueryValueEx(win_reg_key, "DocPath")[0]
497            pov_documents = os.path.join(win_docpath, "Insert Menu")
498            if os.path.exists(pov_documents):
499                return pov_documents
500        except FileNotFoundError:
501            return ""
502    # search the path all os's
503    pov_documents_default = "include"
504
505    os_path_ls = os.getenv("PATH").split(':') + [""]
506
507    for dir_name in os_path_ls:
508        pov_documents = os.path.join(dir_name, pov_documents_default)
509        if os.path.exists(pov_documents):
510            return pov_documents
511    return ""
512
513
514def pov_context_tex_datablock(context):
515    """Texture context type recreated as deprecated in blender 2.8"""
516
517    idblock = context.brush
518    if idblock and context.scene.texture_context == 'OTHER':
519        return idblock
520
521    # idblock = bpy.context.active_object.active_material
522    idblock = context.view_layer.objects.active.active_material
523    if idblock and context.scene.texture_context == 'MATERIAL':
524        return idblock
525
526    idblock = context.scene.world
527    if idblock and context.scene.texture_context == 'WORLD':
528        return idblock
529
530    idblock = context.light
531    if idblock and context.scene.texture_context == 'LIGHT':
532        return idblock
533
534    if context.particle_system and context.scene.texture_context == 'PARTICLES':
535        idblock = context.particle_system.settings
536
537    return idblock
538
539    idblock = context.line_style
540    if idblock and context.scene.texture_context == 'LINESTYLE':
541        return idblock
542
543
544class RenderButtonsPanel:
545    """Use this class to define buttons from the render tab of
546    properties window."""
547
548    bl_space_type = 'PROPERTIES'
549    bl_region_type = 'WINDOW'
550    bl_context = "render"
551    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
552
553    @classmethod
554    def poll(cls, context):
555        rd = context.scene.render
556        return rd.engine in cls.COMPAT_ENGINES
557
558
559class ModifierButtonsPanel:
560    """Use this class to define buttons from the modifier tab of
561    properties window."""
562
563    bl_space_type = 'PROPERTIES'
564    bl_region_type = 'WINDOW'
565    bl_context = "modifier"
566    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
567
568    @classmethod
569    def poll(cls, context):
570        mods = context.object.modifiers
571        rd = context.scene.render
572        return mods and (rd.engine in cls.COMPAT_ENGINES)
573
574
575class MaterialButtonsPanel:
576    """Use this class to define buttons from the material tab of
577    properties window."""
578
579    bl_space_type = 'PROPERTIES'
580    bl_region_type = 'WINDOW'
581    bl_context = "material"
582    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
583
584    @classmethod
585    def poll(cls, context):
586        mat = context.material
587        rd = context.scene.render
588        return mat and (rd.engine in cls.COMPAT_ENGINES)
589
590
591class TextureButtonsPanel:
592    """Use this class to define buttons from the texture tab of
593    properties window."""
594
595    bl_space_type = 'PROPERTIES'
596    bl_region_type = 'WINDOW'
597    bl_context = "texture"
598    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
599
600    @classmethod
601    def poll(cls, context):
602        tex = context.texture
603        rd = context.scene.render
604        return tex and (rd.engine in cls.COMPAT_ENGINES)
605
606
607# class TextureTypePanel(TextureButtonsPanel):
608
609# @classmethod
610# def poll(cls, context):
611# tex = context.texture
612# engine = context.scene.render.engine
613# return tex and ((tex.type == cls.tex_type and not tex.use_nodes) and (engine in cls.COMPAT_ENGINES))
614
615
616class ObjectButtonsPanel:
617    """Use this class to define buttons from the object tab of
618    properties window."""
619
620    bl_space_type = 'PROPERTIES'
621    bl_region_type = 'WINDOW'
622    bl_context = "object"
623    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
624
625    @classmethod
626    def poll(cls, context):
627        obj = context.object
628        rd = context.scene.render
629        return obj and (rd.engine in cls.COMPAT_ENGINES)
630
631
632class CameraDataButtonsPanel:
633    """Use this class to define buttons from the camera data tab of
634    properties window."""
635
636    bl_space_type = 'PROPERTIES'
637    bl_region_type = 'WINDOW'
638    bl_context = "data"
639    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
640
641    @classmethod
642    def poll(cls, context):
643        cam = context.camera
644        rd = context.scene.render
645        return cam and (rd.engine in cls.COMPAT_ENGINES)
646
647
648class WorldButtonsPanel:
649    """Use this class to define buttons from the world tab of
650    properties window."""
651
652    bl_space_type = 'PROPERTIES'
653    bl_region_type = 'WINDOW'
654    bl_context = "world"
655    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
656
657    @classmethod
658    def poll(cls, context):
659        wld = context.world
660        rd = context.scene.render
661        return wld and (rd.engine in cls.COMPAT_ENGINES)
662
663
664class TextButtonsPanel:
665    """Use this class to define buttons from the side tab of
666    text window."""
667
668    bl_space_type = 'TEXT_EDITOR'
669    bl_region_type = 'UI'
670    bl_label = "POV-Ray"
671    # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
672
673    @classmethod
674    def poll(cls, context):
675        text = context.space_data
676        rd = context.scene.render
677        return text and (rd.engine in cls.COMPAT_ENGINES)
678
679
680from bl_ui import properties_data_mesh
681
682# These panels are kept
683properties_data_mesh.DATA_PT_custom_props_mesh.COMPAT_ENGINES.add(
684    'POVRAY_RENDER'
685)
686properties_data_mesh.DATA_PT_context_mesh.COMPAT_ENGINES.add('POVRAY_RENDER')
687
688## make some native panels contextual to some object variable
689## by recreating custom panels inheriting their properties
690
691
692class PovDataButtonsPanel(properties_data_mesh.MeshButtonsPanel):
693    """Use this class to define buttons from the edit data tab of
694    properties window."""
695
696    COMPAT_ENGINES = {'POVRAY_RENDER'}
697    POV_OBJECT_TYPES = {
698        'PLANE',
699        'BOX',
700        'SPHERE',
701        'CYLINDER',
702        'CONE',
703        'TORUS',
704        'BLOB',
705        'ISOSURFACE',
706        'SUPERELLIPSOID',
707        'SUPERTORUS',
708        'HEIGHT_FIELD',
709        'PARAMETRIC',
710        'POLYCIRCLE',
711    }
712
713    @classmethod
714    def poll(cls, context):
715        engine = context.scene.render.engine
716        obj = context.object
717        # We use our parent class poll func too, avoids to re-define too much things...
718        return (
719            super(PovDataButtonsPanel, cls).poll(context)
720            and obj
721            and obj.pov.object_as not in cls.POV_OBJECT_TYPES
722        )
723
724
725# We cannot inherit from RNA classes (like e.g. properties_data_mesh.DATA_PT_vertex_groups).
726# Complex py/bpy/rna interactions (with metaclass and all) simply do not allow it to work.
727# So we simply have to explicitly copy here the interesting bits. ;)
728class DATA_PT_POV_normals(PovDataButtonsPanel, Panel):
729    bl_label = properties_data_mesh.DATA_PT_normals.bl_label
730
731    draw = properties_data_mesh.DATA_PT_normals.draw
732
733
734class DATA_PT_POV_texture_space(PovDataButtonsPanel, Panel):
735    bl_label = properties_data_mesh.DATA_PT_texture_space.bl_label
736    bl_options = properties_data_mesh.DATA_PT_texture_space.bl_options
737
738    draw = properties_data_mesh.DATA_PT_texture_space.draw
739
740
741class DATA_PT_POV_vertex_groups(PovDataButtonsPanel, Panel):
742    bl_label = properties_data_mesh.DATA_PT_vertex_groups.bl_label
743
744    draw = properties_data_mesh.DATA_PT_vertex_groups.draw
745
746
747class DATA_PT_POV_shape_keys(PovDataButtonsPanel, Panel):
748    bl_label = properties_data_mesh.DATA_PT_shape_keys.bl_label
749
750    draw = properties_data_mesh.DATA_PT_shape_keys.draw
751
752
753class DATA_PT_POV_uv_texture(PovDataButtonsPanel, Panel):
754    bl_label = properties_data_mesh.DATA_PT_uv_texture.bl_label
755
756    draw = properties_data_mesh.DATA_PT_uv_texture.draw
757
758
759class DATA_PT_POV_vertex_colors(PovDataButtonsPanel, Panel):
760    bl_label = properties_data_mesh.DATA_PT_vertex_colors.bl_label
761
762    draw = properties_data_mesh.DATA_PT_vertex_colors.draw
763
764
765class DATA_PT_POV_customdata(PovDataButtonsPanel, Panel):
766    bl_label = properties_data_mesh.DATA_PT_customdata.bl_label
767    bl_options = properties_data_mesh.DATA_PT_customdata.bl_options
768    draw = properties_data_mesh.DATA_PT_customdata.draw
769
770
771del properties_data_mesh
772
773
774################################################################################
775# from bl_ui import properties_data_light
776# for member in dir(properties_data_light):
777# subclass = getattr(properties_data_light, member)
778# try:
779# subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
780# except:
781# pass
782# del properties_data_light
783#########################LIGHTS################################
784
785from bl_ui import properties_data_light
786
787# These panels are kept
788properties_data_light.DATA_PT_custom_props_light.COMPAT_ENGINES.add(
789    'POVRAY_RENDER'
790)
791properties_data_light.DATA_PT_context_light.COMPAT_ENGINES.add('POVRAY_RENDER')
792
793## make some native panels contextual to some object variable
794## by recreating custom panels inheriting their properties
795class PovLampButtonsPanel(properties_data_light.DataButtonsPanel):
796    """Use this class to define buttons from the light data tab of
797    properties window."""
798
799    COMPAT_ENGINES = {'POVRAY_RENDER'}
800    POV_OBJECT_TYPES = {'RAINBOW'}
801
802    @classmethod
803    def poll(cls, context):
804        engine = context.scene.render.engine
805        obj = context.object
806        # We use our parent class poll func too, avoids to re-define too much things...
807        return (
808            super(PovLampButtonsPanel, cls).poll(context)
809            and obj
810            and obj.pov.object_as not in cls.POV_OBJECT_TYPES
811        )
812
813
814# We cannot inherit from RNA classes (like e.g. properties_data_mesh.DATA_PT_vertex_groups).
815# Complex py/bpy/rna interactions (with metaclass and all) simply do not allow it to work.
816# So we simply have to explicitly copy here the interesting bits. ;)
817
818
819class LIGHT_PT_POV_preview(PovLampButtonsPanel, Panel):
820    bl_label = properties_data_light.DATA_PT_preview.bl_label
821
822    draw = properties_data_light.DATA_PT_preview.draw
823
824
825class LIGHT_PT_POV_light(PovLampButtonsPanel, Panel):
826    bl_label = properties_data_light.DATA_PT_light.bl_label
827
828    draw = properties_data_light.DATA_PT_light.draw
829
830
831class LIGHT_MT_POV_presets(Menu):
832    """Use this class to define preset menu for pov lights."""
833
834    bl_label = "Lamp Presets"
835    preset_subdir = "pov/light"
836    preset_operator = "script.execute_preset"
837    draw = bpy.types.Menu.draw_preset
838
839
840class LIGHT_OT_POV_add_preset(AddPresetBase, Operator):
841    """Use this class to define pov world buttons."""
842
843    '''Add a Light Preset'''
844    bl_idname = "object.light_preset_add"
845    bl_label = "Add Light Preset"
846    preset_menu = "LIGHT_MT_POV_presets"
847
848    # variable used for all preset values
849    preset_defines = ["lightdata = bpy.context.object.data"]
850
851    # properties to store in the preset
852    preset_values = ["lightdata.type", "lightdata.color"]
853
854    # where to store the preset
855    preset_subdir = "pov/light"
856
857
858# Draw into the existing light panel
859def light_panel_func(self, context):
860    layout = self.layout
861
862    row = layout.row(align=True)
863    row.menu(LIGHT_MT_POV_presets.__name__, text=LIGHT_MT_POV_presets.bl_label)
864    row.operator(LIGHT_OT_POV_add_preset.bl_idname, text="", icon='ADD')
865    row.operator(
866        LIGHT_OT_POV_add_preset.bl_idname, text="", icon='REMOVE'
867    ).remove_active = True
868
869
870'''#TORECREATE##DEPRECATED#
871class LIGHT_PT_POV_sunsky(PovLampButtonsPanel, Panel):
872    bl_label = properties_data_light.DATA_PT_sunsky.bl_label
873
874    @classmethod
875    def poll(cls, context):
876        lamp = context.light
877        engine = context.scene.render.engine
878        return (lamp and lamp.type == 'SUN') and (engine in cls.COMPAT_ENGINES)
879
880    draw = properties_data_light.DATA_PT_sunsky.draw
881
882'''
883
884
885class LIGHT_PT_POV_shadow(PovLampButtonsPanel, Panel):
886    bl_label = "Shadow"
887    COMPAT_ENGINES = {'POVRAY_RENDER'}
888
889    @classmethod
890    def poll(cls, context):
891        lamp = context.lamp
892        engine = context.scene.render.engine
893        return lamp and (engine in cls.COMPAT_ENGINES)
894
895    def draw(self, context):
896        layout = self.layout
897
898        lamp = context.lamp
899
900        layout.row().prop(lamp, "shadow_method", expand=True)
901
902        split = layout.split()
903
904        col = split.column()
905        sub = col.column()
906        sub.prop(lamp, "spot_size", text="Size")
907        sub.prop(lamp, "spot_blend", text="Blend", slider=True)
908        col.prop(lamp, "use_square")
909        col.prop(lamp, "show_cone")
910
911        col = split.column()
912
913        col.active = (
914            lamp.shadow_method != 'BUFFER_SHADOW'
915            or lamp.shadow_buffer_type != 'DEEP'
916        )
917        col.prop(lamp, "use_halo")
918        sub = col.column(align=True)
919        sub.active = lamp.use_halo
920        sub.prop(lamp, "halo_intensity", text="Intensity")
921        if lamp.shadow_method == 'BUFFER_SHADOW':
922            sub.prop(lamp, "halo_step", text="Step")
923        if lamp.shadow_method == 'NOSHADOW' and lamp.type == 'AREA':
924            split = layout.split()
925
926            col = split.column()
927            col.label(text="Form factor sampling:")
928
929            sub = col.row(align=True)
930
931            if lamp.shape == 'SQUARE':
932                sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
933            elif lamp.shape == 'RECTANGLE':
934                sub.prop(lamp.pov, "shadow_ray_samples_x", text="Samples X")
935                sub.prop(lamp.pov, "shadow_ray_samples_y", text="Samples Y")
936
937        if lamp.shadow_method != 'NOSHADOW':
938            split = layout.split()
939
940            col = split.column()
941            col.prop(lamp, "shadow_color", text="")
942
943            col = split.column()
944            col.prop(lamp, "use_shadow_layer", text="This Layer Only")
945            col.prop(lamp, "use_only_shadow")
946
947        if lamp.shadow_method == 'RAY_SHADOW':
948            split = layout.split()
949
950            col = split.column()
951            col.label(text="Sampling:")
952
953            if lamp.type in {'POINT', 'SUN', 'SPOT'}:
954                sub = col.row()
955
956                sub.prop(lamp, "shadow_ray_samples", text="Samples")
957                sub.prop(lamp, "shadow_soft_size", text="Soft Size")
958
959            elif lamp.type == 'AREA':
960                sub = col.row(align=True)
961
962                if lamp.shape == 'SQUARE':
963                    sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
964                elif lamp.shape == 'RECTANGLE':
965                    sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
966                    sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
967
968
969'''
970        if lamp.shadow_method == 'NOSHADOW' and lamp.type == 'AREA':
971            split = layout.split()
972
973            col = split.column()
974            col.label(text="Form factor sampling:")
975
976            sub = col.row(align=True)
977
978            if lamp.shape == 'SQUARE':
979                sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
980            elif lamp.shape == 'RECTANGLE':
981                sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
982                sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
983
984        if lamp.shadow_method != 'NOSHADOW':
985            split = layout.split()
986
987            col = split.column()
988            col.prop(lamp, "shadow_color", text="")
989
990            col = split.column()
991            col.prop(lamp, "use_shadow_layer", text="This Layer Only")
992            col.prop(lamp, "use_only_shadow")
993
994        if lamp.shadow_method == 'RAY_SHADOW':
995            split = layout.split()
996
997            col = split.column()
998            col.label(text="Sampling:")
999
1000            if lamp.type in {'POINT', 'SUN', 'SPOT'}:
1001                sub = col.row()
1002
1003                sub.prop(lamp, "shadow_ray_samples", text="Samples")
1004                sub.prop(lamp, "shadow_soft_size", text="Soft Size")
1005
1006            elif lamp.type == 'AREA':
1007                sub = col.row(align=True)
1008
1009                if lamp.shape == 'SQUARE':
1010                    sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
1011                elif lamp.shape == 'RECTANGLE':
1012                    sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
1013                    sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
1014
1015            col.row().prop(lamp, "shadow_ray_sample_method", expand=True)
1016
1017            if lamp.shadow_ray_sample_method == 'ADAPTIVE_QMC':
1018                layout.prop(lamp, "shadow_adaptive_threshold", text="Threshold")
1019
1020            if lamp.type == 'AREA' and lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
1021                row = layout.row()
1022                row.prop(lamp, "use_umbra")
1023                row.prop(lamp, "use_dither")
1024                row.prop(lamp, "use_jitter")
1025
1026        elif lamp.shadow_method == 'BUFFER_SHADOW':
1027            col = layout.column()
1028            col.label(text="Buffer Type:")
1029            col.row().prop(lamp, "shadow_buffer_type", expand=True)
1030
1031            if lamp.shadow_buffer_type in {'REGULAR', 'HALFWAY', 'DEEP'}:
1032                split = layout.split()
1033
1034                col = split.column()
1035                col.label(text="Filter Type:")
1036                col.prop(lamp, "shadow_filter_type", text="")
1037                sub = col.column(align=True)
1038                sub.prop(lamp, "shadow_buffer_soft", text="Soft")
1039                sub.prop(lamp, "shadow_buffer_bias", text="Bias")
1040
1041                col = split.column()
1042                col.label(text="Sample Buffers:")
1043                col.prop(lamp, "shadow_sample_buffers", text="")
1044                sub = col.column(align=True)
1045                sub.prop(lamp, "shadow_buffer_size", text="Size")
1046                sub.prop(lamp, "shadow_buffer_samples", text="Samples")
1047                if lamp.shadow_buffer_type == 'DEEP':
1048                    col.prop(lamp, "compression_threshold")
1049
1050            elif lamp.shadow_buffer_type == 'IRREGULAR':
1051                layout.prop(lamp, "shadow_buffer_bias", text="Bias")
1052
1053            split = layout.split()
1054
1055            col = split.column()
1056            col.prop(lamp, "use_auto_clip_start", text="Autoclip Start")
1057            sub = col.column()
1058            sub.active = not lamp.use_auto_clip_start
1059            sub.prop(lamp, "shadow_buffer_clip_start", text="Clip Start")
1060
1061            col = split.column()
1062            col.prop(lamp, "use_auto_clip_end", text="Autoclip End")
1063            sub = col.column()
1064            sub.active = not lamp.use_auto_clip_end
1065            sub.prop(lamp, "shadow_buffer_clip_end", text=" Clip End")
1066'''
1067
1068
1069class LIGHT_PT_POV_area(PovLampButtonsPanel, Panel):
1070    bl_label = properties_data_light.DATA_PT_area.bl_label
1071
1072    @classmethod
1073    def poll(cls, context):
1074        lamp = context.light
1075        engine = context.scene.render.engine
1076        return (lamp and lamp.type == 'AREA') and (engine in cls.COMPAT_ENGINES)
1077
1078    draw = properties_data_light.DATA_PT_area.draw
1079
1080
1081class LIGHT_PT_POV_spot(PovLampButtonsPanel, Panel):
1082    bl_label = properties_data_light.DATA_PT_spot.bl_label
1083
1084    @classmethod
1085    def poll(cls, context):
1086        lamp = context.light
1087        engine = context.scene.render.engine
1088        return (lamp and lamp.type == 'SPOT') and (engine in cls.COMPAT_ENGINES)
1089
1090    draw = properties_data_light.DATA_PT_spot.draw
1091
1092
1093class LIGHT_PT_POV_falloff_curve(PovLampButtonsPanel, Panel):
1094    bl_label = properties_data_light.DATA_PT_falloff_curve.bl_label
1095    bl_options = properties_data_light.DATA_PT_falloff_curve.bl_options
1096
1097    @classmethod
1098    def poll(cls, context):
1099        lamp = context.light
1100        engine = context.scene.render.engine
1101
1102        return (
1103            lamp
1104            and lamp.type in {'POINT', 'SPOT'}
1105            and lamp.falloff_type == 'CUSTOM_CURVE'
1106        ) and (engine in cls.COMPAT_ENGINES)
1107
1108    draw = properties_data_light.DATA_PT_falloff_curve.draw
1109
1110
1111class OBJECT_PT_POV_rainbow(PovLampButtonsPanel, Panel):
1112    """Use this class to define buttons from the rainbow panel of
1113    properties window. inheriting lamp buttons panel class"""
1114
1115    bl_label = "POV-Ray Rainbow"
1116    COMPAT_ENGINES = {'POVRAY_RENDER'}
1117    # bl_options = {'HIDE_HEADER'}
1118    @classmethod
1119    def poll(cls, context):
1120        engine = context.scene.render.engine
1121        obj = context.object
1122        return (
1123            obj
1124            and obj.pov.object_as == 'RAINBOW'
1125            and (engine in cls.COMPAT_ENGINES)
1126        )
1127
1128    def draw(self, context):
1129        layout = self.layout
1130
1131        obj = context.object
1132
1133        col = layout.column()
1134
1135        if obj.pov.object_as == 'RAINBOW':
1136            if obj.pov.unlock_parameters == False:
1137                col.prop(
1138                    obj.pov,
1139                    "unlock_parameters",
1140                    text="Exported parameters below",
1141                    icon='LOCKED',
1142                )
1143                col.label(
1144                    text="Rainbow projection angle: " + str(obj.data.spot_size)
1145                )
1146                col.label(text="Rainbow width: " + str(obj.data.spot_blend))
1147                col.label(
1148                    text="Rainbow distance: "
1149                    + str(obj.data.shadow_buffer_clip_start)
1150                )
1151                col.label(text="Rainbow arc angle: " + str(obj.pov.arc_angle))
1152                col.label(
1153                    text="Rainbow falloff angle: " + str(obj.pov.falloff_angle)
1154                )
1155
1156            else:
1157                col.prop(
1158                    obj.pov,
1159                    "unlock_parameters",
1160                    text="Edit exported parameters",
1161                    icon='UNLOCKED',
1162                )
1163                col.label(text="3D view proxy may get out of synch")
1164                col.active = obj.pov.unlock_parameters
1165
1166                layout.operator(
1167                    "pov.cone_update", text="Update", icon="MESH_CONE"
1168                )
1169
1170                # col.label(text="Parameters:")
1171                col.prop(obj.data, "spot_size", text="Rainbow Projection Angle")
1172                col.prop(obj.data, "spot_blend", text="Rainbow width")
1173                col.prop(
1174                    obj.data,
1175                    "shadow_buffer_clip_start",
1176                    text="Visibility distance",
1177                )
1178                col.prop(obj.pov, "arc_angle")
1179                col.prop(obj.pov, "falloff_angle")
1180
1181
1182del properties_data_light
1183###############################################################################
1184
1185
1186class WORLD_PT_POV_world(WorldButtonsPanel, Panel):
1187    """Use this class to define pov world buttons."""
1188
1189    bl_label = "World"
1190    COMPAT_ENGINES = {'POVRAY_RENDER'}
1191
1192    def draw(self, context):
1193        layout = self.layout
1194
1195        world = context.world.pov
1196
1197        row = layout.row(align=True)
1198        row.menu(
1199            WORLD_MT_POV_presets.__name__, text=WORLD_MT_POV_presets.bl_label
1200        )
1201        row.operator(WORLD_OT_POV_add_preset.bl_idname, text="", icon='ADD')
1202        row.operator(
1203            WORLD_OT_POV_add_preset.bl_idname, text="", icon='REMOVE'
1204        ).remove_active = True
1205
1206        row = layout.row()
1207        row.prop(world, "use_sky_paper")
1208        row.prop(world, "use_sky_blend")
1209        row.prop(world, "use_sky_real")
1210
1211        row = layout.row()
1212        row.column().prop(world, "horizon_color")
1213        col = row.column()
1214        col.prop(world, "zenith_color")
1215        col.active = world.use_sky_blend
1216        row.column().prop(world, "ambient_color")
1217
1218        # row = layout.row()
1219        # row.prop(world, "exposure") #Re-implement later as a light multiplier
1220        # row.prop(world, "color_range")
1221
1222
1223class WORLD_PT_POV_mist(WorldButtonsPanel, Panel):
1224    """Use this class to define pov mist buttons."""
1225
1226    bl_label = "Mist"
1227    bl_options = {'DEFAULT_CLOSED'}
1228    COMPAT_ENGINES = {'POVRAY_RENDER'}
1229
1230    def draw_header(self, context):
1231        world = context.world
1232
1233        self.layout.prop(world.mist_settings, "use_mist", text="")
1234
1235    def draw(self, context):
1236        layout = self.layout
1237
1238        world = context.world
1239
1240        layout.active = world.mist_settings.use_mist
1241
1242        split = layout.split()
1243
1244        col = split.column()
1245        col.prop(world.mist_settings, "intensity")
1246        col.prop(world.mist_settings, "start")
1247
1248        col = split.column()
1249        col.prop(world.mist_settings, "depth")
1250        col.prop(world.mist_settings, "height")
1251
1252        layout.prop(world.mist_settings, "falloff")
1253
1254
1255class RENDER_PT_POV_export_settings(RenderButtonsPanel, Panel):
1256    """Use this class to define pov ini settingss buttons."""
1257    bl_options = {'DEFAULT_CLOSED'}
1258    bl_label = "Auto Start"
1259    COMPAT_ENGINES = {'POVRAY_RENDER'}
1260
1261    def draw_header(self, context):
1262        scene = context.scene
1263        if scene.pov.tempfiles_enable:
1264            self.layout.prop(
1265                scene.pov, "tempfiles_enable", text="", icon='AUTO'
1266            )
1267        else:
1268            self.layout.prop(
1269                scene.pov, "tempfiles_enable", text="", icon='CONSOLE'
1270            )
1271
1272    def draw(self, context):
1273
1274        layout = self.layout
1275
1276        scene = context.scene
1277
1278        layout.active = scene.pov.max_trace_level != 0
1279        split = layout.split()
1280
1281        col = split.column()
1282        col.label(text="Command line switches:")
1283        col.prop(scene.pov, "command_line_switches", text="")
1284        split = layout.split()
1285
1286        #layout.active = not scene.pov.tempfiles_enable
1287        if not scene.pov.tempfiles_enable:
1288            split.prop(scene.pov, "deletefiles_enable", text="Delete files")
1289            split.prop(scene.pov, "pov_editor", text="POV Editor")
1290
1291            col = layout.column()
1292            col.prop(scene.pov, "scene_name", text="Name")
1293            col.prop(scene.pov, "scene_path", text="Path to files")
1294            # col.prop(scene.pov, "scene_path", text="Path to POV-file")
1295            # col.prop(scene.pov, "renderimage_path", text="Path to image")
1296
1297            split = layout.split()
1298            split.prop(scene.pov, "indentation_character", text="Indent")
1299            if scene.pov.indentation_character == 'SPACE':
1300                split.prop(scene.pov, "indentation_spaces", text="Spaces")
1301
1302            row = layout.row()
1303            row.prop(scene.pov, "comments_enable", text="Comments")
1304            row.prop(scene.pov, "list_lf_enable", text="Line breaks in lists")
1305
1306
1307class RENDER_PT_POV_render_settings(RenderButtonsPanel, Panel):
1308    """Use this class to define pov render settings buttons."""
1309
1310    bl_label = "Global Settings"
1311    bl_icon = 'SETTINGS'
1312    bl_options = {'DEFAULT_CLOSED'}
1313    COMPAT_ENGINES = {'POVRAY_RENDER'}
1314
1315    def draw_header(self, context):
1316        scene = context.scene
1317        if scene.pov.global_settings_advanced:
1318            self.layout.prop(
1319                scene.pov, "global_settings_advanced", text="", icon='SETTINGS'
1320            )
1321        else:
1322            self.layout.prop(
1323                scene.pov,
1324                "global_settings_advanced",
1325                text="",
1326                icon='PREFERENCES',
1327            )
1328
1329    def draw(self, context):
1330        layout = self.layout
1331
1332        scene = context.scene
1333        rd = context.scene.render
1334        # layout.active = (scene.pov.max_trace_level != 0)
1335
1336        if sys.platform[:3] != "win":
1337            layout.prop(
1338                scene.pov, "sdl_window_enable", text="POV-Ray SDL Window"
1339            )
1340
1341        col = layout.column()
1342        col.label(text="Main Path Tracing:")
1343        col.prop(scene.pov, "max_trace_level", text="Ray Depth")
1344        align = True
1345        layout.active = scene.pov.global_settings_advanced
1346        # Deprecated (autodetected in pov3.8):
1347        # layout.prop(scene.pov, "charset")
1348        row = layout.row(align=align)
1349        row.prop(scene.pov, "adc_bailout")
1350        row = layout.row(align=align)
1351        row.prop(scene.pov, "ambient_light")
1352        row = layout.row(align=align)
1353        row.prop(scene.pov, "irid_wavelength")
1354        row = layout.row(align=align)
1355        row.prop(scene.pov, "max_intersections")
1356        row = layout.row(align=align)
1357        row.prop(scene.pov, "number_of_waves")
1358        row = layout.row(align=align)
1359        row.prop(scene.pov, "noise_generator")
1360
1361        split = layout.split()
1362        split.label(text="Shading:")
1363        split = layout.split()
1364
1365        row = split.row(align=align)
1366        row.prop(scene.pov, "use_shadows")
1367        row.prop(scene.pov, "alpha_mode")
1368
1369
1370class RENDER_PT_POV_photons(RenderButtonsPanel, Panel):
1371    """Use this class to define pov photons buttons."""
1372
1373    bl_label = "Photons"
1374    bl_options = {'DEFAULT_CLOSED'}
1375    COMPAT_ENGINES = {'POVRAY_RENDER'}
1376
1377    # def draw_header(self, context):
1378    # self.layout.label(icon='SETTINGS')
1379
1380    def draw_header(self, context):
1381        scene = context.scene
1382        if scene.pov.photon_enable:
1383            self.layout.prop(
1384                scene.pov, "photon_enable", text="", icon='PMARKER_ACT'
1385            )
1386        else:
1387            self.layout.prop(
1388                scene.pov, "photon_enable", text="", icon='PMARKER'
1389            )
1390
1391    def draw(self, context):
1392        scene = context.scene
1393        layout = self.layout
1394        layout.active = scene.pov.photon_enable
1395        col = layout.column()
1396        # col.label(text="Global Photons:")
1397        col.prop(scene.pov, "photon_max_trace_level", text="Photon Depth")
1398
1399        split = layout.split()
1400
1401        col = split.column()
1402        col.prop(scene.pov, "photon_spacing", text="Spacing")
1403        col.prop(scene.pov, "photon_gather_min")
1404
1405        col = split.column()
1406        col.prop(scene.pov, "photon_adc_bailout", text="Photon ADC")
1407        col.prop(scene.pov, "photon_gather_max")
1408
1409        box = layout.box()
1410        box.label(text='Photon Map File:')
1411        row = box.row()
1412        row.prop(scene.pov, "photon_map_file_save_load", expand=True)
1413        if scene.pov.photon_map_file_save_load in {'save'}:
1414            box.prop(scene.pov, "photon_map_dir")
1415            box.prop(scene.pov, "photon_map_filename")
1416        if scene.pov.photon_map_file_save_load in {'load'}:
1417            box.prop(scene.pov, "photon_map_file")
1418        # end main photons
1419
1420
1421class RENDER_PT_POV_antialias(RenderButtonsPanel, Panel):
1422    """Use this class to define pov antialiasing buttons."""
1423
1424    bl_label = "Anti-Aliasing"
1425    bl_options = {'DEFAULT_CLOSED'}
1426    COMPAT_ENGINES = {'POVRAY_RENDER'}
1427
1428    def draw_header(self, context):
1429        prefs = bpy.context.preferences.addons[__package__].preferences
1430        scene = context.scene
1431        if (
1432            prefs.branch_feature_set_povray != 'uberpov'
1433            and scene.pov.antialias_method == '2'
1434        ):
1435            self.layout.prop(
1436                scene.pov, "antialias_enable", text="", icon='ERROR'
1437            )
1438        elif scene.pov.antialias_enable:
1439            self.layout.prop(
1440                scene.pov, "antialias_enable", text="", icon='ANTIALIASED'
1441            )
1442        else:
1443            self.layout.prop(
1444                scene.pov, "antialias_enable", text="", icon='ALIASED'
1445            )
1446
1447    def draw(self, context):
1448        prefs = bpy.context.preferences.addons[__package__].preferences
1449        layout = self.layout
1450        scene = context.scene
1451
1452        layout.active = scene.pov.antialias_enable
1453
1454        row = layout.row()
1455        row.prop(scene.pov, "antialias_method", text="")
1456
1457        if (
1458            prefs.branch_feature_set_povray != 'uberpov'
1459            and scene.pov.antialias_method == '2'
1460        ):
1461            col = layout.column()
1462            col.alignment = 'CENTER'
1463            col.label(text="Stochastic Anti Aliasing is")
1464            col.label(text="Only Available with UberPOV")
1465            col.label(text="Feature Set in User Preferences.")
1466            col.label(text="Using Type 2 (recursive) instead")
1467        else:
1468            row.prop(scene.pov, "jitter_enable", text="Jitter")
1469
1470            split = layout.split()
1471            col = split.column()
1472            col.prop(scene.pov, "antialias_depth", text="AA Depth")
1473            sub = split.column()
1474            sub.prop(scene.pov, "jitter_amount", text="Jitter Amount")
1475            if scene.pov.jitter_enable:
1476                sub.enabled = True
1477            else:
1478                sub.enabled = False
1479
1480            row = layout.row()
1481            row.prop(scene.pov, "antialias_threshold", text="AA Threshold")
1482            row.prop(scene.pov, "antialias_gamma", text="AA Gamma")
1483
1484            if prefs.branch_feature_set_povray == 'uberpov':
1485                row = layout.row()
1486                row.prop(
1487                    scene.pov, "antialias_confidence", text="AA Confidence"
1488                )
1489                if scene.pov.antialias_method == '2':
1490                    row.enabled = True
1491                else:
1492                    row.enabled = False
1493
1494
1495class RENDER_PT_POV_radiosity(RenderButtonsPanel, Panel):
1496    """Use this class to define pov radiosity buttons."""
1497
1498    bl_label = "Diffuse Radiosity"
1499    bl_options = {'DEFAULT_CLOSED'}
1500    COMPAT_ENGINES = {'POVRAY_RENDER'}
1501
1502    def draw_header(self, context):
1503        scene = context.scene
1504        if scene.pov.radio_enable:
1505            self.layout.prop(
1506                scene.pov,
1507                "radio_enable",
1508                text="",
1509                icon='OUTLINER_OB_LIGHTPROBE',
1510            )
1511        else:
1512            self.layout.prop(
1513                scene.pov, "radio_enable", text="", icon='LIGHTPROBE_CUBEMAP'
1514            )
1515
1516    def draw(self, context):
1517        layout = self.layout
1518
1519        scene = context.scene
1520
1521        layout.active = scene.pov.radio_enable
1522
1523        split = layout.split()
1524
1525        col = split.column()
1526        col.prop(scene.pov, "radio_count", text="Rays")
1527        col.prop(scene.pov, "radio_recursion_limit", text="Recursions")
1528
1529        split.prop(scene.pov, "radio_error_bound", text="Error Bound")
1530
1531        layout.prop(scene.pov, "radio_display_advanced")
1532
1533        if scene.pov.radio_display_advanced:
1534            split = layout.split()
1535
1536            col = split.column()
1537            col.prop(scene.pov, "radio_adc_bailout", slider=True)
1538            col.prop(scene.pov, "radio_minimum_reuse", text="Min Reuse")
1539            col.prop(scene.pov, "radio_gray_threshold", slider=True)
1540            col.prop(scene.pov, "radio_pretrace_start", slider=True)
1541            col.prop(scene.pov, "radio_low_error_factor", slider=True)
1542
1543            col = split.column()
1544            col.prop(scene.pov, "radio_brightness")
1545            col.prop(scene.pov, "radio_maximum_reuse", text="Max Reuse")
1546            col.prop(scene.pov, "radio_nearest_count")
1547            col.prop(scene.pov, "radio_pretrace_end", slider=True)
1548
1549            col = layout.column()
1550            col.label(text="Estimation Influence:")
1551            col.prop(scene.pov, "radio_always_sample")
1552            col.prop(scene.pov, "radio_normal")
1553            col.prop(scene.pov, "radio_media")
1554            col.prop(scene.pov, "radio_subsurface")
1555
1556
1557class POV_RADIOSITY_MT_presets(Menu):
1558    """Use this class to define pov radiosity presets menu."""
1559
1560    bl_label = "Radiosity Presets"
1561    preset_subdir = "pov/radiosity"
1562    preset_operator = "script.execute_preset"
1563    draw = bpy.types.Menu.draw_preset
1564
1565
1566class RENDER_OT_POV_radiosity_add_preset(AddPresetBase, Operator):
1567    """Use this class to define pov radiosity add presets button."""
1568
1569    '''Add a Radiosity Preset'''
1570    bl_idname = "scene.radiosity_preset_add"
1571    bl_label = "Add Radiosity Preset"
1572    preset_menu = "POV_RADIOSITY_MT_presets"
1573
1574    # variable used for all preset values
1575    preset_defines = ["scene = bpy.context.scene"]
1576
1577    # properties to store in the preset
1578    preset_values = [
1579        "scene.pov.radio_display_advanced",
1580        "scene.pov.radio_adc_bailout",
1581        "scene.pov.radio_always_sample",
1582        "scene.pov.radio_brightness",
1583        "scene.pov.radio_count",
1584        "scene.pov.radio_error_bound",
1585        "scene.pov.radio_gray_threshold",
1586        "scene.pov.radio_low_error_factor",
1587        "scene.pov.radio_media",
1588        "scene.pov.radio_subsurface",
1589        "scene.pov.radio_minimum_reuse",
1590        "scene.pov.radio_maximum_reuse",
1591        "scene.pov.radio_nearest_count",
1592        "scene.pov.radio_normal",
1593        "scene.pov.radio_recursion_limit",
1594        "scene.pov.radio_pretrace_start",
1595        "scene.pov.radio_pretrace_end",
1596    ]
1597
1598    # where to store the preset
1599    preset_subdir = "pov/radiosity"
1600
1601
1602# Draw into an existing panel
1603def rad_panel_func(self, context):
1604    layout = self.layout
1605
1606    row = layout.row(align=True)
1607    row.menu(
1608        POV_RADIOSITY_MT_presets.__name__,
1609        text=POV_RADIOSITY_MT_presets.bl_label,
1610    )
1611    row.operator(
1612        RENDER_OT_POV_radiosity_add_preset.bl_idname, text="", icon='ADD'
1613    )
1614    row.operator(
1615        RENDER_OT_POV_radiosity_add_preset.bl_idname, text="", icon='REMOVE'
1616    ).remove_active = True
1617
1618
1619class RENDER_PT_POV_media(WorldButtonsPanel, Panel):
1620    """Use this class to define a pov global atmospheric media buttons."""
1621
1622    bl_label = "Atmosphere Media"
1623    COMPAT_ENGINES = {'POVRAY_RENDER'}
1624
1625    def draw_header(self, context):
1626        scene = context.scene
1627
1628        self.layout.prop(scene.pov, "media_enable", text="")
1629
1630    def draw(self, context):
1631        layout = self.layout
1632
1633        scene = context.scene
1634
1635        layout.active = scene.pov.media_enable
1636
1637        col = layout.column()
1638        col.prop(scene.pov, "media_scattering_type", text="")
1639        col = layout.column()
1640        col.prop(scene.pov, "media_samples", text="Samples")
1641        split = layout.split()
1642        col = split.column(align=True)
1643        col.label(text="Scattering:")
1644        col.prop(scene.pov, "media_diffusion_scale")
1645        col.prop(scene.pov, "media_diffusion_color", text="")
1646        col = split.column(align=True)
1647        col.label(text="Absorption:")
1648        col.prop(scene.pov, "media_absorption_scale")
1649        col.prop(scene.pov, "media_absorption_color", text="")
1650        if scene.pov.media_scattering_type == '5':
1651            col = layout.column()
1652            col.prop(scene.pov, "media_eccentricity", text="Eccentricity")
1653
1654
1655##class RENDER_PT_povray_baking(RenderButtonsPanel, Panel):
1656##    bl_label = "Baking"
1657##    COMPAT_ENGINES = {'POVRAY_RENDER'}
1658##
1659##    def draw_header(self, context):
1660##        scene = context.scene
1661##
1662##        self.layout.prop(scene.pov, "baking_enable", text="")
1663##
1664##    def draw(self, context):
1665##        layout = self.layout
1666##
1667##        scene = context.scene
1668##        rd = scene.render
1669##
1670##        layout.active = scene.pov.baking_enable
1671
1672
1673class MODIFIERS_PT_POV_modifiers(ModifierButtonsPanel, Panel):
1674    """Use this class to define pov modifier buttons. (For booleans)"""
1675
1676    bl_label = "POV-Ray"
1677    COMPAT_ENGINES = {'POVRAY_RENDER'}
1678
1679    # def draw_header(self, context):
1680    # scene = context.scene
1681    # self.layout.prop(scene.pov, "boolean_mod", text="")
1682
1683    def draw(self, context):
1684        scene = context.scene
1685        layout = self.layout
1686        ob = context.object
1687        mod = ob.modifiers
1688        col = layout.column()
1689        # Find Boolean Modifiers for displaying CSG option
1690        onceCSG = 0
1691        for mod in ob.modifiers:
1692            if onceCSG == 0:
1693                if mod:
1694                    if mod.type == 'BOOLEAN':
1695                        col.prop(ob.pov, "boolean_mod")
1696                        onceCSG = 1
1697
1698                    if ob.pov.boolean_mod == "POV":
1699                        split = layout.split()
1700                        col = layout.column()
1701                        # Inside Vector for CSG
1702                        col.prop(ob.pov, "inside_vector")
1703
1704
1705class MATERIAL_MT_POV_sss_presets(Menu):
1706    """Use this class to define pov sss preset menu."""
1707
1708    bl_label = "SSS Presets"
1709    preset_subdir = "pov/material/sss"
1710    preset_operator = "script.execute_preset"
1711    draw = bpy.types.Menu.draw_preset
1712
1713
1714class MATERIAL_OT_POV_sss_add_preset(AddPresetBase, Operator):
1715    """Add an SSS Preset"""
1716
1717    bl_idname = "material.sss_preset_add"
1718    bl_label = "Add SSS Preset"
1719    preset_menu = "MATERIAL_MT_POV_sss_presets"
1720
1721    # variable used for all preset values
1722    preset_defines = ["material = bpy.context.material"]
1723
1724    # properties to store in the preset
1725    preset_values = [
1726        "material.pov_subsurface_scattering.radius",
1727        "material.pov_subsurface_scattering.color",
1728    ]
1729
1730    # where to store the preset
1731    preset_subdir = "pov/material/sss"
1732
1733
1734class MATERIAL_PT_POV_sss(MaterialButtonsPanel, Panel):
1735    """Use this class to define pov sss buttons panel."""
1736
1737    bl_label = "Subsurface Scattering"
1738    bl_options = {'DEFAULT_CLOSED'}
1739    COMPAT_ENGINES = {'POVRAY_RENDER'}
1740
1741    @classmethod
1742    def poll(cls, context):
1743        mat = context.material
1744        engine = context.scene.render.engine
1745        return (
1746            check_material(mat)
1747            and (mat.pov.type in {'SURFACE', 'WIRE'})
1748            and (engine in cls.COMPAT_ENGINES)
1749        )
1750
1751    def draw_header(self, context):
1752        mat = context.material  # FORMERLY : #active_node_mat(context.material)
1753        sss = mat.pov_subsurface_scattering
1754
1755        self.layout.active = not mat.pov.use_shadeless
1756        self.layout.prop(sss, "use", text="")
1757
1758    def draw(self, context):
1759        layout = self.layout
1760
1761        mat = context.material  # FORMERLY : #active_node_mat(context.material)
1762        sss = mat.pov_subsurface_scattering
1763
1764        layout.active = (sss.use) and (not mat.pov.use_shadeless)
1765
1766        row = layout.row().split()
1767        sub = row.row(align=True).split(align=True, factor=0.75)
1768        sub.menu(
1769            MATERIAL_MT_POV_sss_presets.__name__,
1770            text=MATERIAL_MT_POV_sss_presets.bl_label,
1771        )
1772        sub.operator(
1773            MATERIAL_OT_POV_sss_add_preset.bl_idname, text="", icon='ADD'
1774        )
1775        sub.operator(
1776            MATERIAL_OT_POV_sss_add_preset.bl_idname, text="", icon='REMOVE'
1777        ).remove_active = True
1778
1779        split = layout.split()
1780
1781        col = split.column()
1782        col.prop(sss, "ior")
1783        col.prop(sss, "scale")
1784        col.prop(sss, "color", text="")
1785        col.prop(sss, "radius", text="RGB Radius", expand=True)
1786
1787        col = split.column()
1788        sub = col.column(align=True)
1789        sub.label(text="Blend:")
1790        sub.prop(sss, "color_factor", text="Color")
1791        sub.prop(sss, "texture_factor", text="Texture")
1792        sub.label(text="Scattering Weight:")
1793        sub.prop(sss, "front")
1794        sub.prop(sss, "back")
1795        col.separator()
1796        col.prop(sss, "error_threshold", text="Error")
1797
1798
1799class MATERIAL_PT_POV_activate_node(MaterialButtonsPanel, Panel):
1800    """Use this class to define an activate pov nodes button."""
1801
1802    bl_label = "Activate Node Settings"
1803    bl_context = "material"
1804    bl_options = {'HIDE_HEADER'}
1805    COMPAT_ENGINES = {'POVRAY_RENDER'}
1806
1807    @classmethod
1808    def poll(cls, context):
1809        engine = context.scene.render.engine
1810        mat = context.material
1811        ob = context.object
1812        return (
1813            mat
1814            and mat.pov.type == "SURFACE"
1815            and (engine in cls.COMPAT_ENGINES)
1816            and not (mat.pov.material_use_nodes or mat.use_nodes)
1817        )
1818
1819    def draw(self, context):
1820        layout = self.layout
1821        # layout.operator("pov.material_use_nodes", icon='SOUND')#'NODETREE')
1822        # the above replaced with a context hook below:
1823        layout.operator(
1824            "WM_OT_context_toggle", text="Use POV-Ray Nodes", icon='NODETREE'
1825        ).data_path = "material.pov.material_use_nodes"
1826
1827
1828class MATERIAL_PT_POV_active_node(MaterialButtonsPanel, Panel):
1829    """Use this class to show pov active node properties buttons."""
1830
1831    bl_label = "Active Node Settings"
1832    bl_context = "material"
1833    bl_options = {'HIDE_HEADER'}
1834    COMPAT_ENGINES = {'POVRAY_RENDER'}
1835
1836    @classmethod
1837    def poll(cls, context):
1838        engine = context.scene.render.engine
1839        mat = context.material
1840        ob = context.object
1841        return (
1842            mat
1843            and mat.pov.type == "SURFACE"
1844            and (engine in cls.COMPAT_ENGINES)
1845            and mat.pov.material_use_nodes
1846        )
1847
1848    def draw(self, context):
1849        layout = self.layout
1850        mat = context.material
1851        node_tree = mat.node_tree
1852        if node_tree:
1853            node = node_tree.nodes.active
1854            if mat.use_nodes:
1855                if node:
1856                    layout.prop(mat.pov, "material_active_node")
1857                    if node.bl_idname == "PovrayMaterialNode":
1858                        layout.context_pointer_set("node", node)
1859                        if hasattr(node, "draw_buttons_ext"):
1860                            node.draw_buttons_ext(context, layout)
1861                        elif hasattr(node, "draw_buttons"):
1862                            node.draw_buttons(context, layout)
1863                        value_inputs = [
1864                            socket
1865                            for socket in node.inputs
1866                            if socket.enabled and not socket.is_linked
1867                        ]
1868                        if value_inputs:
1869                            layout.separator()
1870                            layout.label(text="Inputs:")
1871                            for socket in value_inputs:
1872                                row = layout.row()
1873                                socket.draw(context, row, node, socket.name)
1874                    else:
1875                        layout.context_pointer_set("node", node)
1876                        if hasattr(node, "draw_buttons_ext"):
1877                            node.draw_buttons_ext(context, layout)
1878                        elif hasattr(node, "draw_buttons"):
1879                            node.draw_buttons(context, layout)
1880                        value_inputs = [
1881                            socket
1882                            for socket in node.inputs
1883                            if socket.enabled and not socket.is_linked
1884                        ]
1885                        if value_inputs:
1886                            layout.separator()
1887                            layout.label(text="Inputs:")
1888                            for socket in value_inputs:
1889                                row = layout.row()
1890                                socket.draw(context, row, node, socket.name)
1891                else:
1892                    layout.label(text="No active nodes!")
1893
1894class MATERIAL_PT_POV_specular(MaterialButtonsPanel, Panel):
1895    """Use this class to define standard material specularity (highlights) buttons."""
1896
1897    bl_label = "Specular"
1898    COMPAT_ENGINES = {'POVRAY_RENDER'}
1899
1900    @classmethod
1901    def poll(cls, context):
1902        mat = context.material
1903        engine = context.scene.render.engine
1904        return (
1905            check_material(mat)
1906            and (mat.pov.type in {'SURFACE', 'WIRE'})
1907            and (engine in cls.COMPAT_ENGINES)
1908        )
1909    def draw(self, context):
1910        layout = self.layout
1911
1912        mat = context.material.pov
1913
1914        layout.active = (not mat.use_shadeless)
1915
1916        split = layout.split()
1917
1918        col = split.column()
1919        col.prop(mat, "specular_color", text="")
1920        col.prop(mat, "specular_intensity", text="Intensity")
1921
1922        col = split.column()
1923        col.prop(mat, "specular_shader", text="")
1924        col.prop(mat, "use_specular_ramp", text="Ramp")
1925
1926        col = layout.column()
1927        if mat.specular_shader in {'COOKTORR', 'PHONG'}:
1928            col.prop(mat, "specular_hardness", text="Hardness")
1929        elif mat.specular_shader == 'BLINN':
1930            row = col.row()
1931            row.prop(mat, "specular_hardness", text="Hardness")
1932            row.prop(mat, "specular_ior", text="IOR")
1933        elif mat.specular_shader == 'WARDISO':
1934            col.prop(mat, "specular_slope", text="Slope")
1935        elif mat.specular_shader == 'TOON':
1936            row = col.row()
1937            row.prop(mat, "specular_toon_size", text="Size")
1938            row.prop(mat, "specular_toon_smooth", text="Smooth")
1939
1940        if mat.use_specular_ramp:
1941            layout.separator()
1942            layout.template_color_ramp(mat, "specular_ramp", expand=True)
1943            layout.separator()
1944
1945            row = layout.row()
1946            row.prop(mat, "specular_ramp_input", text="Input")
1947            row.prop(mat, "specular_ramp_blend", text="Blend")
1948
1949            layout.prop(mat, "specular_ramp_factor", text="Factor")
1950
1951class MATERIAL_PT_POV_mirror(MaterialButtonsPanel, Panel):
1952    """Use this class to define standard material reflectivity (mirror) buttons."""
1953
1954    bl_label = "Mirror"
1955    bl_options = {'DEFAULT_CLOSED'}
1956    bl_idname = "MATERIAL_PT_POV_raytrace_mirror"
1957    COMPAT_ENGINES = {'POVRAY_RENDER'}
1958
1959    @classmethod
1960    def poll(cls, context):
1961        mat = context.material
1962        engine = context.scene.render.engine
1963        return (
1964            check_material(mat)
1965            and (mat.pov.type in {'SURFACE', 'WIRE'})
1966            and (engine in cls.COMPAT_ENGINES)
1967        )
1968
1969    def draw_header(self, context):
1970        mat = context.material
1971        raym = mat.pov_raytrace_mirror
1972
1973        self.layout.prop(raym, "use", text="")
1974
1975    def draw(self, context):
1976        layout = self.layout
1977
1978        mat = (
1979            context.material
1980        )  # Formerly : #mat = active_node_mat(context.material)
1981        raym = mat.pov_raytrace_mirror
1982
1983        layout.active = raym.use
1984
1985        split = layout.split()
1986
1987        col = split.column()
1988        col.prop(raym, "reflect_factor")
1989        col.prop(raym, "mirror_color", text="")
1990
1991        col = split.column()
1992        col.prop(raym, "fresnel")
1993        sub = col.column()
1994        sub.active = raym.fresnel > 0.0
1995        sub.prop(raym, "fresnel_factor", text="Blend")
1996
1997        split = layout.split()
1998
1999        col = split.column()
2000        col.separator()
2001        col.prop(raym, "depth")
2002        col.prop(raym, "distance", text="Max Dist")
2003        col.separator()
2004        sub = col.split(factor=0.4)
2005        sub.active = raym.distance > 0.0
2006        sub.label(text="Fade To:")
2007        sub.prop(raym, "fade_to", text="")
2008
2009        col = split.column()
2010        col.label(text="Gloss:")
2011        col.prop(raym, "gloss_factor", text="Amount")
2012        sub = col.column()
2013        sub.active = raym.gloss_factor < 1.0
2014        sub.prop(raym, "gloss_threshold", text="Threshold")
2015        sub.prop(raym, "gloss_samples", text="Noise")
2016        sub.prop(raym, "gloss_anisotropic", text="Anisotropic")
2017
2018
2019class MATERIAL_PT_POV_transp(MaterialButtonsPanel, Panel):
2020    """Use this class to define pov material transparency (alpha) buttons."""
2021
2022    bl_label = "Transparency"
2023    COMPAT_ENGINES = {'POVRAY_RENDER'}
2024
2025    @classmethod
2026    def poll(cls, context):
2027        mat = context.material
2028        engine = context.scene.render.engine
2029        return (
2030            check_material(mat)
2031            and (mat.pov.type in {'SURFACE', 'WIRE'})
2032            and (engine in cls.COMPAT_ENGINES)
2033        )
2034
2035    def draw_header(self, context):
2036        mat = context.material
2037
2038        if simple_material(mat):
2039            self.layout.prop(mat.pov, "use_transparency", text="")
2040
2041    def draw(self, context):
2042        layout = self.layout
2043
2044        base_mat = context.material
2045        mat = context.material  # FORMERLY active_node_mat(context.material)
2046        rayt = mat.pov_raytrace_transparency
2047
2048        if simple_material(base_mat):
2049            row = layout.row()
2050            row.active = mat.pov.use_transparency
2051            row.prop(mat.pov, "transparency_method", expand=True)
2052
2053        split = layout.split()
2054        split.active = base_mat.pov.use_transparency
2055
2056        col = split.column()
2057        col.prop(mat.pov, "alpha")
2058        row = col.row()
2059        row.active = (base_mat.pov.transparency_method != 'MASK') and (
2060            not mat.pov.use_shadeless
2061        )
2062        row.prop(mat.pov, "specular_alpha", text="Specular")
2063
2064        col = split.column()
2065        col.active = not mat.pov.use_shadeless
2066        col.prop(rayt, "fresnel")
2067        sub = col.column()
2068        sub.active = rayt.fresnel > 0.0
2069        sub.prop(rayt, "fresnel_factor", text="Blend")
2070
2071        if base_mat.pov.transparency_method == 'RAYTRACE':
2072            layout.separator()
2073            split = layout.split()
2074            split.active = base_mat.pov.use_transparency
2075
2076            col = split.column()
2077            col.prop(rayt, "ior")
2078            col.prop(rayt, "filter")
2079            col.prop(rayt, "falloff")
2080            col.prop(rayt, "depth_max")
2081            col.prop(rayt, "depth")
2082
2083            col = split.column()
2084            col.label(text="Gloss:")
2085            col.prop(rayt, "gloss_factor", text="Amount")
2086            sub = col.column()
2087            sub.active = rayt.gloss_factor < 1.0
2088            sub.prop(rayt, "gloss_threshold", text="Threshold")
2089            sub.prop(rayt, "gloss_samples", text="Samples")
2090
2091
2092class MATERIAL_PT_POV_reflection(MaterialButtonsPanel, Panel):
2093    """Use this class to define more pov specific reflectivity buttons."""
2094
2095    bl_label = "POV-Ray Reflection"
2096    bl_parent_id = "MATERIAL_PT_POV_raytrace_mirror"
2097    COMPAT_ENGINES = {'POVRAY_RENDER'}
2098
2099    @classmethod
2100    def poll(cls, context):
2101        engine = context.scene.render.engine
2102        mat = context.material
2103        ob = context.object
2104        return (
2105            mat
2106            and mat.pov.type == "SURFACE"
2107            and (engine in cls.COMPAT_ENGINES)
2108            and not (mat.pov.material_use_nodes or mat.use_nodes)
2109        )
2110
2111    def draw(self, context):
2112        layout = self.layout
2113        mat = context.material
2114        col = layout.column()
2115        col.prop(mat.pov, "irid_enable")
2116        if mat.pov.irid_enable:
2117            col = layout.column()
2118            col.prop(mat.pov, "irid_amount", slider=True)
2119            col.prop(mat.pov, "irid_thickness", slider=True)
2120            col.prop(mat.pov, "irid_turbulence", slider=True)
2121        col.prop(mat.pov, "conserve_energy")
2122        col2 = col.split().column()
2123
2124        if not mat.pov_raytrace_mirror.use:
2125            col2.label(text="Please Check Mirror settings :")
2126        col2.active = mat.pov_raytrace_mirror.use
2127        col2.prop(mat.pov, "mirror_use_IOR")
2128        if mat.pov.mirror_use_IOR:
2129            col2.alignment = 'CENTER'
2130            col2.label(text="The current Raytrace ")
2131            col2.label(text="Transparency IOR is: " + str(mat.pov.ior))
2132        col2.prop(mat.pov, "mirror_metallic")
2133
2134
2135'''
2136#group some native Blender (SSS) and POV (Fade)settings under such a parent panel?
2137class MATERIAL_PT_POV_interior(MaterialButtonsPanel, Panel):
2138    bl_label = "POV-Ray Interior"
2139    bl_idname = "material.pov_interior"
2140    #bl_parent_id = "material.absorption"
2141    COMPAT_ENGINES = {'POVRAY_RENDER'}
2142    @classmethod
2143    def poll(cls, context):
2144        engine = context.scene.render.engine
2145        mat=context.material
2146        ob = context.object
2147        return mat and mat.pov.type == "SURFACE" and (engine in cls.COMPAT_ENGINES) and not (mat.pov.material_use_nodes or mat.use_nodes)
2148
2149
2150    def draw_header(self, context):
2151        mat = context.material
2152'''
2153
2154
2155class MATERIAL_PT_POV_fade_color(MaterialButtonsPanel, Panel):
2156    """Use this class to define pov fading (absorption) color buttons."""
2157
2158    bl_label = "POV-Ray Absorption"
2159    COMPAT_ENGINES = {'POVRAY_RENDER'}
2160    # bl_parent_id = "material.pov_interior"
2161
2162    @classmethod
2163    def poll(cls, context):
2164        engine = context.scene.render.engine
2165        mat = context.material
2166        ob = context.object
2167        return (
2168            mat
2169            and mat.pov.type == "SURFACE"
2170            and (engine in cls.COMPAT_ENGINES)
2171            and not (mat.pov.material_use_nodes or mat.use_nodes)
2172        )
2173
2174    def draw_header(self, context):
2175        mat = context.material
2176
2177        self.layout.prop(mat.pov, "interior_fade_color", text="")
2178
2179    def draw(self, context):
2180        layout = self.layout
2181        mat = context.material
2182        # layout.active = mat.pov.interior_fade_color
2183        if mat.pov.interior_fade_color != (0.0, 0.0, 0.0):
2184            layout.label(text="Raytrace transparency")
2185            layout.label(text="depth max Limit needs")
2186            layout.label(text="to be non zero to fade")
2187
2188        pass
2189
2190
2191class MATERIAL_PT_POV_caustics(MaterialButtonsPanel, Panel):
2192    """Use this class to define pov caustics buttons."""
2193
2194    bl_label = "Caustics"
2195    COMPAT_ENGINES = {'POVRAY_RENDER'}
2196
2197    @classmethod
2198    def poll(cls, context):
2199        engine = context.scene.render.engine
2200        mat = context.material
2201        ob = context.object
2202        return (
2203            mat
2204            and mat.pov.type == "SURFACE"
2205            and (engine in cls.COMPAT_ENGINES)
2206            and not (mat.pov.material_use_nodes or mat.use_nodes)
2207        )
2208
2209    def draw_header(self, context):
2210        mat = context.material
2211        if mat.pov.caustics_enable:
2212            self.layout.prop(
2213                mat.pov, "caustics_enable", text="", icon="PMARKER_SEL"
2214            )
2215        else:
2216            self.layout.prop(
2217                mat.pov, "caustics_enable", text="", icon="PMARKER"
2218            )
2219
2220    def draw(self, context):
2221
2222        layout = self.layout
2223
2224        mat = context.material
2225        layout.active = mat.pov.caustics_enable
2226        col = layout.column()
2227        if mat.pov.caustics_enable:
2228            col.prop(mat.pov, "refraction_caustics")
2229            if mat.pov.refraction_caustics:
2230
2231                col.prop(mat.pov, "refraction_type", text="")
2232
2233                if mat.pov.refraction_type == "1":
2234                    col.prop(mat.pov, "fake_caustics_power", slider=True)
2235                elif mat.pov.refraction_type == "2":
2236                    col.prop(mat.pov, "photons_dispersion", slider=True)
2237                    col.prop(mat.pov, "photons_dispersion_samples", slider=True)
2238            col.prop(mat.pov, "photons_reflection")
2239
2240            if (
2241                not mat.pov.refraction_caustics
2242                and not mat.pov.photons_reflection
2243            ):
2244                col = layout.column()
2245                col.alignment = 'CENTER'
2246                col.label(text="Caustics override is on, ")
2247                col.label(text="but you didn't chose any !")
2248
2249
2250class MATERIAL_PT_strand(MaterialButtonsPanel, Panel):
2251    """Use this class to define Blender strand antialiasing buttons."""
2252
2253    bl_label = "Strand"
2254    bl_options = {'DEFAULT_CLOSED'}
2255    COMPAT_ENGINES = {'POVRAY_RENDER'}
2256
2257    @classmethod
2258    def poll(cls, context):
2259        mat = context.material
2260        engine = context.scene.render.engine
2261        return (
2262            mat
2263            and (mat.pov.type in {'SURFACE', 'WIRE', 'HALO'})
2264            and (engine in cls.COMPAT_ENGINES)
2265        )
2266
2267    def draw(self, context):
2268        layout = self.layout
2269
2270        mat = context.material  # don't use node material
2271        tan = mat.strand
2272
2273        split = layout.split()
2274
2275        col = split.column()
2276        sub = col.column(align=True)
2277        sub.label(text="Size:")
2278        sub.prop(tan, "root_size", text="Root")
2279        sub.prop(tan, "tip_size", text="Tip")
2280        sub.prop(tan, "size_min", text="Minimum")
2281        sub.prop(tan, "use_blender_units")
2282        sub = col.column()
2283        sub.active = not mat.pov.use_shadeless
2284        sub.prop(tan, "use_tangent_shading")
2285        col.prop(tan, "shape")
2286
2287        col = split.column()
2288        col.label(text="Shading:")
2289        col.prop(tan, "width_fade")
2290        ob = context.object
2291        if ob and ob.type == 'MESH':
2292            col.prop_search(
2293                tan, "uv_layer", ob.data, "tessface_uv_textures", text=""
2294            )
2295        else:
2296            col.prop(tan, "uv_layer", text="")
2297        col.separator()
2298        sub = col.column()
2299        sub.active = not mat.pov.use_shadeless
2300        sub.label(text="Surface diffuse:")
2301        sub = col.column()
2302        sub.prop(tan, "blend_distance", text="Distance")
2303
2304
2305class MATERIAL_PT_POV_replacement_text(MaterialButtonsPanel, Panel):
2306    """Use this class to define pov custom code declared name field."""
2307
2308    bl_label = "Custom POV Code"
2309    COMPAT_ENGINES = {'POVRAY_RENDER'}
2310
2311    def draw(self, context):
2312        layout = self.layout
2313
2314        mat = context.material
2315
2316        col = layout.column()
2317        col.label(text="Replace properties with:")
2318        col.prop(mat.pov, "replacement_text", text="")
2319
2320
2321class TEXTURE_MT_POV_specials(Menu):
2322    """Use this class to define pov texture slot operations buttons."""
2323
2324    bl_label = "Texture Specials"
2325    COMPAT_ENGINES = {'POVRAY_RENDER'}
2326
2327    def draw(self, context):
2328        layout = self.layout
2329
2330        layout.operator("texture.slot_copy", icon='COPYDOWN')
2331        layout.operator("texture.slot_paste", icon='PASTEDOWN')
2332
2333
2334class WORLD_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
2335    """Use this class to show pov texture slots list."""  # XXX Not used yet
2336
2337    index: bpy.props.IntProperty(name='index')
2338    def draw_item(
2339        self, context, layout, data, item, icon, active_data, active_propname
2340    ):
2341        world = context.scene.world  # .pov
2342        active_data = world.pov
2343        # tex = context.texture #may be needed later?
2344
2345        # We could write some code to decide which icon to use here...
2346        custom_icon = 'TEXTURE'
2347
2348        ob = data
2349        slot = item
2350        # ma = slot.name
2351        # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
2352        if self.layout_type in {'DEFAULT', 'COMPACT'}:
2353            # You should always start your row layout by a label (icon + text), or a non-embossed text field,
2354            # this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
2355            # We use icon_value of label, as our given icon is an integer value, not an enum ID.
2356            # Note "data" names should never be translated!
2357            if slot:
2358                layout.prop(
2359                    item, "texture", text="", emboss=False, icon='TEXTURE'
2360                )
2361            else:
2362                layout.label(text="New", translate=False, icon_value=icon)
2363        # 'GRID' layout type should be as compact as possible (typically a single icon!).
2364        elif self.layout_type in {'GRID'}:
2365            layout.alignment = 'CENTER'
2366            layout.label(text="", icon_value=icon)
2367
2368
2369class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
2370    """Use this class to show pov texture slots list."""
2371
2372    #    texture_slots:
2373    index: bpy.props.IntProperty(name='index')
2374    # foo  = random prop
2375    def draw_item(
2376        self, context, layout, data, item, icon, active_data, active_propname
2377    ):
2378        ob = data
2379        slot = item
2380        # ma = slot.name
2381        # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
2382        if self.layout_type in {'DEFAULT', 'COMPACT'}:
2383            # You should always start your row layout by a label (icon + text), or a non-embossed text field,
2384            # this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
2385            # We use icon_value of label, as our given icon is an integer value, not an enum ID.
2386            # Note "data" names should never be translated!
2387            if slot:
2388                layout.prop(
2389                    item, "texture", text="", emboss=False, icon='TEXTURE'
2390                )
2391            else:
2392                layout.label(text="New", translate=False, icon_value=icon)
2393        # 'GRID' layout type should be as compact as possible (typically a single icon!).
2394        elif self.layout_type in {'GRID'}:
2395            layout.alignment = 'CENTER'
2396            layout.label(text="", icon_value=icon)
2397
2398# Rewrite an existing class to modify.
2399# register but not unregistered because
2400# the modified parts concern only POVRAY_RENDER
2401class TEXTURE_PT_context(TextureButtonsPanel, Panel):
2402    bl_label = ""
2403    bl_context = "texture"
2404    bl_options = {'HIDE_HEADER'}
2405    COMPAT_ENGINES = {'POVRAY_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
2406
2407    @classmethod
2408    def poll(cls, context):
2409        return (
2410            (context.scene.texture_context
2411            not in('MATERIAL','WORLD','LIGHT','PARTICLES','LINESTYLE')
2412            or context.scene.render.engine != 'POVRAY_RENDER')
2413        )
2414    def draw(self, context):
2415        layout = self.layout
2416        tex = context.texture
2417        space = context.space_data
2418        pin_id = space.pin_id
2419        use_pin_id = space.use_pin_id
2420        user = context.texture_user
2421
2422        col = layout.column()
2423
2424        if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
2425            pin_id = None
2426
2427        if not pin_id:
2428            col.template_texture_user()
2429
2430        if user or pin_id:
2431            col.separator()
2432
2433            if pin_id:
2434                col.template_ID(space, "pin_id")
2435            else:
2436                propname = context.texture_user_property.identifier
2437                col.template_ID(user, propname, new="texture.new")
2438
2439            if tex:
2440                col.separator()
2441
2442                split = col.split(factor=0.2)
2443                split.label(text="Type")
2444                split.prop(tex, "type", text="")
2445
2446class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
2447    """Use this class to show pov texture context buttons."""
2448
2449    bl_label = ""
2450    bl_options = {'HIDE_HEADER'}
2451    COMPAT_ENGINES = {'POVRAY_RENDER'}
2452
2453    @classmethod
2454    def poll(cls, context):
2455        engine = context.scene.render.engine
2456        return engine in cls.COMPAT_ENGINES
2457        # if not (hasattr(context, "pov_texture_slot") or hasattr(context, "texture_node")):
2458        #     return False
2459        return (
2460            context.material
2461            or context.scene.world
2462            or context.light
2463            or context.texture
2464            or context.line_style
2465            or context.particle_system
2466            or isinstance(context.space_data.pin_id, ParticleSettings)
2467            or context.texture_user
2468        ) and (engine in cls.COMPAT_ENGINES)
2469
2470    def draw(self, context):
2471        layout = self.layout
2472
2473        scene = context.scene
2474        mat = context.view_layer.objects.active.active_material
2475        wld = context.scene.world
2476
2477        layout.prop(scene, "texture_context", expand=True)
2478        if scene.texture_context == 'MATERIAL' and mat is not None:
2479
2480            row = layout.row()
2481            row.template_list(
2482                "MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist",
2483                "",
2484                mat,
2485                "pov_texture_slots",
2486                mat.pov,
2487                "active_texture_index",
2488                rows=2,
2489                maxrows=16,
2490                type="DEFAULT"
2491            )
2492            col = row.column(align=True)
2493            col.operator("pov.textureslotadd", icon='ADD', text='')
2494            col.operator("pov.textureslotremove", icon='REMOVE', text='')
2495            #todo: recreate for pov_texture_slots?
2496            #col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
2497            #col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
2498            col.separator()
2499
2500            if mat.pov_texture_slots:
2501                index = mat.pov.active_texture_index
2502                slot = mat.pov_texture_slots[index]
2503                povtex = slot.texture#slot.name
2504                tex = bpy.data.textures[povtex]
2505                col.prop(tex, 'use_fake_user', text='')
2506                #layout.label(text='Linked Texture data browser:')
2507                propname = slot.texture_search
2508                # if slot.texture was a pointer to texture data rather than just a name string:
2509                # layout.template_ID(povtex, "texture", new="texture.new")
2510
2511                layout.prop_search(
2512                    slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
2513                )
2514                try:
2515                    bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[slot.texture_search]
2516                    bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[slot.texture_search]
2517                except KeyError:
2518                    # texture not hand-linked by user
2519                    pass
2520
2521                if tex:
2522                    layout.separator()
2523                    split = layout.split(factor=0.2)
2524                    split.label(text="Type")
2525                    split.prop(tex, "type", text="")
2526
2527            # else:
2528            # for i in range(18):  # length of material texture slots
2529            # mat.pov_texture_slots.add()
2530        elif scene.texture_context == 'WORLD' and wld is not None:
2531
2532            row = layout.row()
2533            row.template_list(
2534                "WORLD_TEXTURE_SLOTS_UL_POV_layerlist",
2535                "",
2536                wld,
2537                "pov_texture_slots",
2538                wld.pov,
2539                "active_texture_index",
2540                rows=2,
2541                maxrows=16,
2542                type="DEFAULT"
2543            )
2544            col = row.column(align=True)
2545            col.operator("pov.textureslotadd", icon='ADD', text='')
2546            col.operator("pov.textureslotremove", icon='REMOVE', text='')
2547
2548            #todo: recreate for pov_texture_slots?
2549            #col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
2550            #col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
2551            col.separator()
2552
2553            if wld.pov_texture_slots:
2554                index = wld.pov.active_texture_index
2555                slot = wld.pov_texture_slots[index]
2556                povtex = slot.texture#slot.name
2557                tex = bpy.data.textures[povtex]
2558                col.prop(tex, 'use_fake_user', text='')
2559                #layout.label(text='Linked Texture data browser:')
2560                propname = slot.texture_search
2561                # if slot.texture was a pointer to texture data rather than just a name string:
2562                # layout.template_ID(povtex, "texture", new="texture.new")
2563
2564                layout.prop_search(
2565                    slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
2566                )
2567                try:
2568                    bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[slot.texture_search]
2569                    bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[slot.texture_search]
2570                except KeyError:
2571                    # texture not hand-linked by user
2572                    pass
2573
2574                if tex:
2575                    layout.separator()
2576                    split = layout.split(factor=0.2)
2577                    split.label(text="Type")
2578                    split.prop(tex, "type", text="")
2579
2580# Commented out below is a reminder of what existed in Blender Internal
2581# attributes need to be recreated
2582'''
2583        slot = getattr(context, "texture_slot", None)
2584        node = getattr(context, "texture_node", None)
2585        space = context.space_data
2586
2587        #attempt at replacing removed space_data
2588        mtl = getattr(context, "material", None)
2589        if mtl != None:
2590            spacedependant = mtl
2591        wld = getattr(context, "world", None)
2592        if wld != None:
2593            spacedependant = wld
2594        lgt = getattr(context, "light", None)
2595        if lgt != None:
2596            spacedependant = lgt
2597
2598
2599        #idblock = context.particle_system.settings
2600
2601        tex = getattr(context, "texture", None)
2602        if tex != None:
2603            spacedependant = tex
2604
2605
2606
2607        scene = context.scene
2608        idblock = scene.pov#pov_context_tex_datablock(context)
2609        pin_id = space.pin_id
2610
2611        #spacedependant.use_limited_texture_context = True
2612
2613        if space.use_pin_id and not isinstance(pin_id, Texture):
2614            idblock = id_tex_datablock(pin_id)
2615            pin_id = None
2616
2617        if not space.use_pin_id:
2618            layout.row().prop(spacedependant, "texture_context", expand=True)
2619            pin_id = None
2620
2621        if spacedependant.texture_context == 'OTHER':
2622            if not pin_id:
2623                layout.template_texture_user()
2624            user = context.texture_user
2625            if user or pin_id:
2626                layout.separator()
2627
2628                row = layout.row()
2629
2630                if pin_id:
2631                    row.template_ID(space, "pin_id")
2632                else:
2633                    propname = context.texture_user_property.identifier
2634                    row.template_ID(user, propname, new="texture.new")
2635
2636                if tex:
2637                    split = layout.split(factor=0.2)
2638                    if tex.use_nodes:
2639                        if slot:
2640                            split.label(text="Output:")
2641                            split.prop(slot, "output_node", text="")
2642                    else:
2643                        split.label(text="Type:")
2644                        split.prop(tex, "type", text="")
2645            return
2646
2647        tex_collection = (pin_id is None) and (node is None) and (spacedependant.texture_context not in ('LINESTYLE','OTHER'))
2648
2649        if tex_collection:
2650
2651            pov = getattr(context, "pov", None)
2652            active_texture_index = getattr(spacedependant, "active_texture_index", None)
2653            print (pov)
2654            print(idblock)
2655            print(active_texture_index)
2656            row = layout.row()
2657
2658            row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots",
2659                              idblock, "active_texture_index", rows=2, maxrows=16, type="DEFAULT")
2660
2661            # row.template_list("WORLD_TEXTURE_SLOTS_UL_List", "texture_slots", world,
2662                              # world.texture_slots, world, "active_texture_index", rows=2)
2663
2664            col = row.column(align=True)
2665            col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
2666            col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
2667            col.menu("TEXTURE_MT_POV_specials", icon='DOWNARROW_HLT', text="")
2668
2669        if tex_collection:
2670            layout.template_ID(idblock, "active_texture", new="texture.new")
2671        elif node:
2672            layout.template_ID(node, "texture", new="texture.new")
2673        elif idblock:
2674            layout.template_ID(idblock, "texture", new="texture.new")
2675
2676        if pin_id:
2677            layout.template_ID(space, "pin_id")
2678
2679        if tex:
2680            split = layout.split(factor=0.2)
2681            if tex.use_nodes:
2682                if slot:
2683                    split.label(text="Output:")
2684                    split.prop(slot, "output_node", text="")
2685            else:
2686                split.label(text="Type:")
2687'''
2688
2689
2690class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
2691    """Use this class to show pov color ramps."""
2692
2693    bl_label = "Colors"
2694    bl_options = {'DEFAULT_CLOSED'}
2695    COMPAT_ENGINES = {'POVRAY_RENDER'}
2696
2697    def draw(self, context):
2698        layout = self.layout
2699
2700        tex = context.texture
2701
2702        layout.prop(tex, "use_color_ramp", text="Ramp")
2703        if tex.use_color_ramp:
2704            layout.template_color_ramp(tex, "color_ramp", expand=True)
2705
2706        split = layout.split()
2707
2708        col = split.column()
2709        col.label(text="RGB Multiply:")
2710        sub = col.column(align=True)
2711        sub.prop(tex, "factor_red", text="R")
2712        sub.prop(tex, "factor_green", text="G")
2713        sub.prop(tex, "factor_blue", text="B")
2714
2715        col = split.column()
2716        col.label(text="Adjust:")
2717        col.prop(tex, "intensity")
2718        col.prop(tex, "contrast")
2719        col.prop(tex, "saturation")
2720
2721        col = layout.column()
2722        col.prop(tex, "use_clamp", text="Clamp")
2723
2724
2725# Texture Slot Panels #
2726
2727
2728class TEXTURE_OT_POV_texture_slot_add(Operator):
2729    """Use this class for the add texture slot button."""
2730
2731    bl_idname = "pov.textureslotadd"
2732    bl_label = "Add"
2733    bl_description = "Add texture_slot"
2734    bl_options = {'REGISTER', 'UNDO'}
2735    COMPAT_ENGINES = {'POVRAY_RENDER'}
2736
2737    def execute(self, context):
2738        idblock = pov_context_tex_datablock(context)
2739        tex = bpy.data.textures.new(name='Texture', type='IMAGE')
2740        #tex.use_fake_user = True
2741        #mat = context.view_layer.objects.active.active_material
2742        slot = idblock.pov_texture_slots.add()
2743        slot.name = tex.name
2744        slot.texture = tex.name
2745        slot.texture_search = tex.name
2746        # Switch paint brush and paint brush mask
2747        # to this texture so settings remain contextual
2748        bpy.context.tool_settings.image_paint.brush.texture = tex
2749        bpy.context.tool_settings.image_paint.brush.mask_texture = tex
2750        idblock.pov.active_texture_index = (len(idblock.pov_texture_slots)-1)
2751
2752        #for area in bpy.context.screen.areas:
2753            #if area.type in ['PROPERTIES']:
2754                #area.tag_redraw()
2755
2756
2757        return {'FINISHED'}
2758
2759
2760class TEXTURE_OT_POV_texture_slot_remove(Operator):
2761    """Use this class for the remove texture slot button."""
2762
2763    bl_idname = "pov.textureslotremove"
2764    bl_label = "Remove"
2765    bl_description = "Remove texture_slot"
2766    bl_options = {'REGISTER', 'UNDO'}
2767    COMPAT_ENGINES = {'POVRAY_RENDER'}
2768
2769    def execute(self, context):
2770        idblock = pov_context_tex_datablock(context)
2771        #mat = context.view_layer.objects.active.active_material
2772        tex_slot = idblock.pov_texture_slots.remove(idblock.pov.active_texture_index)
2773        if idblock.pov.active_texture_index > 0:
2774            idblock.pov.active_texture_index -= 1
2775        try:
2776            tex = idblock.pov_texture_slots[idblock.pov.active_texture_index].texture
2777        except IndexError:
2778            # No more slots
2779            return {'FINISHED'}
2780        # Switch paint brush to previous texture so settings remain contextual
2781        # if 'tex' in locals(): # Would test is the tex variable is assigned / exists
2782        bpy.context.tool_settings.image_paint.brush.texture = bpy.data.textures[tex]
2783        bpy.context.tool_settings.image_paint.brush.mask_texture = bpy.data.textures[tex]
2784
2785        return {'FINISHED'}
2786
2787class TextureSlotPanel(TextureButtonsPanel):
2788    """Use this class to show pov texture slots panel."""
2789
2790    COMPAT_ENGINES = {'POVRAY_RENDER'}
2791
2792    @classmethod
2793    def poll(cls, context):
2794        if not hasattr(context, "pov_texture_slot"):
2795            return False
2796
2797        engine = context.scene.render.engine
2798        return TextureButtonsPanel.poll(cls, context) and (
2799            engine in cls.COMPAT_ENGINES
2800        )
2801
2802
2803class TEXTURE_PT_POV_type(TextureButtonsPanel, Panel):
2804    """Use this class to define pov texture type buttons."""
2805
2806    bl_label = "POV Textures"
2807    COMPAT_ENGINES = {'POVRAY_RENDER'}
2808    bl_options = {'HIDE_HEADER'}
2809
2810    def draw(self, context):
2811        layout = self.layout
2812        world = context.world
2813        tex = context.texture
2814
2815        split = layout.split(factor=0.2)
2816        split.label(text="Pattern")
2817        split.prop(tex.pov, "tex_pattern_type", text="")
2818
2819        # row = layout.row()
2820        # row.template_list("WORLD_TEXTURE_SLOTS_UL_List", "texture_slots", world,
2821        # world.texture_slots, world, "active_texture_index")
2822
2823
2824class TEXTURE_PT_POV_preview(TextureButtonsPanel, Panel):
2825    """Use this class to define pov texture preview panel."""
2826
2827    bl_label = "Preview"
2828    COMPAT_ENGINES = {'POVRAY_RENDER'}
2829    bl_options = {'HIDE_HEADER'}
2830
2831    @classmethod
2832    def poll(cls, context):
2833        engine = context.scene.render.engine
2834        if not hasattr(context, "pov_texture_slot"):
2835            return False
2836        tex = context.texture
2837        mat = bpy.context.active_object.active_material
2838        return (
2839            tex
2840            and (tex.pov.tex_pattern_type != 'emulator')
2841            and (engine in cls.COMPAT_ENGINES)
2842        )
2843
2844    def draw(self, context):
2845        tex = context.texture
2846        slot = getattr(context, "pov_texture_slot", None)
2847        idblock = pov_context_tex_datablock(context)
2848        layout = self.layout
2849        # if idblock:
2850        # layout.template_preview(tex, parent=idblock, slot=slot)
2851        if tex.pov.tex_pattern_type != 'emulator':
2852            layout.operator("tex.preview_update")
2853        else:
2854            layout.template_preview(tex, slot=slot)
2855
2856
2857class TEXTURE_PT_POV_parameters(TextureButtonsPanel, Panel):
2858    """Use this class to define pov texture pattern buttons."""
2859
2860    bl_label = "POV Pattern Options"
2861    bl_options = {'HIDE_HEADER'}
2862    COMPAT_ENGINES = {'POVRAY_RENDER'}
2863
2864    def draw(self, context):
2865        mat = bpy.context.active_object.active_material
2866        layout = self.layout
2867        tex = context.texture
2868        align = True
2869        if tex is not None and tex.pov.tex_pattern_type != 'emulator':
2870            if tex.pov.tex_pattern_type == 'agate':
2871                layout.prop(
2872                    tex.pov, "modifier_turbulence", text="Agate Turbulence"
2873                )
2874            if tex.pov.tex_pattern_type in {'spiral1', 'spiral2'}:
2875                layout.prop(tex.pov, "modifier_numbers", text="Number of arms")
2876            if tex.pov.tex_pattern_type == 'tiling':
2877                layout.prop(tex.pov, "modifier_numbers", text="Pattern number")
2878            if tex.pov.tex_pattern_type == 'magnet':
2879                layout.prop(tex.pov, "magnet_style", text="Magnet style")
2880            if tex.pov.tex_pattern_type == 'quilted':
2881                row = layout.row(align=align)
2882                row.prop(tex.pov, "modifier_control0", text="Control0")
2883                row.prop(tex.pov, "modifier_control1", text="Control1")
2884            if tex.pov.tex_pattern_type == 'brick':
2885                col = layout.column(align=align)
2886                row = col.row()
2887                row.prop(tex.pov, "brick_size_x", text="Brick size X")
2888                row.prop(tex.pov, "brick_size_y", text="Brick size Y")
2889                row = col.row()
2890                row.prop(tex.pov, "brick_size_z", text="Brick size Z")
2891                row.prop(tex.pov, "brick_mortar", text="Brick mortar")
2892            if tex.pov.tex_pattern_type in {'julia', 'mandel', 'magnet'}:
2893                col = layout.column(align=align)
2894                if tex.pov.tex_pattern_type == 'julia':
2895                    row = col.row()
2896                    row.prop(tex.pov, "julia_complex_1", text="Complex 1")
2897                    row.prop(tex.pov, "julia_complex_2", text="Complex 2")
2898                if (
2899                    tex.pov.tex_pattern_type == 'magnet'
2900                    and tex.pov.magnet_style == 'julia'
2901                ):
2902                    row = col.row()
2903                    row.prop(tex.pov, "julia_complex_1", text="Complex 1")
2904                    row.prop(tex.pov, "julia_complex_2", text="Complex 2")
2905                row = col.row()
2906                if tex.pov.tex_pattern_type in {'julia', 'mandel'}:
2907                    row.prop(tex.pov, "f_exponent", text="Exponent")
2908                if tex.pov.tex_pattern_type == 'magnet':
2909                    row.prop(tex.pov, "magnet_type", text="Type")
2910                row.prop(tex.pov, "f_iter", text="Iterations")
2911                row = col.row()
2912                row.prop(tex.pov, "f_ior", text="Interior")
2913                row.prop(tex.pov, "f_ior_fac", text="Factor I")
2914                row = col.row()
2915                row.prop(tex.pov, "f_eor", text="Exterior")
2916                row.prop(tex.pov, "f_eor_fac", text="Factor E")
2917            if tex.pov.tex_pattern_type == 'gradient':
2918                layout.label(text="Gradient orientation:")
2919                column_flow = layout.column_flow(columns=3, align=True)
2920                column_flow.prop(tex.pov, "grad_orient_x", text="X")
2921                column_flow.prop(tex.pov, "grad_orient_y", text="Y")
2922                column_flow.prop(tex.pov, "grad_orient_z", text="Z")
2923            if tex.pov.tex_pattern_type == 'pavement':
2924                layout.prop(
2925                    tex.pov, "pave_sides", text="Pavement:number of sides"
2926                )
2927                col = layout.column(align=align)
2928                column_flow = col.column_flow(columns=3, align=True)
2929                column_flow.prop(tex.pov, "pave_tiles", text="Tiles")
2930                if tex.pov.pave_sides == '4' and tex.pov.pave_tiles == 6:
2931                    column_flow.prop(tex.pov, "pave_pat_35", text="Pattern")
2932                if tex.pov.pave_sides == '6' and tex.pov.pave_tiles == 5:
2933                    column_flow.prop(tex.pov, "pave_pat_22", text="Pattern")
2934                if tex.pov.pave_sides == '4' and tex.pov.pave_tiles == 5:
2935                    column_flow.prop(tex.pov, "pave_pat_12", text="Pattern")
2936                if tex.pov.pave_sides == '3' and tex.pov.pave_tiles == 6:
2937                    column_flow.prop(tex.pov, "pave_pat_12", text="Pattern")
2938                if tex.pov.pave_sides == '6' and tex.pov.pave_tiles == 4:
2939                    column_flow.prop(tex.pov, "pave_pat_7", text="Pattern")
2940                if tex.pov.pave_sides == '4' and tex.pov.pave_tiles == 4:
2941                    column_flow.prop(tex.pov, "pave_pat_5", text="Pattern")
2942                if tex.pov.pave_sides == '3' and tex.pov.pave_tiles == 5:
2943                    column_flow.prop(tex.pov, "pave_pat_4", text="Pattern")
2944                if tex.pov.pave_sides == '6' and tex.pov.pave_tiles == 3:
2945                    column_flow.prop(tex.pov, "pave_pat_3", text="Pattern")
2946                if tex.pov.pave_sides == '3' and tex.pov.pave_tiles == 4:
2947                    column_flow.prop(tex.pov, "pave_pat_3", text="Pattern")
2948                if tex.pov.pave_sides == '4' and tex.pov.pave_tiles == 3:
2949                    column_flow.prop(tex.pov, "pave_pat_2", text="Pattern")
2950                if tex.pov.pave_sides == '6' and tex.pov.pave_tiles == 6:
2951                    column_flow.label(text="!!! 5 tiles!")
2952                column_flow.prop(tex.pov, "pave_form", text="Form")
2953            if tex.pov.tex_pattern_type == 'function':
2954                layout.prop(tex.pov, "func_list", text="Functions")
2955            if (
2956                tex.pov.tex_pattern_type == 'function'
2957                and tex.pov.func_list != "NONE"
2958            ):
2959                func = None
2960                if tex.pov.func_list in {"f_noise3d", "f_ph", "f_r", "f_th"}:
2961                    func = 0
2962                if tex.pov.func_list in {
2963                    "f_comma",
2964                    "f_crossed_trough",
2965                    "f_cubic_saddle",
2966                    "f_cushion",
2967                    "f_devils_curve",
2968                    "f_enneper",
2969                    "f_glob",
2970                    "f_heart",
2971                    "f_hex_x",
2972                    "f_hex_y",
2973                    "f_hunt_surface",
2974                    "f_klein_bottle",
2975                    "f_kummer_surface_v1",
2976                    "f_lemniscate_of_gerono",
2977                    "f_mitre",
2978                    "f_nodal_cubic",
2979                    "f_noise_generator",
2980                    "f_odd",
2981                    "f_paraboloid",
2982                    "f_pillow",
2983                    "f_piriform",
2984                    "f_quantum",
2985                    "f_quartic_paraboloid",
2986                    "f_quartic_saddle",
2987                    "f_sphere",
2988                    "f_steiners_roman",
2989                    "f_torus_gumdrop",
2990                    "f_umbrella",
2991                }:
2992                    func = 1
2993                if tex.pov.func_list in {
2994                    "f_bicorn",
2995                    "f_bifolia",
2996                    "f_boy_surface",
2997                    "f_superellipsoid",
2998                    "f_torus",
2999                }:
3000                    func = 2
3001                if tex.pov.func_list in {
3002                    "f_ellipsoid",
3003                    "f_folium_surface",
3004                    "f_hyperbolic_torus",
3005                    "f_kampyle_of_eudoxus",
3006                    "f_parabolic_torus",
3007                    "f_quartic_cylinder",
3008                    "f_torus2",
3009                }:
3010                    func = 3
3011                if tex.pov.func_list in {
3012                    "f_blob2",
3013                    "f_cross_ellipsoids",
3014                    "f_flange_cover",
3015                    "f_isect_ellipsoids",
3016                    "f_kummer_surface_v2",
3017                    "f_ovals_of_cassini",
3018                    "f_rounded_box",
3019                    "f_spikes_2d",
3020                    "f_strophoid",
3021                }:
3022                    func = 4
3023                if tex.pov.func_list in {
3024                    "f_algbr_cyl1",
3025                    "f_algbr_cyl2",
3026                    "f_algbr_cyl3",
3027                    "f_algbr_cyl4",
3028                    "f_blob",
3029                    "f_mesh1",
3030                    "f_poly4",
3031                    "f_spikes",
3032                }:
3033                    func = 5
3034                if tex.pov.func_list in {
3035                    "f_devils_curve_2d",
3036                    "f_dupin_cyclid",
3037                    "f_folium_surface_2d",
3038                    "f_hetero_mf",
3039                    "f_kampyle_of_eudoxus_2d",
3040                    "f_lemniscate_of_gerono_2d",
3041                    "f_polytubes",
3042                    "f_ridge",
3043                    "f_ridged_mf",
3044                    "f_spiral",
3045                    "f_witch_of_agnesi",
3046                }:
3047                    func = 6
3048                if tex.pov.func_list in {
3049                    "f_helix1",
3050                    "f_helix2",
3051                    "f_piriform_2d",
3052                    "f_strophoid_2d",
3053                }:
3054                    func = 7
3055                if tex.pov.func_list == "f_helical_torus":
3056                    func = 8
3057                column_flow = layout.column_flow(columns=3, align=True)
3058                column_flow.label(text="X")
3059                column_flow.prop(tex.pov, "func_plus_x", text="")
3060                column_flow.prop(tex.pov, "func_x", text="Value")
3061                column_flow = layout.column_flow(columns=3, align=True)
3062                column_flow.label(text="Y")
3063                column_flow.prop(tex.pov, "func_plus_y", text="")
3064                column_flow.prop(tex.pov, "func_y", text="Value")
3065                column_flow = layout.column_flow(columns=3, align=True)
3066                column_flow.label(text="Z")
3067                column_flow.prop(tex.pov, "func_plus_z", text="")
3068                column_flow.prop(tex.pov, "func_z", text="Value")
3069                row = layout.row(align=align)
3070                if func > 0:
3071                    row.prop(tex.pov, "func_P0", text="P0")
3072                if func > 1:
3073                    row.prop(tex.pov, "func_P1", text="P1")
3074                row = layout.row(align=align)
3075                if func > 2:
3076                    row.prop(tex.pov, "func_P2", text="P2")
3077                if func > 3:
3078                    row.prop(tex.pov, "func_P3", text="P3")
3079                row = layout.row(align=align)
3080                if func > 4:
3081                    row.prop(tex.pov, "func_P4", text="P4")
3082                if func > 5:
3083                    row.prop(tex.pov, "func_P5", text="P5")
3084                row = layout.row(align=align)
3085                if func > 6:
3086                    row.prop(tex.pov, "func_P6", text="P6")
3087                if func > 7:
3088                    row.prop(tex.pov, "func_P7", text="P7")
3089                    row = layout.row(align=align)
3090                    row.prop(tex.pov, "func_P8", text="P8")
3091                    row.prop(tex.pov, "func_P9", text="P9")
3092            ###################################################End Patterns############################
3093
3094            layout.prop(tex.pov, "warp_types", text="Warp types")  # warp
3095            if tex.pov.warp_types == "TOROIDAL":
3096                layout.prop(
3097                    tex.pov, "warp_tor_major_radius", text="Major radius"
3098                )
3099            if tex.pov.warp_types not in {"CUBIC", "NONE"}:
3100                layout.prop(
3101                    tex.pov, "warp_orientation", text="Warp orientation"
3102                )
3103            col = layout.column(align=align)
3104            row = col.row()
3105            row.prop(tex.pov, "warp_dist_exp", text="Distance exponent")
3106            row = col.row()
3107            row.prop(tex.pov, "modifier_frequency", text="Frequency")
3108            row.prop(tex.pov, "modifier_phase", text="Phase")
3109
3110            row = layout.row()
3111
3112            row.label(text="Offset:")
3113            row.label(text="Scale:")
3114            row.label(text="Rotate:")
3115            col = layout.column(align=align)
3116            row = col.row()
3117            row.prop(tex.pov, "tex_mov_x", text="X")
3118            row.prop(tex.pov, "tex_scale_x", text="X")
3119            row.prop(tex.pov, "tex_rot_x", text="X")
3120            row = col.row()
3121            row.prop(tex.pov, "tex_mov_y", text="Y")
3122            row.prop(tex.pov, "tex_scale_y", text="Y")
3123            row.prop(tex.pov, "tex_rot_y", text="Y")
3124            row = col.row()
3125            row.prop(tex.pov, "tex_mov_z", text="Z")
3126            row.prop(tex.pov, "tex_scale_z", text="Z")
3127            row.prop(tex.pov, "tex_rot_z", text="Z")
3128            row = layout.row()
3129
3130            row.label(text="Turbulence:")
3131            col = layout.column(align=align)
3132            row = col.row()
3133            row.prop(tex.pov, "warp_turbulence_x", text="X")
3134            row.prop(tex.pov, "modifier_octaves", text="Octaves")
3135            row = col.row()
3136            row.prop(tex.pov, "warp_turbulence_y", text="Y")
3137            row.prop(tex.pov, "modifier_lambda", text="Lambda")
3138            row = col.row()
3139            row.prop(tex.pov, "warp_turbulence_z", text="Z")
3140            row.prop(tex.pov, "modifier_omega", text="Omega")
3141
3142class TEXTURE_PT_POV_mapping(TextureSlotPanel, Panel):
3143    """Use this class to define POV texture mapping buttons"""
3144    bl_label = "Mapping"
3145    COMPAT_ENGINES = {'POVRAY_RENDER'}
3146    bl_space_type = 'PROPERTIES'
3147    bl_region_type = 'WINDOW'
3148
3149    @classmethod
3150    def poll(cls, context):
3151        idblock = pov_context_tex_datablock(context)
3152        if isinstance(idblock, Brush) and not context.sculpt_object:
3153            return False
3154
3155        if not getattr(context, "texture_slot", None):
3156            return False
3157
3158        engine = context.scene.render.engine
3159        return (engine in cls.COMPAT_ENGINES)
3160
3161    def draw(self, context):
3162        layout = self.layout
3163
3164        idblock = pov_context_tex_datablock(context)
3165
3166        #tex = context.texture_slot
3167        tex = mat.pov_texture_slots[
3168            mat.active_texture_index
3169        ]
3170        if not isinstance(idblock, Brush):
3171            split = layout.split(percentage=0.3)
3172            col = split.column()
3173            col.label(text="Coordinates:")
3174            col = split.column()
3175            col.prop(tex, "texture_coords", text="")
3176
3177            if tex.texture_coords == 'ORCO':
3178                """
3179                ob = context.object
3180                if ob and ob.type == 'MESH':
3181                    split = layout.split(percentage=0.3)
3182                    split.label(text="Mesh:")
3183                    split.prop(ob.data, "texco_mesh", text="")
3184                """
3185            elif tex.texture_coords == 'UV':
3186                split = layout.split(percentage=0.3)
3187                split.label(text="Map:")
3188                ob = context.object
3189                if ob and ob.type == 'MESH':
3190                    split.prop_search(tex, "uv_layer", ob.data, "uv_textures", text="")
3191                else:
3192                    split.prop(tex, "uv_layer", text="")
3193
3194            elif tex.texture_coords == 'OBJECT':
3195                split = layout.split(percentage=0.3)
3196                split.label(text="Object:")
3197                split.prop(tex, "object", text="")
3198
3199            elif tex.texture_coords == 'ALONG_STROKE':
3200                split = layout.split(percentage=0.3)
3201                split.label(text="Use Tips:")
3202                split.prop(tex, "use_tips", text="")
3203
3204        if isinstance(idblock, Brush):
3205            if context.sculpt_object or context.image_paint_object:
3206                brush_texture_settings(layout, idblock, context.sculpt_object)
3207        else:
3208            if isinstance(idblock, FreestyleLineStyle):
3209                split = layout.split(percentage=0.3)
3210                split.label(text="Projection:")
3211                split.prop(tex, "mapping", text="")
3212
3213                split = layout.split(percentage=0.3)
3214                split.separator()
3215                row = split.row()
3216                row.prop(tex, "mapping_x", text="")
3217                row.prop(tex, "mapping_y", text="")
3218                row.prop(tex, "mapping_z", text="")
3219
3220            elif isinstance(idblock, Material):
3221                split = layout.split(percentage=0.3)
3222                split.label(text="Projection:")
3223                split.prop(tex, "mapping", text="")
3224
3225                split = layout.split()
3226
3227                col = split.column()
3228                if tex.texture_coords in {'ORCO', 'UV'}:
3229                    col.prop(tex, "use_from_dupli")
3230                    if (idblock.type == 'VOLUME' and tex.texture_coords == 'ORCO'):
3231                        col.prop(tex, "use_map_to_bounds")
3232                elif tex.texture_coords == 'OBJECT':
3233                    col.prop(tex, "use_from_original")
3234                    if (idblock.type == 'VOLUME'):
3235                        col.prop(tex, "use_map_to_bounds")
3236                else:
3237                    col.label()
3238
3239                col = split.column()
3240                row = col.row()
3241                row.prop(tex, "mapping_x", text="")
3242                row.prop(tex, "mapping_y", text="")
3243                row.prop(tex, "mapping_z", text="")
3244
3245            row = layout.row()
3246            row.column().prop(tex, "offset")
3247            row.column().prop(tex, "scale")
3248
3249class TEXTURE_PT_POV_influence(TextureSlotPanel, Panel):
3250    """Use this class to define pov texture influence buttons."""
3251
3252    bl_label = "Influence"
3253    COMPAT_ENGINES = {'POVRAY_RENDER'}
3254    bl_space_type = 'PROPERTIES'
3255    bl_region_type = 'WINDOW'
3256    #bl_context = 'texture'
3257    @classmethod
3258    def poll(cls, context):
3259        idblock = pov_context_tex_datablock(context)
3260        if (
3261            # isinstance(idblock, Brush) and # Brush used for everything since 2.8
3262            context.scene.texture_context == 'OTHER'
3263        ):  # XXX replace by isinstance(idblock, bpy.types.Brush) and ...
3264            return False
3265
3266        # Specify below also for pov_world_texture_slots, lights etc.
3267        # to display for various types of slots but only when any
3268        if not getattr(idblock, "pov_texture_slots", None):
3269            return False
3270
3271        engine = context.scene.render.engine
3272        return engine in cls.COMPAT_ENGINES
3273
3274    def draw(self, context):
3275
3276        layout = self.layout
3277
3278        idblock = pov_context_tex_datablock(context)
3279        # tex = context.pov_texture_slot
3280        #mat = bpy.context.active_object.active_material
3281        texslot = idblock.pov_texture_slots[
3282            idblock.pov.active_texture_index
3283        ]  # bpy.data.textures[mat.active_texture_index]
3284        tex = bpy.data.textures[
3285            idblock.pov_texture_slots[idblock.pov.active_texture_index].texture
3286        ]
3287
3288        def factor_but(layout, toggle, factor, name):
3289            row = layout.row(align=True)
3290            row.prop(texslot, toggle, text="")
3291            sub = row.row(align=True)
3292            sub.active = getattr(texslot, toggle)
3293            sub.prop(texslot, factor, text=name, slider=True)
3294            return sub  # XXX, temp. use_map_normal needs to override.
3295
3296        if isinstance(idblock, Material):
3297            split = layout.split()
3298
3299            col = split.column()
3300            if idblock.pov.type in {'SURFACE', 'WIRE'}:
3301
3302                split = layout.split()
3303
3304                col = split.column()
3305                col.label(text="Diffuse:")
3306                factor_but(
3307                    col, "use_map_diffuse", "diffuse_factor", "Intensity"
3308                )
3309                factor_but(
3310                    col,
3311                    "use_map_color_diffuse",
3312                    "diffuse_color_factor",
3313                    "Color",
3314                )
3315                factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
3316                factor_but(
3317                    col,
3318                    "use_map_translucency",
3319                    "translucency_factor",
3320                    "Translucency",
3321                )
3322
3323                col.label(text="Specular:")
3324                factor_but(
3325                    col, "use_map_specular", "specular_factor", "Intensity"
3326                )
3327                factor_but(
3328                    col, "use_map_color_spec", "specular_color_factor", "Color"
3329                )
3330                factor_but(
3331                    col, "use_map_hardness", "hardness_factor", "Hardness"
3332                )
3333
3334                col = split.column()
3335                col.label(text="Shading:")
3336                factor_but(col, "use_map_ambient", "ambient_factor", "Ambient")
3337                factor_but(col, "use_map_emit", "emit_factor", "Emit")
3338                factor_but(col, "use_map_mirror", "mirror_factor", "Mirror")
3339                factor_but(col, "use_map_raymir", "raymir_factor", "Ray Mirror")
3340
3341                col.label(text="Geometry:")
3342                # XXX replace 'or' when displacement is fixed to not rely on normal influence value.
3343                sub_tmp = factor_but(
3344                    col, "use_map_normal", "normal_factor", "Normal"
3345                )
3346                sub_tmp.active = (
3347                    texslot.use_map_normal or texslot.use_map_displacement
3348                )
3349                # END XXX
3350
3351                factor_but(col, "use_map_warp", "warp_factor", "Warp")
3352                factor_but(
3353                    col,
3354                    "use_map_displacement",
3355                    "displacement_factor",
3356                    "Displace",
3357                )
3358
3359                # ~ sub = col.column()
3360                # ~ sub.active = texslot.use_map_translucency or texslot.map_emit or texslot.map_alpha or texslot.map_raymir or texslot.map_hardness or texslot.map_ambient or texslot.map_specularity or texslot.map_reflection or texslot.map_mirror
3361                # ~ sub.prop(texslot, "default_value", text="Amount", slider=True)
3362            elif idblock.pov.type == 'HALO':
3363                layout.label(text="Halo:")
3364
3365                split = layout.split()
3366
3367                col = split.column()
3368                factor_but(
3369                    col,
3370                    "use_map_color_diffuse",
3371                    "diffuse_color_factor",
3372                    "Color",
3373                )
3374                factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
3375
3376                col = split.column()
3377                factor_but(col, "use_map_raymir", "raymir_factor", "Size")
3378                factor_but(
3379                    col, "use_map_hardness", "hardness_factor", "Hardness"
3380                )
3381                factor_but(
3382                    col, "use_map_translucency", "translucency_factor", "Add"
3383                )
3384            elif idblock.pov.type == 'VOLUME':
3385                layout.label(text="Volume:")
3386
3387                split = layout.split()
3388
3389                col = split.column()
3390                factor_but(col, "use_map_density", "density_factor", "Density")
3391                factor_but(
3392                    col, "use_map_emission", "emission_factor", "Emission"
3393                )
3394                factor_but(
3395                    col, "use_map_scatter", "scattering_factor", "Scattering"
3396                )
3397                factor_but(
3398                    col, "use_map_reflect", "reflection_factor", "Reflection"
3399                )
3400
3401                col = split.column()
3402                col.label(text=" ")
3403                factor_but(
3404                    col,
3405                    "use_map_color_emission",
3406                    "emission_color_factor",
3407                    "Emission Color",
3408                )
3409                factor_but(
3410                    col,
3411                    "use_map_color_transmission",
3412                    "transmission_color_factor",
3413                    "Transmission Color",
3414                )
3415                factor_but(
3416                    col,
3417                    "use_map_color_reflection",
3418                    "reflection_color_factor",
3419                    "Reflection Color",
3420                )
3421
3422                layout.label(text="Geometry:")
3423
3424                split = layout.split()
3425
3426                col = split.column()
3427                factor_but(col, "use_map_warp", "warp_factor", "Warp")
3428
3429                col = split.column()
3430                factor_but(
3431                    col,
3432                    "use_map_displacement",
3433                    "displacement_factor",
3434                    "Displace",
3435                )
3436
3437        elif isinstance(idblock, Light):
3438            split = layout.split()
3439
3440            col = split.column()
3441            factor_but(col, "use_map_color", "color_factor", "Color")
3442
3443            col = split.column()
3444            factor_but(col, "use_map_shadow", "shadow_factor", "Shadow")
3445
3446        elif isinstance(idblock, World):
3447            split = layout.split()
3448
3449            col = split.column()
3450            factor_but(col, "use_map_blend", "blend_factor", "Blend")
3451            factor_but(col, "use_map_horizon", "horizon_factor", "Horizon")
3452
3453            col = split.column()
3454            factor_but(
3455                col, "use_map_zenith_up", "zenith_up_factor", "Zenith Up"
3456            )
3457            factor_but(
3458                col, "use_map_zenith_down", "zenith_down_factor", "Zenith Down"
3459            )
3460        elif isinstance(idblock, ParticleSettings):
3461            split = layout.split()
3462
3463            col = split.column()
3464            col.label(text="General:")
3465            factor_but(col, "use_map_time", "time_factor", "Time")
3466            factor_but(col, "use_map_life", "life_factor", "Lifetime")
3467            factor_but(col, "use_map_density", "density_factor", "Density")
3468            factor_but(col, "use_map_size", "size_factor", "Size")
3469
3470            col = split.column()
3471            col.label(text="Physics:")
3472            factor_but(col, "use_map_velocity", "velocity_factor", "Velocity")
3473            factor_but(col, "use_map_damp", "damp_factor", "Damp")
3474            factor_but(col, "use_map_gravity", "gravity_factor", "Gravity")
3475            factor_but(col, "use_map_field", "field_factor", "Force Fields")
3476
3477            layout.label(text="Hair:")
3478
3479            split = layout.split()
3480
3481            col = split.column()
3482            factor_but(col, "use_map_length", "length_factor", "Length")
3483            factor_but(col, "use_map_clump", "clump_factor", "Clump")
3484            factor_but(col, "use_map_twist", "twist_factor", "Twist")
3485
3486            col = split.column()
3487            factor_but(
3488                col, "use_map_kink_amp", "kink_amp_factor", "Kink Amplitude"
3489            )
3490            factor_but(
3491                col, "use_map_kink_freq", "kink_freq_factor", "Kink Frequency"
3492            )
3493            factor_but(col, "use_map_rough", "rough_factor", "Rough")
3494
3495        elif isinstance(idblock, FreestyleLineStyle):
3496            split = layout.split()
3497
3498            col = split.column()
3499            factor_but(
3500                col, "use_map_color_diffuse", "diffuse_color_factor", "Color"
3501            )
3502            col = split.column()
3503            factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
3504
3505        layout.separator()
3506
3507        if not isinstance(idblock, ParticleSettings):
3508            split = layout.split()
3509
3510            col = split.column()
3511            # col.prop(tex, "blend_type", text="Blend") #deprecated since 2.8
3512            # col.prop(tex, "use_rgb_to_intensity") #deprecated since 2.8
3513            # color is used on gray-scale textures even when use_rgb_to_intensity is disabled.
3514            # col.prop(tex, "color", text="") #deprecated since 2.8
3515
3516            col = split.column()
3517            # col.prop(tex, "invert", text="Negative") #deprecated since 2.8
3518            # col.prop(tex, "use_stencil") #deprecated since 2.8
3519
3520        # if isinstance(idblock, (Material, World)):
3521        # col.prop(tex, "default_value", text="DVar", slider=True)
3522
3523
3524class TEXTURE_PT_POV_tex_gamma(TextureButtonsPanel, Panel):
3525    """Use this class to define pov texture gamma buttons."""
3526
3527    bl_label = "Image Gamma"
3528    COMPAT_ENGINES = {'POVRAY_RENDER'}
3529
3530    def draw_header(self, context):
3531        tex = context.texture
3532
3533        self.layout.prop(
3534            tex.pov, "tex_gamma_enable", text="", icon='SEQ_LUMA_WAVEFORM'
3535        )
3536
3537    def draw(self, context):
3538        layout = self.layout
3539
3540        tex = context.texture
3541
3542        layout.active = tex.pov.tex_gamma_enable
3543        layout.prop(tex.pov, "tex_gamma_value", text="Gamma Value")
3544
3545
3546# commented out below UI for texture only custom code inside exported material:
3547# class TEXTURE_PT_povray_replacement_text(TextureButtonsPanel, Panel):
3548# bl_label = "Custom POV Code"
3549# COMPAT_ENGINES = {'POVRAY_RENDER'}
3550
3551# def draw(self, context):
3552# layout = self.layout
3553
3554# tex = context.texture
3555
3556# col = layout.column()
3557# col.label(text="Replace properties with:")
3558# col.prop(tex.pov, "replacement_text", text="")
3559
3560
3561class OBJECT_PT_POV_obj_parameters(ObjectButtonsPanel, Panel):
3562    """Use this class to define pov specific object level options buttons."""
3563
3564    bl_label = "POV"
3565    COMPAT_ENGINES = {'POVRAY_RENDER'}
3566
3567    @classmethod
3568    def poll(cls, context):
3569
3570        engine = context.scene.render.engine
3571        return engine in cls.COMPAT_ENGINES
3572
3573    def draw(self, context):
3574        layout = self.layout
3575
3576        obj = context.object
3577
3578        split = layout.split()
3579
3580        col = split.column(align=True)
3581
3582        col.label(text="Radiosity:")
3583        col.prop(obj.pov, "importance_value", text="Importance")
3584        col.label(text="Photons:")
3585        col.prop(obj.pov, "collect_photons", text="Receive Photon Caustics")
3586        if obj.pov.collect_photons:
3587            col.prop(
3588                obj.pov, "spacing_multiplier", text="Photons Spacing Multiplier"
3589            )
3590
3591        split = layout.split()
3592
3593        col = split.column()
3594        col.prop(obj.pov, "hollow")
3595        col.prop(obj.pov, "double_illuminate")
3596
3597        if obj.type == 'META' or obj.pov.curveshape == 'lathe':
3598            # if obj.pov.curveshape == 'sor'
3599            col.prop(obj.pov, "sturm")
3600        col.prop(obj.pov, "no_shadow")
3601        col.prop(obj.pov, "no_image")
3602        col.prop(obj.pov, "no_reflection")
3603        col.prop(obj.pov, "no_radiosity")
3604        col.prop(obj.pov, "inverse")
3605        col.prop(obj.pov, "hierarchy")
3606        # col.prop(obj.pov,"boundorclip",text="Bound / Clip")
3607        # if obj.pov.boundorclip != "none":
3608        # col.prop_search(obj.pov,"boundorclipob",context.blend_data,"objects",text="Object")
3609        # text = "Clipped by"
3610        # if obj.pov.boundorclip == "clipped_by":
3611        # text = "Bounded by"
3612        # col.prop(obj.pov,"addboundorclip",text=text)
3613
3614
3615class OBJECT_PT_POV_obj_sphere(PovDataButtonsPanel, Panel):
3616    """Use this class to define pov sphere primitive parameters buttons."""
3617
3618    bl_label = "POV Sphere"
3619    COMPAT_ENGINES = {'POVRAY_RENDER'}
3620    # bl_options = {'HIDE_HEADER'}
3621    @classmethod
3622    def poll(cls, context):
3623        engine = context.scene.render.engine
3624        obj = context.object
3625        return (
3626            obj
3627            and obj.pov.object_as == 'SPHERE'
3628            and (engine in cls.COMPAT_ENGINES)
3629        )
3630
3631    def draw(self, context):
3632        layout = self.layout
3633
3634        obj = context.object
3635
3636        col = layout.column()
3637
3638        if obj.pov.object_as == 'SPHERE':
3639            if obj.pov.unlock_parameters == False:
3640                col.prop(
3641                    obj.pov,
3642                    "unlock_parameters",
3643                    text="Exported parameters below",
3644                    icon='LOCKED',
3645                )
3646                col.label(text="Sphere radius: " + str(obj.pov.sphere_radius))
3647
3648            else:
3649                col.prop(
3650                    obj.pov,
3651                    "unlock_parameters",
3652                    text="Edit exported parameters",
3653                    icon='UNLOCKED',
3654                )
3655                col.label(text="3D view proxy may get out of synch")
3656                col.active = obj.pov.unlock_parameters
3657
3658                layout.operator(
3659                    "pov.sphere_update", text="Update", icon="SHADING_RENDERED"
3660                )
3661
3662                # col.label(text="Parameters:")
3663                col.prop(obj.pov, "sphere_radius", text="Radius of Sphere")
3664
3665
3666class OBJECT_PT_POV_obj_cylinder(PovDataButtonsPanel, Panel):
3667    """Use this class to define pov cylinder primitive parameters buttons."""
3668
3669    bl_label = "POV Cylinder"
3670    COMPAT_ENGINES = {'POVRAY_RENDER'}
3671    # bl_options = {'HIDE_HEADER'}
3672    @classmethod
3673    def poll(cls, context):
3674        engine = context.scene.render.engine
3675        obj = context.object
3676        return (
3677            obj
3678            and obj.pov.object_as == 'CYLINDER'
3679            and (engine in cls.COMPAT_ENGINES)
3680        )
3681
3682    def draw(self, context):
3683        layout = self.layout
3684
3685        obj = context.object
3686
3687        col = layout.column()
3688
3689        if obj.pov.object_as == 'CYLINDER':
3690            if obj.pov.unlock_parameters == False:
3691                col.prop(
3692                    obj.pov,
3693                    "unlock_parameters",
3694                    text="Exported parameters below",
3695                    icon='LOCKED',
3696                )
3697                col.label(
3698                    text="Cylinder radius: " + str(obj.pov.cylinder_radius)
3699                )
3700                col.label(
3701                    text="Cylinder cap location: "
3702                    + str(obj.pov.cylinder_location_cap)
3703                )
3704
3705            else:
3706                col.prop(
3707                    obj.pov,
3708                    "unlock_parameters",
3709                    text="Edit exported parameters",
3710                    icon='UNLOCKED',
3711                )
3712                col.label(text="3D view proxy may get out of synch")
3713                col.active = obj.pov.unlock_parameters
3714
3715                layout.operator(
3716                    "pov.cylinder_update", text="Update", icon="MESH_CYLINDER"
3717                )
3718
3719                # col.label(text="Parameters:")
3720                col.prop(obj.pov, "cylinder_radius")
3721                col.prop(obj.pov, "cylinder_location_cap")
3722
3723
3724class OBJECT_PT_POV_obj_cone(PovDataButtonsPanel, Panel):
3725    """Use this class to define pov cone primitive parameters buttons."""
3726
3727    bl_label = "POV Cone"
3728    COMPAT_ENGINES = {'POVRAY_RENDER'}
3729    # bl_options = {'HIDE_HEADER'}
3730    @classmethod
3731    def poll(cls, context):
3732        engine = context.scene.render.engine
3733        obj = context.object
3734        return (
3735            obj
3736            and obj.pov.object_as == 'CONE'
3737            and (engine in cls.COMPAT_ENGINES)
3738        )
3739
3740    def draw(self, context):
3741        layout = self.layout
3742
3743        obj = context.object
3744
3745        col = layout.column()
3746
3747        if obj.pov.object_as == 'CONE':
3748            if obj.pov.unlock_parameters == False:
3749                col.prop(
3750                    obj.pov,
3751                    "unlock_parameters",
3752                    text="Exported parameters below",
3753                    icon='LOCKED',
3754                )
3755                col.label(
3756                    text="Cone base radius: " + str(obj.pov.cone_base_radius)
3757                )
3758                col.label(
3759                    text="Cone cap radius: " + str(obj.pov.cone_cap_radius)
3760                )
3761                col.label(
3762                    text="Cone proxy segments: " + str(obj.pov.cone_segments)
3763                )
3764                col.label(text="Cone height: " + str(obj.pov.cone_height))
3765            else:
3766                col.prop(
3767                    obj.pov,
3768                    "unlock_parameters",
3769                    text="Edit exported parameters",
3770                    icon='UNLOCKED',
3771                )
3772                col.label(text="3D view proxy may get out of synch")
3773                col.active = obj.pov.unlock_parameters
3774
3775                layout.operator(
3776                    "pov.cone_update", text="Update", icon="MESH_CONE"
3777                )
3778
3779                # col.label(text="Parameters:")
3780                col.prop(
3781                    obj.pov, "cone_base_radius", text="Radius of Cone Base"
3782                )
3783                col.prop(obj.pov, "cone_cap_radius", text="Radius of Cone Cap")
3784                col.prop(
3785                    obj.pov, "cone_segments", text="Segmentation of Cone proxy"
3786                )
3787                col.prop(obj.pov, "cone_height", text="Height of the cone")
3788
3789
3790class OBJECT_PT_POV_obj_superellipsoid(PovDataButtonsPanel, Panel):
3791    """Use this class to define pov superellipsoid primitive parameters buttons."""
3792
3793    bl_label = "POV Superquadric ellipsoid"
3794    COMPAT_ENGINES = {'POVRAY_RENDER'}
3795    # bl_options = {'HIDE_HEADER'}
3796    @classmethod
3797    def poll(cls, context):
3798        engine = context.scene.render.engine
3799        obj = context.object
3800        return (
3801            obj
3802            and obj.pov.object_as == 'SUPERELLIPSOID'
3803            and (engine in cls.COMPAT_ENGINES)
3804        )
3805
3806    def draw(self, context):
3807        layout = self.layout
3808
3809        obj = context.object
3810
3811        col = layout.column()
3812
3813        if obj.pov.object_as == 'SUPERELLIPSOID':
3814            if obj.pov.unlock_parameters == False:
3815                col.prop(
3816                    obj.pov,
3817                    "unlock_parameters",
3818                    text="Exported parameters below",
3819                    icon='LOCKED',
3820                )
3821                col.label(text="Radial segmentation: " + str(obj.pov.se_u))
3822                col.label(text="Lateral segmentation: " + str(obj.pov.se_v))
3823                col.label(text="Ring shape: " + str(obj.pov.se_n1))
3824                col.label(text="Cross-section shape: " + str(obj.pov.se_n2))
3825                col.label(text="Fill up and down: " + str(obj.pov.se_edit))
3826            else:
3827                col.prop(
3828                    obj.pov,
3829                    "unlock_parameters",
3830                    text="Edit exported parameters",
3831                    icon='UNLOCKED',
3832                )
3833                col.label(text="3D view proxy may get out of synch")
3834                col.active = obj.pov.unlock_parameters
3835
3836                layout.operator(
3837                    "pov.superellipsoid_update",
3838                    text="Update",
3839                    icon="MOD_SUBSURF",
3840                )
3841
3842                # col.label(text="Parameters:")
3843                col.prop(obj.pov, "se_u")
3844                col.prop(obj.pov, "se_v")
3845                col.prop(obj.pov, "se_n1")
3846                col.prop(obj.pov, "se_n2")
3847                col.prop(obj.pov, "se_edit")
3848
3849
3850class OBJECT_PT_POV_obj_torus(PovDataButtonsPanel, Panel):
3851    """Use this class to define pov torus primitive parameters buttons."""
3852
3853    bl_label = "POV Torus"
3854    COMPAT_ENGINES = {'POVRAY_RENDER'}
3855    # bl_options = {'HIDE_HEADER'}
3856    @classmethod
3857    def poll(cls, context):
3858        engine = context.scene.render.engine
3859        obj = context.object
3860        return (
3861            obj
3862            and obj.pov.object_as == 'TORUS'
3863            and (engine in cls.COMPAT_ENGINES)
3864        )
3865
3866    def draw(self, context):
3867        layout = self.layout
3868
3869        obj = context.object
3870
3871        col = layout.column()
3872
3873        if obj.pov.object_as == 'TORUS':
3874            if obj.pov.unlock_parameters == False:
3875                col.prop(
3876                    obj.pov,
3877                    "unlock_parameters",
3878                    text="Exported parameters below",
3879                    icon='LOCKED',
3880                )
3881                col.label(
3882                    text="Torus major radius: "
3883                    + str(obj.pov.torus_major_radius)
3884                )
3885                col.label(
3886                    text="Torus minor radius: "
3887                    + str(obj.pov.torus_minor_radius)
3888                )
3889                col.label(
3890                    text="Torus major segments: "
3891                    + str(obj.pov.torus_major_segments)
3892                )
3893                col.label(
3894                    text="Torus minor segments: "
3895                    + str(obj.pov.torus_minor_segments)
3896                )
3897            else:
3898                col.prop(
3899                    obj.pov,
3900                    "unlock_parameters",
3901                    text="Edit exported parameters",
3902                    icon='UNLOCKED',
3903                )
3904                col.label(text="3D view proxy may get out of synch")
3905                col.active = obj.pov.unlock_parameters
3906
3907                layout.operator(
3908                    "pov.torus_update", text="Update", icon="MESH_TORUS"
3909                )
3910
3911                # col.label(text="Parameters:")
3912                col.prop(obj.pov, "torus_major_radius")
3913                col.prop(obj.pov, "torus_minor_radius")
3914                col.prop(obj.pov, "torus_major_segments")
3915                col.prop(obj.pov, "torus_minor_segments")
3916
3917
3918class OBJECT_PT_POV_obj_supertorus(PovDataButtonsPanel, Panel):
3919    """Use this class to define pov supertorus primitive parameters buttons."""
3920
3921    bl_label = "POV SuperTorus"
3922    COMPAT_ENGINES = {'POVRAY_RENDER'}
3923    # bl_options = {'HIDE_HEADER'}
3924    @classmethod
3925    def poll(cls, context):
3926        engine = context.scene.render.engine
3927        obj = context.object
3928        return (
3929            obj
3930            and obj.pov.object_as == 'SUPERTORUS'
3931            and (engine in cls.COMPAT_ENGINES)
3932        )
3933
3934    def draw(self, context):
3935        layout = self.layout
3936
3937        obj = context.object
3938
3939        col = layout.column()
3940
3941        if obj.pov.object_as == 'SUPERTORUS':
3942            if obj.pov.unlock_parameters == False:
3943                col.prop(
3944                    obj.pov,
3945                    "unlock_parameters",
3946                    text="Exported parameters below",
3947                    icon='LOCKED',
3948                )
3949                col.label(
3950                    text="SuperTorus major radius: "
3951                    + str(obj.pov.st_major_radius)
3952                )
3953                col.label(
3954                    text="SuperTorus minor radius: "
3955                    + str(obj.pov.st_minor_radius)
3956                )
3957                col.label(
3958                    text="SuperTorus major segments: " + str(obj.pov.st_u)
3959                )
3960                col.label(
3961                    text="SuperTorus minor segments: " + str(obj.pov.st_v)
3962                )
3963
3964                col.label(
3965                    text="SuperTorus Ring Manipulator: " + str(obj.pov.st_ring)
3966                )
3967                col.label(
3968                    text="SuperTorus Cross Manipulator: "
3969                    + str(obj.pov.st_cross)
3970                )
3971                col.label(
3972                    text="SuperTorus Internal And External radii: "
3973                    + str(obj.pov.st_ie)
3974                )
3975
3976                col.label(
3977                    text="SuperTorus accuracy: " + str(ob.pov.st_accuracy)
3978                )
3979                col.label(
3980                    text="SuperTorus max gradient: "
3981                    + str(ob.pov.st_max_gradient)
3982                )
3983
3984            else:
3985                col.prop(
3986                    obj.pov,
3987                    "unlock_parameters",
3988                    text="Edit exported parameters",
3989                    icon='UNLOCKED',
3990                )
3991                col.label(text="3D view proxy may get out of synch")
3992                col.active = obj.pov.unlock_parameters
3993
3994                layout.operator(
3995                    "pov.supertorus_update", text="Update", icon="MESH_TORUS"
3996                )
3997
3998                # col.label(text="Parameters:")
3999                col.prop(obj.pov, "st_major_radius")
4000                col.prop(obj.pov, "st_minor_radius")
4001                col.prop(obj.pov, "st_u")
4002                col.prop(obj.pov, "st_v")
4003                col.prop(obj.pov, "st_ring")
4004                col.prop(obj.pov, "st_cross")
4005                col.prop(obj.pov, "st_ie")
4006                # col.prop(obj.pov, "st_edit") #?
4007                col.prop(obj.pov, "st_accuracy")
4008                col.prop(obj.pov, "st_max_gradient")
4009
4010
4011class OBJECT_PT_POV_obj_parametric(PovDataButtonsPanel, Panel):
4012    """Use this class to define pov parametric surface primitive parameters buttons."""
4013
4014    bl_label = "POV Parametric surface"
4015    COMPAT_ENGINES = {'POVRAY_RENDER'}
4016    # bl_options = {'HIDE_HEADER'}
4017    @classmethod
4018    def poll(cls, context):
4019        engine = context.scene.render.engine
4020        obj = context.object
4021        return (
4022            obj
4023            and obj.pov.object_as == 'PARAMETRIC'
4024            and (engine in cls.COMPAT_ENGINES)
4025        )
4026
4027    def draw(self, context):
4028        layout = self.layout
4029
4030        obj = context.object
4031
4032        col = layout.column()
4033
4034        if obj.pov.object_as == 'PARAMETRIC':
4035            if obj.pov.unlock_parameters == False:
4036                col.prop(
4037                    obj.pov,
4038                    "unlock_parameters",
4039                    text="Exported parameters below",
4040                    icon='LOCKED',
4041                )
4042                col.label(text="Minimum U: " + str(obj.pov.u_min))
4043                col.label(text="Minimum V: " + str(obj.pov.v_min))
4044                col.label(text="Maximum U: " + str(obj.pov.u_max))
4045                col.label(text="Minimum V: " + str(obj.pov.v_min))
4046                col.label(text="X Function: " + str(obj.pov.x_eq))
4047                col.label(text="Y Function: " + str(obj.pov.y_eq))
4048                col.label(text="Z Function: " + str(obj.pov.x_eq))
4049
4050            else:
4051                col.prop(
4052                    obj.pov,
4053                    "unlock_parameters",
4054                    text="Edit exported parameters",
4055                    icon='UNLOCKED',
4056                )
4057                col.label(text="3D view proxy may get out of synch")
4058                col.active = obj.pov.unlock_parameters
4059
4060                layout.operator(
4061                    "pov.parametric_update", text="Update", icon="SCRIPTPLUGINS"
4062                )
4063
4064                col.prop(obj.pov, "u_min", text="Minimum U")
4065                col.prop(obj.pov, "v_min", text="Minimum V")
4066                col.prop(obj.pov, "u_max", text="Maximum U")
4067                col.prop(obj.pov, "v_max", text="Minimum V")
4068                col.prop(obj.pov, "x_eq", text="X Function")
4069                col.prop(obj.pov, "y_eq", text="Y Function")
4070                col.prop(obj.pov, "z_eq", text="Z Function")
4071
4072
4073class OBJECT_PT_povray_replacement_text(ObjectButtonsPanel, Panel):
4074    """Use this class to define pov object replacement field."""
4075
4076    bl_label = "Custom POV Code"
4077    COMPAT_ENGINES = {'POVRAY_RENDER'}
4078
4079    def draw(self, context):
4080        layout = self.layout
4081
4082        obj = context.object
4083
4084        col = layout.column()
4085        col.label(text="Replace properties with:")
4086        col.prop(obj.pov, "replacement_text", text="")
4087
4088
4089###############################################################################
4090# Add Povray Objects
4091###############################################################################
4092
4093
4094class VIEW_MT_POV_primitives_add(Menu):
4095    """Define the primitives menu with presets"""
4096
4097    bl_idname = "VIEW_MT_POV_primitives_add"
4098    bl_label = "Povray"
4099    COMPAT_ENGINES = {'POVRAY_RENDER'}
4100
4101    @classmethod
4102    def poll(cls, context):
4103        engine = context.scene.render.engine
4104        return engine == 'POVRAY_RENDER'
4105
4106    def draw(self, context):
4107        layout = self.layout
4108        layout.operator_context = 'INVOKE_REGION_WIN'
4109        layout.menu(
4110            VIEW_MT_POV_Basic_Shapes.bl_idname, text="Primitives", icon="GROUP"
4111        )
4112        layout.menu(VIEW_MT_POV_import.bl_idname, text="Import", icon="IMPORT")
4113
4114
4115class VIEW_MT_POV_Basic_Shapes(Menu):
4116    """Use this class to sort simple primitives menu entries."""
4117
4118    bl_idname = "POVRAY_MT_basic_shape_tools"
4119    bl_label = "Basic_shapes"
4120
4121    def draw(self, context):
4122        layout = self.layout
4123        layout.operator_context = 'INVOKE_REGION_WIN'
4124        layout.operator(
4125            "pov.addplane", text="Infinite Plane", icon='MESH_PLANE'
4126        )
4127        layout.operator("pov.addbox", text="Box", icon='MESH_CUBE')
4128        layout.operator("pov.addsphere", text="Sphere", icon='SHADING_RENDERED')
4129        layout.operator(
4130            "pov.addcylinder", text="Cylinder", icon="MESH_CYLINDER"
4131        )
4132        layout.operator("pov.cone_add", text="Cone", icon="MESH_CONE")
4133        layout.operator("pov.addtorus", text="Torus", icon='MESH_TORUS')
4134        layout.separator()
4135        layout.operator("pov.addrainbow", text="Rainbow", icon="COLOR")
4136        layout.operator("pov.addlathe", text="Lathe", icon='MOD_SCREW')
4137        layout.operator("pov.addprism", text="Prism", icon='MOD_SOLIDIFY')
4138        layout.operator(
4139            "pov.addsuperellipsoid",
4140            text="Superquadric Ellipsoid",
4141            icon='MOD_SUBSURF',
4142        )
4143        layout.operator(
4144            "pov.addheightfield", text="Height Field", icon="RNDCURVE"
4145        )
4146        layout.operator(
4147            "pov.addspheresweep", text="Sphere Sweep", icon='FORCE_CURVE'
4148        )
4149        layout.separator()
4150        layout.operator(
4151            "pov.addblobsphere", text="Blob Sphere", icon='META_DATA'
4152        )
4153        layout.separator()
4154        layout.label(text="Isosurfaces")
4155        layout.operator(
4156            "pov.addisosurfacebox", text="Isosurface Box", icon="META_CUBE"
4157        )
4158        layout.operator(
4159            "pov.addisosurfacesphere",
4160            text="Isosurface Sphere",
4161            icon="META_BALL",
4162        )
4163        layout.operator(
4164            "pov.addsupertorus", text="Supertorus", icon="SURFACE_NTORUS"
4165        )
4166        layout.separator()
4167        layout.label(text="Macro based")
4168        layout.operator(
4169            "pov.addpolygontocircle",
4170            text="Polygon To Circle Blending",
4171            icon="MOD_CAST",
4172        )
4173        layout.operator("pov.addloft", text="Loft", icon="SURFACE_NSURFACE")
4174        layout.separator()
4175        # Warning if the Add Advanced Objects addon containing
4176        # Add mesh extra objects is not enabled
4177        if not check_add_mesh_extra_objects():
4178            # col = box.column()
4179            layout.label(
4180                text="Please enable Add Mesh: Extra Objects addon", icon="INFO"
4181            )
4182            # layout.separator()
4183            layout.operator(
4184                "preferences.addon_show",
4185                text="Go to Add Mesh: Extra Objects addon",
4186                icon="PREFERENCES",
4187            ).module = "add_mesh_extra_objects"
4188
4189            # layout.separator()
4190            return
4191        else:
4192            layout.operator(
4193                "pov.addparametric", text="Parametric", icon='SCRIPTPLUGINS'
4194            )
4195
4196
4197class VIEW_MT_POV_import(Menu):
4198    """Use this class for the import menu."""
4199
4200    bl_idname = "POVRAY_MT_import_tools"
4201    bl_label = "Import"
4202
4203    def draw(self, context):
4204        layout = self.layout
4205        layout.operator_context = 'INVOKE_REGION_WIN'
4206        layout.operator("import_scene.pov", icon="FORCE_LENNARDJONES")
4207
4208
4209def menu_func_add(self, context):
4210    engine = context.scene.render.engine
4211    if engine == 'POVRAY_RENDER':
4212        self.layout.menu("VIEW_MT_POV_primitives_add", icon="PLUGIN")
4213
4214
4215def menu_func_import(self, context):
4216    engine = context.scene.render.engine
4217    if engine == 'POVRAY_RENDER':
4218        self.layout.operator("import_scene.pov", icon="FORCE_LENNARDJONES")
4219
4220
4221##############Nodes
4222
4223# def find_node_input(node, name):
4224# for input in node.inputs:
4225# if input.name == name:
4226# return input
4227
4228# def panel_node_draw(layout, id_data, output_type, input_name):
4229# if not id_data.use_nodes:
4230# #layout.operator("pov.material_use_nodes", icon='SOUND')#'NODETREE')
4231# #layout.operator("pov.use_shading_nodes", icon='NODETREE')
4232# layout.operator("WM_OT_context_toggle", icon='NODETREE').data_path = \
4233# "material.pov.material_use_nodes"
4234# return False
4235
4236# ntree = id_data.node_tree
4237
4238# node = find_node(id_data, output_type)
4239# if not node:
4240# layout.label(text="No output node")
4241# else:
4242# input = find_node_input(node, input_name)
4243# layout.template_node_view(ntree, node, input)
4244
4245# return True
4246
4247
4248class NODE_MT_POV_map_create(Menu):
4249    """Create maps"""
4250
4251    bl_idname = "POVRAY_MT_node_map_create"
4252    bl_label = "Create map"
4253
4254    def draw(self, context):
4255        layout = self.layout
4256        layout.operator("node.map_create")
4257
4258
4259def menu_func_nodes(self, context):
4260    ob = context.object
4261    if hasattr(ob, 'active_material'):
4262        mat = context.object.active_material
4263        if mat and context.space_data.tree_type == 'ObjectNodeTree':
4264            self.layout.prop(mat.pov, "material_use_nodes")
4265            self.layout.menu(NODE_MT_POV_map_create.bl_idname)
4266            self.layout.operator("wm.updatepreviewkey")
4267        if (
4268            hasattr(mat, 'active_texture')
4269            and context.scene.render.engine == 'POVRAY_RENDER'
4270        ):
4271            tex = mat.active_texture
4272            if tex and context.space_data.tree_type == 'TextureNodeTree':
4273                self.layout.prop(tex.pov, "texture_use_nodes")
4274
4275
4276###############################################################################
4277# Camera Povray Settings
4278###############################################################################
4279class CAMERA_PT_POV_cam_dof(CameraDataButtonsPanel, Panel):
4280    """Use this class for camera depth of field focal blur buttons."""
4281
4282    bl_label = "POV Aperture"
4283    COMPAT_ENGINES = {'POVRAY_RENDER'}
4284    bl_parent_id = "DATA_PT_camera_dof_aperture"
4285    bl_options = {'HIDE_HEADER'}
4286    # def draw_header(self, context):
4287    # cam = context.camera
4288
4289    # self.layout.prop(cam.pov, "dof_enable", text="")
4290
4291    def draw(self, context):
4292        layout = self.layout
4293
4294        cam = context.camera
4295
4296        layout.active = cam.dof.use_dof
4297        layout.use_property_split = True  # Active single-column layout
4298
4299        flow = layout.grid_flow(
4300            row_major=True,
4301            columns=0,
4302            even_columns=True,
4303            even_rows=False,
4304            align=False,
4305        )
4306
4307        col = flow.column()
4308        col.label(text="F-Stop value will export as")
4309        col.label(
4310            text="POV aperture : "
4311            + "%.3f" % (1 / cam.dof.aperture_fstop * 1000)
4312        )
4313
4314        col = flow.column()
4315        col.prop(cam.pov, "dof_samples_min")
4316        col.prop(cam.pov, "dof_samples_max")
4317        col.prop(cam.pov, "dof_variance")
4318        col.prop(cam.pov, "dof_confidence")
4319
4320
4321class CAMERA_PT_POV_cam_nor(CameraDataButtonsPanel, Panel):
4322    """Use this class for camera normal perturbation buttons."""
4323
4324    bl_label = "POV Perturbation"
4325    COMPAT_ENGINES = {'POVRAY_RENDER'}
4326
4327    def draw_header(self, context):
4328        cam = context.camera
4329
4330        self.layout.prop(cam.pov, "normal_enable", text="")
4331
4332    def draw(self, context):
4333        layout = self.layout
4334
4335        cam = context.camera
4336
4337        layout.active = cam.pov.normal_enable
4338
4339        layout.prop(cam.pov, "normal_patterns")
4340        layout.prop(cam.pov, "cam_normal")
4341        layout.prop(cam.pov, "turbulence")
4342        layout.prop(cam.pov, "scale")
4343
4344
4345class CAMERA_PT_POV_replacement_text(CameraDataButtonsPanel, Panel):
4346    """Use this class for camera text replacement field."""
4347
4348    bl_label = "Custom POV Code"
4349    COMPAT_ENGINES = {'POVRAY_RENDER'}
4350
4351    def draw(self, context):
4352        layout = self.layout
4353
4354        cam = context.camera
4355
4356        col = layout.column()
4357        col.label(text="Replace properties with:")
4358        col.prop(cam.pov, "replacement_text", text="")
4359
4360
4361###############################################################################
4362# Text Povray Settings
4363###############################################################################
4364
4365
4366class TEXT_OT_POV_insert(Operator):
4367    """Use this class to create blender text editor operator to insert pov snippets like other pov IDEs."""
4368
4369    bl_idname = "text.povray_insert"
4370    bl_label = "Insert"
4371
4372    filepath: bpy.props.StringProperty(name="Filepath", subtype='FILE_PATH')
4373
4374    @classmethod
4375    def poll(cls, context):
4376        # context.area.type == 'TEXT_EDITOR'
4377        return bpy.ops.text.insert.poll()
4378
4379    def execute(self, context):
4380        if self.filepath and isfile(self.filepath):
4381            file = open(self.filepath, "r")
4382            bpy.ops.text.insert(text=file.read())
4383
4384            # places the cursor at the end without scrolling -.-
4385            # context.space_data.text.write(file.read())
4386            file.close()
4387        return {'FINISHED'}
4388
4389
4390def validinsert(ext):
4391    return ext in {".txt", ".inc", ".pov"}
4392
4393
4394class TEXT_MT_POV_insert(Menu):
4395    """Use this class to create a menu launcher in text editor for the TEXT_OT_POV_insert operator ."""
4396
4397    bl_label = "Insert"
4398    bl_idname = "TEXT_MT_POV_insert"
4399
4400    def draw(self, context):
4401        pov_documents = locate_docpath()
4402        prop = self.layout.operator(
4403            "wm.path_open", text="Open folder", icon='FILE_FOLDER'
4404        )
4405        prop.filepath = pov_documents
4406        self.layout.separator()
4407
4408        list = []
4409        for root, dirs, files in os.walk(pov_documents):
4410            list.append(root)
4411        print(list)
4412        self.path_menu(
4413            list,
4414            "text.povray_insert",
4415            # {"internal": True},
4416            filter_ext=validinsert,
4417        )
4418
4419
4420class TEXT_PT_POV_custom_code(TextButtonsPanel, Panel):
4421    """Use this class to create a panel in text editor for the user to decide if he renders text only or adds to 3d scene."""
4422
4423    bl_label = "POV"
4424    COMPAT_ENGINES = {'POVRAY_RENDER'}
4425
4426    def draw(self, context):
4427        layout = self.layout
4428
4429        text = context.space_data.text
4430
4431        pov_documents = locate_docpath()
4432        if not pov_documents:
4433            layout.label(text="Please configure ", icon="INFO")
4434            layout.label(text="default pov include path ")
4435            layout.label(text="in addon preferences")
4436            # layout.separator()
4437            layout.operator(
4438                "preferences.addon_show",
4439                text="Go to Render: Persistence of Vision addon",
4440                icon="PREFERENCES",
4441            ).module = "render_povray"
4442
4443            # layout.separator()
4444        else:
4445            # print(pov_documents)
4446            layout.menu(TEXT_MT_POV_insert.bl_idname)
4447
4448        if text:
4449            box = layout.box()
4450            box.label(text='Source to render:', icon='RENDER_STILL')
4451            row = box.row()
4452            row.prop(text.pov, "custom_code", expand=True)
4453            if text.pov.custom_code in {'3dview'}:
4454                box.operator("render.render", icon='OUTLINER_DATA_ARMATURE')
4455            if text.pov.custom_code in {'text'}:
4456                rtext = bpy.context.space_data.text
4457                box.operator("text.run", icon='ARMATURE_DATA')
4458            # layout.prop(text.pov, "custom_code")
4459            elif text.pov.custom_code in {'both'}:
4460                box.operator("render.render", icon='POSE_HLT')
4461                layout.label(text="Please specify declared", icon="INFO")
4462                layout.label(text="items in properties ")
4463                # layout.label(text="")
4464                layout.label(text="replacement fields")
4465
4466
4467###############################################
4468# Text editor templates from header menu
4469
4470
4471class TEXT_MT_POV_templates(Menu):
4472    """Use this class to create a menu for the same pov templates scenes as other pov IDEs."""
4473
4474    bl_label = "POV"
4475
4476    # We list templates on file evaluation, we can assume they are static data,
4477    # and better avoid running this on every draw call.
4478    import os
4479
4480    template_paths = [os.path.join(os.path.dirname(__file__), "templates_pov")]
4481
4482    def draw(self, context):
4483        self.path_menu(
4484            self.template_paths, "text.open", props_default={"internal": True}
4485        )
4486
4487
4488def menu_func_templates(self, context):
4489    # Do not depend on POV being active renderer here...
4490    self.layout.menu("TEXT_MT_POV_templates")
4491
4492###############################################################################
4493# Freestyle
4494###############################################################################
4495#import addon_utils
4496#addon_utils.paths()[0]
4497#addon_utils.modules()
4498#mod.bl_info['name'] == 'Freestyle SVG Exporter':
4499bpy.utils.script_paths("addons")
4500#render_freestyle_svg = os.path.join(bpy.utils.script_paths("addons"), "render_freestyle_svg.py")
4501
4502render_freestyle_svg = bpy.context.preferences.addons.get('render_freestyle_svg')
4503    #mpath=addon_utils.paths()[0].render_freestyle_svg
4504    #import mpath
4505    #from mpath import render_freestyle_svg #= addon_utils.modules(['Freestyle SVG Exporter'])
4506    #from scripts\\addons import render_freestyle_svg
4507if check_render_freestyle_svg():
4508    '''
4509    snippetsWIP
4510    import myscript
4511    import importlib
4512
4513    importlib.reload(myscript)
4514    myscript.main()
4515    '''
4516    for member in dir(render_freestyle_svg):
4517        subclass = getattr(render_freestyle_svg, member)
4518        try:
4519            subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
4520            if subclass.bl_idname == "RENDER_PT_SVGExporterPanel":
4521                subclass.bl_parent_id = "RENDER_PT_POV_filter"
4522                subclass.bl_options = {'HIDE_HEADER'}
4523                #subclass.bl_order = 11
4524                print(subclass.bl_info)
4525        except:
4526            pass
4527
4528    #del render_freestyle_svg.RENDER_PT_SVGExporterPanel.bl_parent_id
4529
4530
4531class RENDER_PT_POV_filter(RenderButtonsPanel, Panel):
4532    """Use this class to invoke stuff like Freestyle UI."""
4533
4534    bl_label = "Freestyle"
4535    bl_options = {'DEFAULT_CLOSED'}
4536    COMPAT_ENGINES = {'POVRAY_RENDER'}
4537
4538    @classmethod
4539    def poll(cls, context):
4540        with_freestyle = bpy.app.build_options.freestyle
4541        engine = context.scene.render.engine
4542        return(with_freestyle and engine == 'POVRAY_RENDER')
4543    def draw_header(self, context):
4544
4545        #scene = context.scene
4546        rd = context.scene.render
4547        layout = self.layout
4548
4549        if rd.use_freestyle:
4550            layout.prop(
4551                rd, "use_freestyle", text="", icon='LINE_DATA'
4552                    )
4553
4554        else:
4555            layout.prop(
4556                rd, "use_freestyle", text="", icon='OUTLINER_OB_IMAGE'
4557                    )
4558
4559    def draw(self, context):
4560        rd = context.scene.render
4561        layout = self.layout
4562        layout.active = rd.use_freestyle
4563        layout.use_property_split = True
4564        layout.use_property_decorate = False  # No animation.
4565        flow = layout.grid_flow(
4566            row_major=True,
4567            columns=0,
4568            even_columns=True,
4569            even_rows=False,
4570            align=True,
4571        )
4572
4573        flow.prop(rd, "line_thickness_mode", expand=True)
4574
4575        if rd.line_thickness_mode == 'ABSOLUTE':
4576            flow.prop(rd, "line_thickness")
4577
4578        # Warning if the Freestyle SVG Exporter addon is not enabled
4579        if not check_render_freestyle_svg():
4580            # col = box.column()
4581            layout.label(
4582                text="Please enable Freestyle SVG Exporter addon", icon="INFO"
4583            )
4584            # layout.separator()
4585            layout.operator(
4586                "preferences.addon_show",
4587                text="Go to Render: Freestyle SVG Exporter addon",
4588                icon="PREFERENCES",
4589            ).module = "render_freestyle_svg"
4590
4591classes = (
4592    WORLD_PT_POV_world,
4593    WORLD_MT_POV_presets,
4594    WORLD_OT_POV_add_preset,
4595    WORLD_TEXTURE_SLOTS_UL_POV_layerlist,
4596    #WORLD_TEXTURE_SLOTS_UL_List,
4597    WORLD_PT_POV_mist,
4598    # RenderButtonsPanel,
4599    # ModifierButtonsPanel,
4600    # MaterialButtonsPanel,
4601    # TextureButtonsPanel,
4602    # ObjectButtonsPanel,
4603    # CameraDataButtonsPanel,
4604    # WorldButtonsPanel,
4605    # TextButtonsPanel,
4606    # PovDataButtonsPanel,
4607    DATA_PT_POV_normals,
4608    DATA_PT_POV_texture_space,
4609    DATA_PT_POV_vertex_groups,
4610    DATA_PT_POV_shape_keys,
4611    DATA_PT_POV_uv_texture,
4612    DATA_PT_POV_vertex_colors,
4613    DATA_PT_POV_customdata,
4614    # PovLampButtonsPanel,
4615    LIGHT_PT_POV_preview,
4616    LIGHT_PT_POV_light,
4617    LIGHT_MT_POV_presets,
4618    LIGHT_OT_POV_add_preset,
4619    OBJECT_PT_POV_rainbow,
4620    RENDER_PT_POV_export_settings,
4621    RENDER_PT_POV_render_settings,
4622    RENDER_PT_POV_photons,
4623    RENDER_PT_POV_antialias,
4624    RENDER_PT_POV_radiosity,
4625    RENDER_PT_POV_filter,
4626    POV_RADIOSITY_MT_presets,
4627    RENDER_OT_POV_radiosity_add_preset,
4628    RENDER_PT_POV_media,
4629    MODIFIERS_PT_POV_modifiers,
4630    MATERIAL_PT_POV_sss,
4631    MATERIAL_MT_POV_sss_presets,
4632    MATERIAL_OT_POV_sss_add_preset,
4633    MATERIAL_PT_strand,
4634    MATERIAL_PT_POV_activate_node,
4635    MATERIAL_PT_POV_active_node,
4636    MATERIAL_PT_POV_specular,
4637    MATERIAL_PT_POV_mirror,
4638    MATERIAL_PT_POV_transp,
4639    MATERIAL_PT_POV_reflection,
4640    # MATERIAL_PT_POV_interior,
4641    MATERIAL_PT_POV_fade_color,
4642    MATERIAL_PT_POV_caustics,
4643    MATERIAL_PT_POV_replacement_text,
4644    TEXTURE_MT_POV_specials,
4645    TEXTURE_PT_POV_context_texture,
4646    TEXTURE_PT_POV_type,
4647    TEXTURE_PT_POV_preview,
4648    TEXTURE_PT_POV_parameters,
4649    TEXTURE_PT_POV_tex_gamma,
4650    OBJECT_PT_POV_obj_parameters,
4651    OBJECT_PT_POV_obj_sphere,
4652    OBJECT_PT_POV_obj_cylinder,
4653    OBJECT_PT_POV_obj_cone,
4654    OBJECT_PT_POV_obj_superellipsoid,
4655    OBJECT_PT_POV_obj_torus,
4656    OBJECT_PT_POV_obj_supertorus,
4657    OBJECT_PT_POV_obj_parametric,
4658    OBJECT_PT_povray_replacement_text,
4659    VIEW_MT_POV_primitives_add,
4660    VIEW_MT_POV_Basic_Shapes,
4661    VIEW_MT_POV_import,
4662    NODE_MT_POV_map_create,
4663    CAMERA_PT_POV_cam_dof,
4664    CAMERA_PT_POV_cam_nor,
4665    CAMERA_PT_POV_replacement_text,
4666    TEXT_OT_POV_insert,
4667    TEXT_MT_POV_insert,
4668    TEXT_PT_POV_custom_code,
4669    TEXT_MT_POV_templates,
4670    #TEXTURE_PT_POV_povray_texture_slots,
4671    #TEXTURE_UL_POV_texture_slots,
4672    MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist,
4673    TEXTURE_OT_POV_texture_slot_add,
4674    TEXTURE_OT_POV_texture_slot_remove,
4675    TEXTURE_PT_POV_influence,
4676    TEXTURE_PT_POV_mapping,
4677)
4678
4679
4680def register():
4681    # from bpy.utils import register_class
4682
4683    for cls in classes:
4684        register_class(cls)
4685
4686    bpy.types.VIEW3D_MT_add.prepend(menu_func_add)
4687    bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
4688    bpy.types.TEXT_MT_templates.append(menu_func_templates)
4689    bpy.types.RENDER_PT_POV_radiosity.prepend(rad_panel_func)
4690    bpy.types.LIGHT_PT_POV_light.prepend(light_panel_func)
4691    # bpy.types.WORLD_PT_POV_world.prepend(world_panel_func)
4692    # was used for parametric objects but made the other addon unreachable on
4693    # unregister for other tools to use created a user action call instead
4694    # addon_utils.enable("add_mesh_extra_objects", default_set=False, persistent=True)
4695    # bpy.types.TEXTURE_PT_context_texture.prepend(TEXTURE_PT_POV_type)
4696
4697    if not povCentricWorkspace in bpy.app.handlers.load_post:
4698        # print("Adding POV wentric workspace on load handlers list")
4699        bpy.app.handlers.load_post.append(povCentricWorkspace)
4700
4701def unregister():
4702    if povCentricWorkspace in bpy.app.handlers.load_post:
4703        # print("Removing POV wentric workspace from load handlers list")
4704        bpy.app.handlers.load_post.remove(povCentricWorkspace)
4705
4706    # from bpy.utils import unregister_class
4707
4708    # bpy.types.TEXTURE_PT_context_texture.remove(TEXTURE_PT_POV_type)
4709    # addon_utils.disable("add_mesh_extra_objects", default_set=False)
4710    # bpy.types.WORLD_PT_POV_world.remove(world_panel_func)
4711    bpy.types.LIGHT_PT_POV_light.remove(light_panel_func)
4712    bpy.types.RENDER_PT_POV_radiosity.remove(rad_panel_func)
4713    bpy.types.TEXT_MT_templates.remove(menu_func_templates)
4714    bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
4715    bpy.types.VIEW3D_MT_add.remove(menu_func_add)
4716
4717    for cls in reversed(classes):
4718        if cls != TEXTURE_PT_context:
4719            unregister_class(cls)
4720