Cleanup: trailing space
[blender-addons.git] / render_povray / ui.py
blob297c2e0d85c7c13dce39aa6371a4a4f9c8f7b292
1 # ##### BEGIN GPL LICENSE BLOCK #####
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.
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.
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.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
20 """User interface for the POV tools"""
22 import bpy
23 import sys # really import here and in render.py?
24 import os # really import here and in render.py?
25 import addon_utils
26 from time import sleep
27 from os.path import isfile
28 from bpy.app.handlers import persistent
29 from bl_operators.presets import AddPresetBase
30 from bpy.utils import register_class, unregister_class
31 from bpy.types import (
32 Operator,
33 Menu,
34 UIList,
35 Panel,
36 Brush,
37 Material,
38 Light,
39 World,
40 ParticleSettings,
41 FreestyleLineStyle,
44 # Example of wrapping every class 'as is'
45 from bl_ui import properties_output
47 for member in dir(properties_output):
48 subclass = getattr(properties_output, member)
49 try:
50 subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
51 except:
52 pass
53 del properties_output
55 from bl_ui import properties_freestyle
56 for 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
65 del properties_freestyle
67 from bl_ui import properties_view_layer
69 for 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
75 del properties_view_layer
77 # Use some of the existing buttons.
78 from bl_ui import properties_render
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')
85 del properties_render
88 # Use only a subset of the world panels
89 from bl_ui import properties_world
91 # TORECREATE##DEPRECATED#properties_world.WORLD_PT_preview.COMPAT_ENGINES.add('POVRAY_RENDER')
92 properties_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')
95 del properties_world
98 # Example of wrapping every class 'as is'
99 from bl_ui import properties_texture
100 from bl_ui.properties_texture import context_tex_datablock
101 from bl_ui.properties_texture import texture_filter_common
103 for member in dir(properties_texture):
104 subclass = getattr(properties_texture, member)
105 try:
106 subclass.COMPAT_ENGINES.add('POVRAY_RENDER')
107 except:
108 pass
109 del properties_texture
111 # Physics Main wrapping every class 'as is'
112 from bl_ui import properties_physics_common
114 for 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
120 del properties_physics_common
122 # Physics Rigid Bodies wrapping every class 'as is'
123 from bl_ui import properties_physics_rigidbody
125 for 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
131 del properties_physics_rigidbody
133 # Physics Rigid Body Constraint wrapping every class 'as is'
134 from bl_ui import properties_physics_rigidbody_constraint
136 for 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
142 del properties_physics_rigidbody_constraint
144 # Physics Smoke wrapping every class 'as is'
145 from bl_ui import properties_physics_fluid
147 for 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
153 del properties_physics_fluid
155 # Physics softbody wrapping every class 'as is'
156 from bl_ui import properties_physics_softbody
158 for 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
164 del properties_physics_softbody
166 # Physics Fluid wrapping every class 'as is'
167 from bl_ui import properties_physics_fluid
169 for 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
175 del properties_physics_fluid
177 # Physics Field wrapping every class 'as is'
178 from bl_ui import properties_physics_field
180 for 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
186 del properties_physics_field
188 # Physics Cloth wrapping every class 'as is'
189 from bl_ui import properties_physics_cloth
191 for 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
197 del properties_physics_cloth
199 # Physics Dynamic Paint wrapping every class 'as is'
200 from bl_ui import properties_physics_dynamicpaint
202 for 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
208 del properties_physics_dynamicpaint
211 # Example of wrapping every class 'as is'
212 from bl_ui import properties_data_modifier
214 for 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
220 del properties_data_modifier
222 # Example of wrapping every class 'as is' except some
223 from bl_ui import properties_material
225 for 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
235 del properties_material
238 from bl_ui import properties_data_camera
240 for 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
246 del properties_data_camera
249 from bl_ui import properties_particle as properties_particle
251 for 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
259 del properties_particle
262 ############# POV-Centric WORSPACE #############
263 @persistent
264 def povCentricWorkspace(dummy):
265 """Set up a POV centric Workspace if addon was activated and saved as default renderer
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.
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
285 override = bpy.context.copy()
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)
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
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')
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')
325 break
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')
338 #bpy.ops.screen.area_join(override, cursor=(area.x, area.y + area.height))
340 break
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)
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'
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
377 bpy.ops.view3d.camera_to_view(context_override)
381 else:
382 print("default 'Scripting' workspace needed for POV centric Workspace")
390 class 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
397 class WORLD_OT_POV_add_preset(AddPresetBase, Operator):
398 """Add a World Preset"""
400 bl_idname = "object.world_preset_add"
401 bl_label = "Add World Preset"
402 preset_menu = "WORLD_MT_POV_presets"
404 # variable used for all preset values
405 preset_defines = ["scene = bpy.context.scene"]
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",
427 # where to store the preset
428 preset_subdir = "pov/world"
431 def 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
443 def 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
450 def check_add_mesh_extra_objects():
451 """Test if Add mesh extra objects addon is activated
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
456 if "add_mesh_extra_objects" in bpy.context.preferences.addons.keys():
457 return True
458 return False
460 def check_render_freestyle_svg():
461 """Test if Freestyle SVG Exporter addon is activated
463 This addon is currently used to generate the SVG lines file
464 when Freestyle is enabled alongside POV
466 if "render_freestyle_svg" in bpy.context.preferences.addons.keys():
467 return True
468 return False
470 def locate_docpath():
471 """POV can be installed with some include files.
473 Get their path as defined in user preferences or registry keys for
474 the user to be able to invoke them."""
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
488 # Windows Only
489 if sys.platform[:3] == "win":
490 import winreg
492 try:
493 win_reg_key = winreg.OpenKey(
494 winreg.HKEY_CURRENT_USER, "Software\\POV-Ray\\v3.7\\Windows"
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"
505 os_path_ls = os.getenv("PATH").split(':') + [""]
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 ""
514 def pov_context_tex_datablock(context):
515 """Texture context type recreated as deprecated in blender 2.8"""
517 idblock = context.brush
518 if idblock and context.scene.texture_context == 'OTHER':
519 return idblock
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
526 idblock = context.scene.world
527 if idblock and context.scene.texture_context == 'WORLD':
528 return idblock
530 idblock = context.light
531 if idblock and context.scene.texture_context == 'LIGHT':
532 return idblock
534 if context.particle_system and context.scene.texture_context == 'PARTICLES':
535 idblock = context.particle_system.settings
537 return idblock
539 idblock = context.line_style
540 if idblock and context.scene.texture_context == 'LINESTYLE':
541 return idblock
544 class RenderButtonsPanel:
545 """Use this class to define buttons from the render tab of
546 properties window."""
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
553 @classmethod
554 def poll(cls, context):
555 rd = context.scene.render
556 return rd.engine in cls.COMPAT_ENGINES
559 class ModifierButtonsPanel:
560 """Use this class to define buttons from the modifier tab of
561 properties window."""
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
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)
575 class MaterialButtonsPanel:
576 """Use this class to define buttons from the material tab of
577 properties window."""
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
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)
591 class TextureButtonsPanel:
592 """Use this class to define buttons from the texture tab of
593 properties window."""
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
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)
607 # class TextureTypePanel(TextureButtonsPanel):
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))
616 class ObjectButtonsPanel:
617 """Use this class to define buttons from the object tab of
618 properties window."""
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
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)
632 class CameraDataButtonsPanel:
633 """Use this class to define buttons from the camera data tab of
634 properties window."""
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
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)
648 class WorldButtonsPanel:
649 """Use this class to define buttons from the world tab of
650 properties window."""
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
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)
664 class TextButtonsPanel:
665 """Use this class to define buttons from the side tab of
666 text window."""
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
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)
680 from bl_ui import properties_data_mesh
682 # These panels are kept
683 properties_data_mesh.DATA_PT_custom_props_mesh.COMPAT_ENGINES.add(
684 'POVRAY_RENDER'
686 properties_data_mesh.DATA_PT_context_mesh.COMPAT_ENGINES.add('POVRAY_RENDER')
688 ## make some native panels contextual to some object variable
689 ## by recreating custom panels inheriting their properties
692 class PovDataButtonsPanel(properties_data_mesh.MeshButtonsPanel):
693 """Use this class to define buttons from the edit data tab of
694 properties window."""
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',
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
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. ;)
728 class DATA_PT_POV_normals(PovDataButtonsPanel, Panel):
729 bl_label = properties_data_mesh.DATA_PT_normals.bl_label
731 draw = properties_data_mesh.DATA_PT_normals.draw
734 class 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
738 draw = properties_data_mesh.DATA_PT_texture_space.draw
741 class DATA_PT_POV_vertex_groups(PovDataButtonsPanel, Panel):
742 bl_label = properties_data_mesh.DATA_PT_vertex_groups.bl_label
744 draw = properties_data_mesh.DATA_PT_vertex_groups.draw
747 class DATA_PT_POV_shape_keys(PovDataButtonsPanel, Panel):
748 bl_label = properties_data_mesh.DATA_PT_shape_keys.bl_label
750 draw = properties_data_mesh.DATA_PT_shape_keys.draw
753 class DATA_PT_POV_uv_texture(PovDataButtonsPanel, Panel):
754 bl_label = properties_data_mesh.DATA_PT_uv_texture.bl_label
756 draw = properties_data_mesh.DATA_PT_uv_texture.draw
759 class DATA_PT_POV_vertex_colors(PovDataButtonsPanel, Panel):
760 bl_label = properties_data_mesh.DATA_PT_vertex_colors.bl_label
762 draw = properties_data_mesh.DATA_PT_vertex_colors.draw
765 class 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
771 del properties_data_mesh
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################################
785 from bl_ui import properties_data_light
787 # These panels are kept
788 properties_data_light.DATA_PT_custom_props_light.COMPAT_ENGINES.add(
789 'POVRAY_RENDER'
791 properties_data_light.DATA_PT_context_light.COMPAT_ENGINES.add('POVRAY_RENDER')
793 ## make some native panels contextual to some object variable
794 ## by recreating custom panels inheriting their properties
795 class PovLampButtonsPanel(properties_data_light.DataButtonsPanel):
796 """Use this class to define buttons from the light data tab of
797 properties window."""
799 COMPAT_ENGINES = {'POVRAY_RENDER'}
800 POV_OBJECT_TYPES = {'RAINBOW'}
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
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. ;)
819 class LIGHT_PT_POV_preview(PovLampButtonsPanel, Panel):
820 bl_label = properties_data_light.DATA_PT_preview.bl_label
822 draw = properties_data_light.DATA_PT_preview.draw
825 class LIGHT_PT_POV_light(PovLampButtonsPanel, Panel):
826 bl_label = properties_data_light.DATA_PT_light.bl_label
828 draw = properties_data_light.DATA_PT_light.draw
831 class LIGHT_MT_POV_presets(Menu):
832 """Use this class to define preset menu for pov lights."""
834 bl_label = "Lamp Presets"
835 preset_subdir = "pov/light"
836 preset_operator = "script.execute_preset"
837 draw = bpy.types.Menu.draw_preset
840 class LIGHT_OT_POV_add_preset(AddPresetBase, Operator):
841 """Use this class to define pov world buttons"""
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"
848 # variable used for all preset values
849 preset_defines = ["lightdata = bpy.context.object.data"]
851 # properties to store in the preset
852 preset_values = ["lightdata.type", "lightdata.color"]
854 # where to store the preset
855 preset_subdir = "pov/light"
858 # Draw into the existing light panel
859 def light_panel_func(self, context):
860 layout = self.layout
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
870 '''#TORECREATE##DEPRECATED#
871 class LIGHT_PT_POV_sunsky(PovLampButtonsPanel, Panel):
872 bl_label = properties_data_light.DATA_PT_sunsky.bl_label
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)
880 draw = properties_data_light.DATA_PT_sunsky.draw
885 class LIGHT_PT_POV_shadow(PovLampButtonsPanel, Panel):
886 bl_label = "Shadow"
887 COMPAT_ENGINES = {'POVRAY_RENDER'}
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)
895 def draw(self, context):
896 layout = self.layout
898 lamp = context.lamp
900 layout.row().prop(lamp, "shadow_method", expand=True)
902 split = layout.split()
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")
911 col = split.column()
913 col.active = (
914 lamp.shadow_method != 'BUFFER_SHADOW'
915 or lamp.shadow_buffer_type != 'DEEP'
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()
926 col = split.column()
927 col.label(text="Form factor sampling:")
929 sub = col.row(align=True)
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")
937 if lamp.shadow_method != 'NOSHADOW':
938 split = layout.split()
940 col = split.column()
941 col.prop(lamp, "shadow_color", text="")
943 col = split.column()
944 col.prop(lamp, "use_shadow_layer", text="This Layer Only")
945 col.prop(lamp, "use_only_shadow")
947 if lamp.shadow_method == 'RAY_SHADOW':
948 split = layout.split()
950 col = split.column()
951 col.label(text="Sampling:")
953 if lamp.type in {'POINT', 'SUN', 'SPOT'}:
954 sub = col.row()
956 sub.prop(lamp, "shadow_ray_samples", text="Samples")
957 sub.prop(lamp, "shadow_soft_size", text="Soft Size")
959 elif lamp.type == 'AREA':
960 sub = col.row(align=True)
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")
970 if lamp.shadow_method == 'NOSHADOW' and lamp.type == 'AREA':
971 split = layout.split()
973 col = split.column()
974 col.label(text="Form factor sampling:")
976 sub = col.row(align=True)
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")
984 if lamp.shadow_method != 'NOSHADOW':
985 split = layout.split()
987 col = split.column()
988 col.prop(lamp, "shadow_color", text="")
990 col = split.column()
991 col.prop(lamp, "use_shadow_layer", text="This Layer Only")
992 col.prop(lamp, "use_only_shadow")
994 if lamp.shadow_method == 'RAY_SHADOW':
995 split = layout.split()
997 col = split.column()
998 col.label(text="Sampling:")
1000 if lamp.type in {'POINT', 'SUN', 'SPOT'}:
1001 sub = col.row()
1003 sub.prop(lamp, "shadow_ray_samples", text="Samples")
1004 sub.prop(lamp, "shadow_soft_size", text="Soft Size")
1006 elif lamp.type == 'AREA':
1007 sub = col.row(align=True)
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")
1015 col.row().prop(lamp, "shadow_ray_sample_method", expand=True)
1017 if lamp.shadow_ray_sample_method == 'ADAPTIVE_QMC':
1018 layout.prop(lamp, "shadow_adaptive_threshold", text="Threshold")
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")
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)
1031 if lamp.shadow_buffer_type in {'REGULAR', 'HALFWAY', 'DEEP'}:
1032 split = layout.split()
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")
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")
1050 elif lamp.shadow_buffer_type == 'IRREGULAR':
1051 layout.prop(lamp, "shadow_buffer_bias", text="Bias")
1053 split = layout.split()
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")
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")
1069 class LIGHT_PT_POV_area(PovLampButtonsPanel, Panel):
1070 bl_label = properties_data_light.DATA_PT_area.bl_label
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)
1078 draw = properties_data_light.DATA_PT_area.draw
1081 class LIGHT_PT_POV_spot(PovLampButtonsPanel, Panel):
1082 bl_label = properties_data_light.DATA_PT_spot.bl_label
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)
1090 draw = properties_data_light.DATA_PT_spot.draw
1093 class 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
1097 @classmethod
1098 def poll(cls, context):
1099 lamp = context.light
1100 engine = context.scene.render.engine
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)
1108 draw = properties_data_light.DATA_PT_falloff_curve.draw
1111 class 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"""
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 (
1124 and obj.pov.object_as == 'RAINBOW'
1125 and (engine in cls.COMPAT_ENGINES)
1128 def draw(self, context):
1129 layout = self.layout
1131 obj = context.object
1133 col = layout.column()
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',
1143 col.label(
1144 text="Rainbow projection angle: " + str(obj.data.spot_size)
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)
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)
1156 else:
1157 col.prop(
1158 obj.pov,
1159 "unlock_parameters",
1160 text="Edit exported parameters",
1161 icon='UNLOCKED',
1163 col.label(text="3D view proxy may get out of synch")
1164 col.active = obj.pov.unlock_parameters
1166 layout.operator(
1167 "pov.cone_update", text="Update", icon="MESH_CONE"
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",
1178 col.prop(obj.pov, "arc_angle")
1179 col.prop(obj.pov, "falloff_angle")
1182 del properties_data_light
1183 ###############################################################################
1186 class WORLD_PT_POV_world(WorldButtonsPanel, Panel):
1187 """Use this class to define pov world buttons"""
1189 bl_label = "World"
1190 COMPAT_ENGINES = {'POVRAY_RENDER'}
1192 def draw(self, context):
1193 layout = self.layout
1195 world = context.world.pov
1197 row = layout.row(align=True)
1198 row.menu(
1199 WORLD_MT_POV_presets.__name__, text=WORLD_MT_POV_presets.bl_label
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
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")
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")
1218 # row = layout.row()
1219 # row.prop(world, "exposure") #Re-implement later as a light multiplier
1220 # row.prop(world, "color_range")
1223 class WORLD_PT_POV_mist(WorldButtonsPanel, Panel):
1224 """Use this class to define pov mist buttons."""
1226 bl_label = "Mist"
1227 bl_options = {'DEFAULT_CLOSED'}
1228 COMPAT_ENGINES = {'POVRAY_RENDER'}
1230 def draw_header(self, context):
1231 world = context.world
1233 self.layout.prop(world.mist_settings, "use_mist", text="")
1235 def draw(self, context):
1236 layout = self.layout
1238 world = context.world
1240 layout.active = world.mist_settings.use_mist
1242 split = layout.split()
1244 col = split.column()
1245 col.prop(world.mist_settings, "intensity")
1246 col.prop(world.mist_settings, "start")
1248 col = split.column()
1249 col.prop(world.mist_settings, "depth")
1250 col.prop(world.mist_settings, "height")
1252 layout.prop(world.mist_settings, "falloff")
1255 class 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'}
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'
1267 else:
1268 self.layout.prop(
1269 scene.pov, "tempfiles_enable", text="", icon='CONSOLE'
1272 def draw(self, context):
1274 layout = self.layout
1276 scene = context.scene
1278 layout.active = scene.pov.max_trace_level != 0
1279 split = layout.split()
1281 col = split.column()
1282 col.label(text="Command line switches:")
1283 col.prop(scene.pov, "command_line_switches", text="")
1284 split = layout.split()
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")
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")
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")
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")
1307 class RENDER_PT_POV_render_settings(RenderButtonsPanel, Panel):
1308 """Use this class to define pov render settings buttons."""
1310 bl_label = "Global Settings"
1311 bl_icon = 'SETTINGS'
1312 bl_options = {'DEFAULT_CLOSED'}
1313 COMPAT_ENGINES = {'POVRAY_RENDER'}
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'
1321 else:
1322 self.layout.prop(
1323 scene.pov,
1324 "global_settings_advanced",
1325 text="",
1326 icon='PREFERENCES',
1329 def draw(self, context):
1330 layout = self.layout
1332 scene = context.scene
1333 rd = context.scene.render
1334 # layout.active = (scene.pov.max_trace_level != 0)
1336 if sys.platform[:3] != "win":
1337 layout.prop(
1338 scene.pov, "sdl_window_enable", text="POV-Ray SDL Window"
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")
1361 split = layout.split()
1362 split.label(text="Shading:")
1363 split = layout.split()
1365 row = split.row(align=align)
1366 row.prop(scene.pov, "use_shadows")
1367 row.prop(scene.pov, "alpha_mode")
1370 class RENDER_PT_POV_photons(RenderButtonsPanel, Panel):
1371 """Use this class to define pov photons buttons."""
1373 bl_label = "Photons"
1374 bl_options = {'DEFAULT_CLOSED'}
1375 COMPAT_ENGINES = {'POVRAY_RENDER'}
1377 # def draw_header(self, context):
1378 # self.layout.label(icon='SETTINGS')
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'
1386 else:
1387 self.layout.prop(
1388 scene.pov, "photon_enable", text="", icon='PMARKER'
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")
1399 split = layout.split()
1401 col = split.column()
1402 col.prop(scene.pov, "photon_spacing", text="Spacing")
1403 col.prop(scene.pov, "photon_gather_min")
1405 col = split.column()
1406 col.prop(scene.pov, "photon_adc_bailout", text="Photon ADC")
1407 col.prop(scene.pov, "photon_gather_max")
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
1421 class RENDER_PT_POV_antialias(RenderButtonsPanel, Panel):
1422 """Use this class to define pov antialiasing buttons."""
1424 bl_label = "Anti-Aliasing"
1425 bl_options = {'DEFAULT_CLOSED'}
1426 COMPAT_ENGINES = {'POVRAY_RENDER'}
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'
1435 self.layout.prop(
1436 scene.pov, "antialias_enable", text="", icon='ERROR'
1438 elif scene.pov.antialias_enable:
1439 self.layout.prop(
1440 scene.pov, "antialias_enable", text="", icon='ANTIALIASED'
1442 else:
1443 self.layout.prop(
1444 scene.pov, "antialias_enable", text="", icon='ALIASED'
1447 def draw(self, context):
1448 prefs = bpy.context.preferences.addons[__package__].preferences
1449 layout = self.layout
1450 scene = context.scene
1452 layout.active = scene.pov.antialias_enable
1454 row = layout.row()
1455 row.prop(scene.pov, "antialias_method", text="")
1457 if (
1458 prefs.branch_feature_set_povray != 'uberpov'
1459 and scene.pov.antialias_method == '2'
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")
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
1480 row = layout.row()
1481 row.prop(scene.pov, "antialias_threshold", text="AA Threshold")
1482 row.prop(scene.pov, "antialias_gamma", text="AA Gamma")
1484 if prefs.branch_feature_set_povray == 'uberpov':
1485 row = layout.row()
1486 row.prop(
1487 scene.pov, "antialias_confidence", text="AA Confidence"
1489 if scene.pov.antialias_method == '2':
1490 row.enabled = True
1491 else:
1492 row.enabled = False
1495 class RENDER_PT_POV_radiosity(RenderButtonsPanel, Panel):
1496 """Use this class to define pov radiosity buttons."""
1498 bl_label = "Diffuse Radiosity"
1499 bl_options = {'DEFAULT_CLOSED'}
1500 COMPAT_ENGINES = {'POVRAY_RENDER'}
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',
1511 else:
1512 self.layout.prop(
1513 scene.pov, "radio_enable", text="", icon='LIGHTPROBE_CUBEMAP'
1516 def draw(self, context):
1517 layout = self.layout
1519 scene = context.scene
1521 layout.active = scene.pov.radio_enable
1523 split = layout.split()
1525 col = split.column()
1526 col.prop(scene.pov, "radio_count", text="Rays")
1527 col.prop(scene.pov, "radio_recursion_limit", text="Recursions")
1529 split.prop(scene.pov, "radio_error_bound", text="Error Bound")
1531 layout.prop(scene.pov, "radio_display_advanced")
1533 if scene.pov.radio_display_advanced:
1534 split = layout.split()
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)
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)
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")
1557 class POV_RADIOSITY_MT_presets(Menu):
1558 """Use this class to define pov radiosity presets menu."""
1560 bl_label = "Radiosity Presets"
1561 preset_subdir = "pov/radiosity"
1562 preset_operator = "script.execute_preset"
1563 draw = bpy.types.Menu.draw_preset
1566 class RENDER_OT_POV_radiosity_add_preset(AddPresetBase, Operator):
1567 """Use this class to define pov radiosity add presets button"""
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"
1574 # variable used for all preset values
1575 preset_defines = ["scene = bpy.context.scene"]
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",
1598 # where to store the preset
1599 preset_subdir = "pov/radiosity"
1602 # Draw into an existing panel
1603 def rad_panel_func(self, context):
1604 layout = self.layout
1606 row = layout.row(align=True)
1607 row.menu(
1608 POV_RADIOSITY_MT_presets.__name__,
1609 text=POV_RADIOSITY_MT_presets.bl_label,
1611 row.operator(
1612 RENDER_OT_POV_radiosity_add_preset.bl_idname, text="", icon='ADD'
1614 row.operator(
1615 RENDER_OT_POV_radiosity_add_preset.bl_idname, text="", icon='REMOVE'
1616 ).remove_active = True
1619 class RENDER_PT_POV_media(WorldButtonsPanel, Panel):
1620 """Use this class to define a pov global atmospheric media buttons."""
1622 bl_label = "Atmosphere Media"
1623 COMPAT_ENGINES = {'POVRAY_RENDER'}
1625 def draw_header(self, context):
1626 scene = context.scene
1628 self.layout.prop(scene.pov, "media_enable", text="")
1630 def draw(self, context):
1631 layout = self.layout
1633 scene = context.scene
1635 layout.active = scene.pov.media_enable
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")
1655 ##class RENDER_PT_povray_baking(RenderButtonsPanel, Panel):
1656 ## bl_label = "Baking"
1657 ## COMPAT_ENGINES = {'POVRAY_RENDER'}
1659 ## def draw_header(self, context):
1660 ## scene = context.scene
1662 ## self.layout.prop(scene.pov, "baking_enable", text="")
1664 ## def draw(self, context):
1665 ## layout = self.layout
1667 ## scene = context.scene
1668 ## rd = scene.render
1670 ## layout.active = scene.pov.baking_enable
1673 class MODIFIERS_PT_POV_modifiers(ModifierButtonsPanel, Panel):
1674 """Use this class to define pov modifier buttons. (For booleans)"""
1676 bl_label = "POV-Ray"
1677 COMPAT_ENGINES = {'POVRAY_RENDER'}
1679 # def draw_header(self, context):
1680 # scene = context.scene
1681 # self.layout.prop(scene.pov, "boolean_mod", text="")
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
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")
1705 class MATERIAL_MT_POV_sss_presets(Menu):
1706 """Use this class to define pov sss preset menu."""
1708 bl_label = "SSS Presets"
1709 preset_subdir = "pov/material/sss"
1710 preset_operator = "script.execute_preset"
1711 draw = bpy.types.Menu.draw_preset
1714 class MATERIAL_OT_POV_sss_add_preset(AddPresetBase, Operator):
1715 """Add an SSS Preset"""
1717 bl_idname = "material.sss_preset_add"
1718 bl_label = "Add SSS Preset"
1719 preset_menu = "MATERIAL_MT_POV_sss_presets"
1721 # variable used for all preset values
1722 preset_defines = ["material = bpy.context.material"]
1724 # properties to store in the preset
1725 preset_values = [
1726 "material.pov_subsurface_scattering.radius",
1727 "material.pov_subsurface_scattering.color",
1730 # where to store the preset
1731 preset_subdir = "pov/material/sss"
1734 class MATERIAL_PT_POV_sss(MaterialButtonsPanel, Panel):
1735 """Use this class to define pov sss buttons panel."""
1737 bl_label = "Subsurface Scattering"
1738 bl_options = {'DEFAULT_CLOSED'}
1739 COMPAT_ENGINES = {'POVRAY_RENDER'}
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)
1751 def draw_header(self, context):
1752 mat = context.material # FORMERLY : #active_node_mat(context.material)
1753 sss = mat.pov_subsurface_scattering
1755 self.layout.active = not mat.pov.use_shadeless
1756 self.layout.prop(sss, "use", text="")
1758 def draw(self, context):
1759 layout = self.layout
1761 mat = context.material # FORMERLY : #active_node_mat(context.material)
1762 sss = mat.pov_subsurface_scattering
1764 layout.active = (sss.use) and (not mat.pov.use_shadeless)
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,
1772 sub.operator(
1773 MATERIAL_OT_POV_sss_add_preset.bl_idname, text="", icon='ADD'
1775 sub.operator(
1776 MATERIAL_OT_POV_sss_add_preset.bl_idname, text="", icon='REMOVE'
1777 ).remove_active = True
1779 split = layout.split()
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)
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")
1799 class MATERIAL_PT_POV_activate_node(MaterialButtonsPanel, Panel):
1800 """Use this class to define an activate pov nodes button."""
1802 bl_label = "Activate Node Settings"
1803 bl_context = "material"
1804 bl_options = {'HIDE_HEADER'}
1805 COMPAT_ENGINES = {'POVRAY_RENDER'}
1807 @classmethod
1808 def poll(cls, context):
1809 engine = context.scene.render.engine
1810 mat = context.material
1811 ob = context.object
1812 return (
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)
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"
1828 class MATERIAL_PT_POV_active_node(MaterialButtonsPanel, Panel):
1829 """Use this class to show pov active node properties buttons."""
1831 bl_label = "Active Node Settings"
1832 bl_context = "material"
1833 bl_options = {'HIDE_HEADER'}
1834 COMPAT_ENGINES = {'POVRAY_RENDER'}
1836 @classmethod
1837 def poll(cls, context):
1838 engine = context.scene.render.engine
1839 mat = context.material
1840 ob = context.object
1841 return (
1843 and mat.pov.type == "SURFACE"
1844 and (engine in cls.COMPAT_ENGINES)
1845 and mat.pov.material_use_nodes
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
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
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!")
1894 class MATERIAL_PT_POV_specular(MaterialButtonsPanel, Panel):
1895 """Use this class to define standard material specularity (highlights) buttons."""
1897 bl_label = "Specular"
1898 COMPAT_ENGINES = {'POVRAY_RENDER'}
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)
1909 def draw(self, context):
1910 layout = self.layout
1912 mat = context.material.pov
1914 layout.active = (not mat.use_shadeless)
1916 split = layout.split()
1918 col = split.column()
1919 col.prop(mat, "specular_color", text="")
1920 col.prop(mat, "specular_intensity", text="Intensity")
1922 col = split.column()
1923 col.prop(mat, "specular_shader", text="")
1924 col.prop(mat, "use_specular_ramp", text="Ramp")
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")
1940 if mat.use_specular_ramp:
1941 layout.separator()
1942 layout.template_color_ramp(mat, "specular_ramp", expand=True)
1943 layout.separator()
1945 row = layout.row()
1946 row.prop(mat, "specular_ramp_input", text="Input")
1947 row.prop(mat, "specular_ramp_blend", text="Blend")
1949 layout.prop(mat, "specular_ramp_factor", text="Factor")
1951 class MATERIAL_PT_POV_mirror(MaterialButtonsPanel, Panel):
1952 """Use this class to define standard material reflectivity (mirror) buttons."""
1954 bl_label = "Mirror"
1955 bl_options = {'DEFAULT_CLOSED'}
1956 bl_idname = "MATERIAL_PT_POV_raytrace_mirror"
1957 COMPAT_ENGINES = {'POVRAY_RENDER'}
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)
1969 def draw_header(self, context):
1970 mat = context.material
1971 raym = mat.pov_raytrace_mirror
1973 self.layout.prop(raym, "use", text="")
1975 def draw(self, context):
1976 layout = self.layout
1978 mat = (
1979 context.material
1980 ) # Formerly : #mat = active_node_mat(context.material)
1981 raym = mat.pov_raytrace_mirror
1983 layout.active = raym.use
1985 split = layout.split()
1987 col = split.column()
1988 col.prop(raym, "reflect_factor")
1989 col.prop(raym, "mirror_color", text="")
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")
1997 split = layout.split()
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="")
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")
2019 class MATERIAL_PT_POV_transp(MaterialButtonsPanel, Panel):
2020 """Use this class to define pov material transparency (alpha) buttons."""
2022 bl_label = "Transparency"
2023 COMPAT_ENGINES = {'POVRAY_RENDER'}
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)
2035 def draw_header(self, context):
2036 mat = context.material
2038 if simple_material(mat):
2039 self.layout.prop(mat.pov, "use_transparency", text="")
2041 def draw(self, context):
2042 layout = self.layout
2044 base_mat = context.material
2045 mat = context.material # FORMERLY active_node_mat(context.material)
2046 rayt = mat.pov_raytrace_transparency
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)
2053 split = layout.split()
2054 split.active = base_mat.pov.use_transparency
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
2062 row.prop(mat.pov, "specular_alpha", text="Specular")
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")
2071 if base_mat.pov.transparency_method == 'RAYTRACE':
2072 layout.separator()
2073 split = layout.split()
2074 split.active = base_mat.pov.use_transparency
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")
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")
2092 class MATERIAL_PT_POV_reflection(MaterialButtonsPanel, Panel):
2093 """Use this class to define more pov specific reflectivity buttons."""
2095 bl_label = "POV-Ray Reflection"
2096 bl_parent_id = "MATERIAL_PT_POV_raytrace_mirror"
2097 COMPAT_ENGINES = {'POVRAY_RENDER'}
2099 @classmethod
2100 def poll(cls, context):
2101 engine = context.scene.render.engine
2102 mat = context.material
2103 ob = context.object
2104 return (
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)
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()
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")
2136 #group some native Blender (SSS) and POV (Fade)settings under such a parent panel?
2137 class 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)
2150 def draw_header(self, context):
2151 mat = context.material
2155 class MATERIAL_PT_POV_fade_color(MaterialButtonsPanel, Panel):
2156 """Use this class to define pov fading (absorption) color buttons."""
2158 bl_label = "POV-Ray Absorption"
2159 COMPAT_ENGINES = {'POVRAY_RENDER'}
2160 # bl_parent_id = "material.pov_interior"
2162 @classmethod
2163 def poll(cls, context):
2164 engine = context.scene.render.engine
2165 mat = context.material
2166 ob = context.object
2167 return (
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)
2174 def draw_header(self, context):
2175 mat = context.material
2177 self.layout.prop(mat.pov, "interior_fade_color", text="")
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")
2188 pass
2191 class MATERIAL_PT_POV_caustics(MaterialButtonsPanel, Panel):
2192 """Use this class to define pov caustics buttons."""
2194 bl_label = "Caustics"
2195 COMPAT_ENGINES = {'POVRAY_RENDER'}
2197 @classmethod
2198 def poll(cls, context):
2199 engine = context.scene.render.engine
2200 mat = context.material
2201 ob = context.object
2202 return (
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)
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"
2215 else:
2216 self.layout.prop(
2217 mat.pov, "caustics_enable", text="", icon="PMARKER"
2220 def draw(self, context):
2222 layout = self.layout
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:
2231 col.prop(mat.pov, "refraction_type", text="")
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")
2240 if (
2241 not mat.pov.refraction_caustics
2242 and not mat.pov.photons_reflection
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 !")
2250 class MATERIAL_PT_strand(MaterialButtonsPanel, Panel):
2251 """Use this class to define Blender strand antialiasing buttons."""
2253 bl_label = "Strand"
2254 bl_options = {'DEFAULT_CLOSED'}
2255 COMPAT_ENGINES = {'POVRAY_RENDER'}
2257 @classmethod
2258 def poll(cls, context):
2259 mat = context.material
2260 engine = context.scene.render.engine
2261 return (
2263 and (mat.pov.type in {'SURFACE', 'WIRE', 'HALO'})
2264 and (engine in cls.COMPAT_ENGINES)
2267 def draw(self, context):
2268 layout = self.layout
2270 mat = context.material # don't use node material
2271 tan = mat.strand
2273 split = layout.split()
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")
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=""
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")
2305 class MATERIAL_PT_POV_replacement_text(MaterialButtonsPanel, Panel):
2306 """Use this class to define pov custom code declared name field."""
2308 bl_label = "Custom POV Code"
2309 COMPAT_ENGINES = {'POVRAY_RENDER'}
2311 def draw(self, context):
2312 layout = self.layout
2314 mat = context.material
2316 col = layout.column()
2317 col.label(text="Replace properties with:")
2318 col.prop(mat.pov, "replacement_text", text="")
2321 class TEXTURE_MT_POV_specials(Menu):
2322 """Use this class to define pov texture slot operations buttons."""
2324 bl_label = "Texture Specials"
2325 COMPAT_ENGINES = {'POVRAY_RENDER'}
2327 def draw(self, context):
2328 layout = self.layout
2330 layout.operator("texture.slot_copy", icon='COPYDOWN')
2331 layout.operator("texture.slot_paste", icon='PASTEDOWN')
2334 class WORLD_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
2335 """Use this class to show pov texture slots list.""" # XXX Not used yet
2337 index: bpy.props.IntProperty(name='index')
2338 def draw_item(
2339 self, context, layout, data, item, icon, active_data, active_propname
2341 world = context.scene.world # .pov
2342 active_data = world.pov
2343 # tex = context.texture #may be needed later?
2345 # We could write some code to decide which icon to use here...
2346 custom_icon = 'TEXTURE'
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'
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)
2369 class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
2370 """Use this class to show pov texture slots list."""
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
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'
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)
2398 # Rewrite an existing class to modify.
2399 # register but not unregistered because
2400 # the modified parts concern only POVRAY_RENDER
2401 class 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'}
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')
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
2422 col = layout.column()
2424 if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
2425 pin_id = None
2427 if not pin_id:
2428 col.template_texture_user()
2430 if user or pin_id:
2431 col.separator()
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")
2439 if tex:
2440 col.separator()
2442 split = col.split(factor=0.2)
2443 split.label(text="Type")
2444 split.prop(tex, "type", text="")
2446 class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
2447 """Use this class to show pov texture context buttons."""
2449 bl_label = ""
2450 bl_options = {'HIDE_HEADER'}
2451 COMPAT_ENGINES = {'POVRAY_RENDER'}
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)
2470 def draw(self, context):
2471 layout = self.layout
2473 scene = context.scene
2474 mat = context.view_layer.objects.active.active_material
2475 wld = context.scene.world
2477 layout.prop(scene, "texture_context", expand=True)
2478 if scene.texture_context == 'MATERIAL' and mat is not None:
2480 row = layout.row()
2481 row.template_list(
2482 "MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist",
2484 mat,
2485 "pov_texture_slots",
2486 mat.pov,
2487 "active_texture_index",
2488 rows=2,
2489 maxrows=16,
2490 type="DEFAULT"
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()
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")
2511 layout.prop_search(
2512 slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
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
2521 if tex:
2522 layout.separator()
2523 split = layout.split(factor=0.2)
2524 split.label(text="Type")
2525 split.prop(tex, "type", text="")
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:
2532 row = layout.row()
2533 row.template_list(
2534 "WORLD_TEXTURE_SLOTS_UL_POV_layerlist",
2536 wld,
2537 "pov_texture_slots",
2538 wld.pov,
2539 "active_texture_index",
2540 rows=2,
2541 maxrows=16,
2542 type="DEFAULT"
2544 col = row.column(align=True)
2545 col.operator("pov.textureslotadd", icon='ADD', text='')
2546 col.operator("pov.textureslotremove", icon='REMOVE', text='')
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()
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")
2564 layout.prop_search(
2565 slot, 'texture_search', bpy.data, 'textures', text='', icon='TEXTURE'
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
2574 if tex:
2575 layout.separator()
2576 split = layout.split(factor=0.2)
2577 split.label(text="Type")
2578 split.prop(tex, "type", text="")
2580 # Commented out below is a reminder of what existed in Blender Internal
2581 # attributes need to be recreated
2583 slot = getattr(context, "texture_slot", None)
2584 node = getattr(context, "texture_node", None)
2585 space = context.space_data
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
2599 #idblock = context.particle_system.settings
2601 tex = getattr(context, "texture", None)
2602 if tex != None:
2603 spacedependant = tex
2607 scene = context.scene
2608 idblock = scene.pov#pov_context_tex_datablock(context)
2609 pin_id = space.pin_id
2611 #spacedependant.use_limited_texture_context = True
2613 if space.use_pin_id and not isinstance(pin_id, Texture):
2614 idblock = id_tex_datablock(pin_id)
2615 pin_id = None
2617 if not space.use_pin_id:
2618 layout.row().prop(spacedependant, "texture_context", expand=True)
2619 pin_id = None
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()
2628 row = layout.row()
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")
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
2647 tex_collection = (pin_id is None) and (node is None) and (spacedependant.texture_context not in ('LINESTYLE','OTHER'))
2649 if tex_collection:
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()
2658 row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots",
2659 idblock, "active_texture_index", rows=2, maxrows=16, type="DEFAULT")
2661 # row.template_list("WORLD_TEXTURE_SLOTS_UL_List", "texture_slots", world,
2662 # world.texture_slots, world, "active_texture_index", rows=2)
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="")
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")
2676 if pin_id:
2677 layout.template_ID(space, "pin_id")
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:")
2690 class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
2691 """Use this class to show pov color ramps."""
2693 bl_label = "Colors"
2694 bl_options = {'DEFAULT_CLOSED'}
2695 COMPAT_ENGINES = {'POVRAY_RENDER'}
2697 def draw(self, context):
2698 layout = self.layout
2700 tex = context.texture
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)
2706 split = layout.split()
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")
2715 col = split.column()
2716 col.label(text="Adjust:")
2717 col.prop(tex, "intensity")
2718 col.prop(tex, "contrast")
2719 col.prop(tex, "saturation")
2721 col = layout.column()
2722 col.prop(tex, "use_clamp", text="Clamp")
2725 # Texture Slot Panels #
2728 class TEXTURE_OT_POV_texture_slot_add(Operator):
2729 """Use this class for the add texture slot button."""
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'}
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)
2752 #for area in bpy.context.screen.areas:
2753 #if area.type in ['PROPERTIES']:
2754 #area.tag_redraw()
2757 return {'FINISHED'}
2760 class TEXTURE_OT_POV_texture_slot_remove(Operator):
2761 """Use this class for the remove texture slot button."""
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'}
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]
2785 return {'FINISHED'}
2787 class TextureSlotPanel(TextureButtonsPanel):
2788 """Use this class to show pov texture slots panel."""
2790 COMPAT_ENGINES = {'POVRAY_RENDER'}
2792 @classmethod
2793 def poll(cls, context):
2794 if not hasattr(context, "pov_texture_slot"):
2795 return False
2797 engine = context.scene.render.engine
2798 return TextureButtonsPanel.poll(cls, context) and (
2799 engine in cls.COMPAT_ENGINES
2803 class TEXTURE_PT_POV_type(TextureButtonsPanel, Panel):
2804 """Use this class to define pov texture type buttons."""
2806 bl_label = "POV Textures"
2807 COMPAT_ENGINES = {'POVRAY_RENDER'}
2808 bl_options = {'HIDE_HEADER'}
2810 def draw(self, context):
2811 layout = self.layout
2812 world = context.world
2813 tex = context.texture
2815 split = layout.split(factor=0.2)
2816 split.label(text="Pattern")
2817 split.prop(tex.pov, "tex_pattern_type", text="")
2819 # row = layout.row()
2820 # row.template_list("WORLD_TEXTURE_SLOTS_UL_List", "texture_slots", world,
2821 # world.texture_slots, world, "active_texture_index")
2824 class TEXTURE_PT_POV_preview(TextureButtonsPanel, Panel):
2825 """Use this class to define pov texture preview panel."""
2827 bl_label = "Preview"
2828 COMPAT_ENGINES = {'POVRAY_RENDER'}
2829 bl_options = {'HIDE_HEADER'}
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 (
2840 and (tex.pov.tex_pattern_type != 'emulator')
2841 and (engine in cls.COMPAT_ENGINES)
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)
2857 class TEXTURE_PT_POV_parameters(TextureButtonsPanel, Panel):
2858 """Use this class to define pov texture pattern buttons."""
2860 bl_label = "POV Pattern Options"
2861 bl_options = {'HIDE_HEADER'}
2862 COMPAT_ENGINES = {'POVRAY_RENDER'}
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"
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'
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"
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"
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",
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",
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",
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",
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",
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",
3047 func = 6
3048 if tex.pov.func_list in {
3049 "f_helix1",
3050 "f_helix2",
3051 "f_piriform_2d",
3052 "f_strophoid_2d",
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############################
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"
3099 if tex.pov.warp_types not in {"CUBIC", "NONE"}:
3100 layout.prop(
3101 tex.pov, "warp_orientation", text="Warp orientation"
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")
3110 row = layout.row()
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()
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")
3142 class 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'
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
3155 if not getattr(context, "texture_slot", None):
3156 return False
3158 engine = context.scene.render.engine
3159 return (engine in cls.COMPAT_ENGINES)
3161 def draw(self, context):
3162 layout = self.layout
3164 idblock = pov_context_tex_datablock(context)
3166 #tex = context.texture_slot
3167 tex = mat.pov_texture_slots[
3168 mat.active_texture_index
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="")
3177 if tex.texture_coords == 'ORCO':
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="")
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="")
3194 elif tex.texture_coords == 'OBJECT':
3195 split = layout.split(percentage=0.3)
3196 split.label(text="Object:")
3197 split.prop(tex, "object", text="")
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="")
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="")
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="")
3220 elif isinstance(idblock, Material):
3221 split = layout.split(percentage=0.3)
3222 split.label(text="Projection:")
3223 split.prop(tex, "mapping", text="")
3225 split = layout.split()
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()
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="")
3245 row = layout.row()
3246 row.column().prop(tex, "offset")
3247 row.column().prop(tex, "scale")
3249 class TEXTURE_PT_POV_influence(TextureSlotPanel, Panel):
3250 """Use this class to define pov texture influence buttons."""
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
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
3271 engine = context.scene.render.engine
3272 return engine in cls.COMPAT_ENGINES
3274 def draw(self, context):
3276 layout = self.layout
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
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.
3296 if isinstance(idblock, Material):
3297 split = layout.split()
3299 col = split.column()
3300 if idblock.pov.type in {'SURFACE', 'WIRE'}:
3302 split = layout.split()
3304 col = split.column()
3305 col.label(text="Diffuse:")
3306 factor_but(
3307 col, "use_map_diffuse", "diffuse_factor", "Intensity"
3309 factor_but(
3310 col,
3311 "use_map_color_diffuse",
3312 "diffuse_color_factor",
3313 "Color",
3315 factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
3316 factor_but(
3317 col,
3318 "use_map_translucency",
3319 "translucency_factor",
3320 "Translucency",
3323 col.label(text="Specular:")
3324 factor_but(
3325 col, "use_map_specular", "specular_factor", "Intensity"
3327 factor_but(
3328 col, "use_map_color_spec", "specular_color_factor", "Color"
3330 factor_but(
3331 col, "use_map_hardness", "hardness_factor", "Hardness"
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")
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"
3346 sub_tmp.active = (
3347 texslot.use_map_normal or texslot.use_map_displacement
3349 # END XXX
3351 factor_but(col, "use_map_warp", "warp_factor", "Warp")
3352 factor_but(
3353 col,
3354 "use_map_displacement",
3355 "displacement_factor",
3356 "Displace",
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:")
3365 split = layout.split()
3367 col = split.column()
3368 factor_but(
3369 col,
3370 "use_map_color_diffuse",
3371 "diffuse_color_factor",
3372 "Color",
3374 factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
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"
3381 factor_but(
3382 col, "use_map_translucency", "translucency_factor", "Add"
3384 elif idblock.pov.type == 'VOLUME':
3385 layout.label(text="Volume:")
3387 split = layout.split()
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"
3394 factor_but(
3395 col, "use_map_scatter", "scattering_factor", "Scattering"
3397 factor_but(
3398 col, "use_map_reflect", "reflection_factor", "Reflection"
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",
3409 factor_but(
3410 col,
3411 "use_map_color_transmission",
3412 "transmission_color_factor",
3413 "Transmission Color",
3415 factor_but(
3416 col,
3417 "use_map_color_reflection",
3418 "reflection_color_factor",
3419 "Reflection Color",
3422 layout.label(text="Geometry:")
3424 split = layout.split()
3426 col = split.column()
3427 factor_but(col, "use_map_warp", "warp_factor", "Warp")
3429 col = split.column()
3430 factor_but(
3431 col,
3432 "use_map_displacement",
3433 "displacement_factor",
3434 "Displace",
3437 elif isinstance(idblock, Light):
3438 split = layout.split()
3440 col = split.column()
3441 factor_but(col, "use_map_color", "color_factor", "Color")
3443 col = split.column()
3444 factor_but(col, "use_map_shadow", "shadow_factor", "Shadow")
3446 elif isinstance(idblock, World):
3447 split = layout.split()
3449 col = split.column()
3450 factor_but(col, "use_map_blend", "blend_factor", "Blend")
3451 factor_but(col, "use_map_horizon", "horizon_factor", "Horizon")
3453 col = split.column()
3454 factor_but(
3455 col, "use_map_zenith_up", "zenith_up_factor", "Zenith Up"
3457 factor_but(
3458 col, "use_map_zenith_down", "zenith_down_factor", "Zenith Down"
3460 elif isinstance(idblock, ParticleSettings):
3461 split = layout.split()
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")
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")
3477 layout.label(text="Hair:")
3479 split = layout.split()
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")
3486 col = split.column()
3487 factor_but(
3488 col, "use_map_kink_amp", "kink_amp_factor", "Kink Amplitude"
3490 factor_but(
3491 col, "use_map_kink_freq", "kink_freq_factor", "Kink Frequency"
3493 factor_but(col, "use_map_rough", "rough_factor", "Rough")
3495 elif isinstance(idblock, FreestyleLineStyle):
3496 split = layout.split()
3498 col = split.column()
3499 factor_but(
3500 col, "use_map_color_diffuse", "diffuse_color_factor", "Color"
3502 col = split.column()
3503 factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
3505 layout.separator()
3507 if not isinstance(idblock, ParticleSettings):
3508 split = layout.split()
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
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
3520 # if isinstance(idblock, (Material, World)):
3521 # col.prop(tex, "default_value", text="DVar", slider=True)
3524 class TEXTURE_PT_POV_tex_gamma(TextureButtonsPanel, Panel):
3525 """Use this class to define pov texture gamma buttons."""
3527 bl_label = "Image Gamma"
3528 COMPAT_ENGINES = {'POVRAY_RENDER'}
3530 def draw_header(self, context):
3531 tex = context.texture
3533 self.layout.prop(
3534 tex.pov, "tex_gamma_enable", text="", icon='SEQ_LUMA_WAVEFORM'
3537 def draw(self, context):
3538 layout = self.layout
3540 tex = context.texture
3542 layout.active = tex.pov.tex_gamma_enable
3543 layout.prop(tex.pov, "tex_gamma_value", text="Gamma Value")
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'}
3551 # def draw(self, context):
3552 # layout = self.layout
3554 # tex = context.texture
3556 # col = layout.column()
3557 # col.label(text="Replace properties with:")
3558 # col.prop(tex.pov, "replacement_text", text="")
3561 class OBJECT_PT_POV_obj_parameters(ObjectButtonsPanel, Panel):
3562 """Use this class to define pov specific object level options buttons."""
3564 bl_label = "POV"
3565 COMPAT_ENGINES = {'POVRAY_RENDER'}
3567 @classmethod
3568 def poll(cls, context):
3570 engine = context.scene.render.engine
3571 return engine in cls.COMPAT_ENGINES
3573 def draw(self, context):
3574 layout = self.layout
3576 obj = context.object
3578 split = layout.split()
3580 col = split.column(align=True)
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"
3591 split = layout.split()
3593 col = split.column()
3594 col.prop(obj.pov, "hollow")
3595 col.prop(obj.pov, "double_illuminate")
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)
3615 class OBJECT_PT_POV_obj_sphere(PovDataButtonsPanel, Panel):
3616 """Use this class to define pov sphere primitive parameters buttons."""
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 (
3627 and obj.pov.object_as == 'SPHERE'
3628 and (engine in cls.COMPAT_ENGINES)
3631 def draw(self, context):
3632 layout = self.layout
3634 obj = context.object
3636 col = layout.column()
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',
3646 col.label(text="Sphere radius: " + str(obj.pov.sphere_radius))
3648 else:
3649 col.prop(
3650 obj.pov,
3651 "unlock_parameters",
3652 text="Edit exported parameters",
3653 icon='UNLOCKED',
3655 col.label(text="3D view proxy may get out of synch")
3656 col.active = obj.pov.unlock_parameters
3658 layout.operator(
3659 "pov.sphere_update", text="Update", icon="SHADING_RENDERED"
3662 # col.label(text="Parameters:")
3663 col.prop(obj.pov, "sphere_radius", text="Radius of Sphere")
3666 class OBJECT_PT_POV_obj_cylinder(PovDataButtonsPanel, Panel):
3667 """Use this class to define pov cylinder primitive parameters buttons."""
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 (
3678 and obj.pov.object_as == 'CYLINDER'
3679 and (engine in cls.COMPAT_ENGINES)
3682 def draw(self, context):
3683 layout = self.layout
3685 obj = context.object
3687 col = layout.column()
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',
3697 col.label(
3698 text="Cylinder radius: " + str(obj.pov.cylinder_radius)
3700 col.label(
3701 text="Cylinder cap location: "
3702 + str(obj.pov.cylinder_location_cap)
3705 else:
3706 col.prop(
3707 obj.pov,
3708 "unlock_parameters",
3709 text="Edit exported parameters",
3710 icon='UNLOCKED',
3712 col.label(text="3D view proxy may get out of synch")
3713 col.active = obj.pov.unlock_parameters
3715 layout.operator(
3716 "pov.cylinder_update", text="Update", icon="MESH_CYLINDER"
3719 # col.label(text="Parameters:")
3720 col.prop(obj.pov, "cylinder_radius")
3721 col.prop(obj.pov, "cylinder_location_cap")
3724 class OBJECT_PT_POV_obj_cone(PovDataButtonsPanel, Panel):
3725 """Use this class to define pov cone primitive parameters buttons."""
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 (
3736 and obj.pov.object_as == 'CONE'
3737 and (engine in cls.COMPAT_ENGINES)
3740 def draw(self, context):
3741 layout = self.layout
3743 obj = context.object
3745 col = layout.column()
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',
3755 col.label(
3756 text="Cone base radius: " + str(obj.pov.cone_base_radius)
3758 col.label(
3759 text="Cone cap radius: " + str(obj.pov.cone_cap_radius)
3761 col.label(
3762 text="Cone proxy segments: " + str(obj.pov.cone_segments)
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',
3772 col.label(text="3D view proxy may get out of synch")
3773 col.active = obj.pov.unlock_parameters
3775 layout.operator(
3776 "pov.cone_update", text="Update", icon="MESH_CONE"
3779 # col.label(text="Parameters:")
3780 col.prop(
3781 obj.pov, "cone_base_radius", text="Radius of Cone Base"
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"
3787 col.prop(obj.pov, "cone_height", text="Height of the cone")
3790 class OBJECT_PT_POV_obj_superellipsoid(PovDataButtonsPanel, Panel):
3791 """Use this class to define pov superellipsoid primitive parameters buttons."""
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 (
3802 and obj.pov.object_as == 'SUPERELLIPSOID'
3803 and (engine in cls.COMPAT_ENGINES)
3806 def draw(self, context):
3807 layout = self.layout
3809 obj = context.object
3811 col = layout.column()
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',
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',
3833 col.label(text="3D view proxy may get out of synch")
3834 col.active = obj.pov.unlock_parameters
3836 layout.operator(
3837 "pov.superellipsoid_update",
3838 text="Update",
3839 icon="MOD_SUBSURF",
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")
3850 class OBJECT_PT_POV_obj_torus(PovDataButtonsPanel, Panel):
3851 """Use this class to define pov torus primitive parameters buttons."""
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 (
3862 and obj.pov.object_as == 'TORUS'
3863 and (engine in cls.COMPAT_ENGINES)
3866 def draw(self, context):
3867 layout = self.layout
3869 obj = context.object
3871 col = layout.column()
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',
3881 col.label(
3882 text="Torus major radius: "
3883 + str(obj.pov.torus_major_radius)
3885 col.label(
3886 text="Torus minor radius: "
3887 + str(obj.pov.torus_minor_radius)
3889 col.label(
3890 text="Torus major segments: "
3891 + str(obj.pov.torus_major_segments)
3893 col.label(
3894 text="Torus minor segments: "
3895 + str(obj.pov.torus_minor_segments)
3897 else:
3898 col.prop(
3899 obj.pov,
3900 "unlock_parameters",
3901 text="Edit exported parameters",
3902 icon='UNLOCKED',
3904 col.label(text="3D view proxy may get out of synch")
3905 col.active = obj.pov.unlock_parameters
3907 layout.operator(
3908 "pov.torus_update", text="Update", icon="MESH_TORUS"
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")
3918 class OBJECT_PT_POV_obj_supertorus(PovDataButtonsPanel, Panel):
3919 """Use this class to define pov supertorus primitive parameters buttons."""
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 (
3930 and obj.pov.object_as == 'SUPERTORUS'
3931 and (engine in cls.COMPAT_ENGINES)
3934 def draw(self, context):
3935 layout = self.layout
3937 obj = context.object
3939 col = layout.column()
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',
3949 col.label(
3950 text="SuperTorus major radius: "
3951 + str(obj.pov.st_major_radius)
3953 col.label(
3954 text="SuperTorus minor radius: "
3955 + str(obj.pov.st_minor_radius)
3957 col.label(
3958 text="SuperTorus major segments: " + str(obj.pov.st_u)
3960 col.label(
3961 text="SuperTorus minor segments: " + str(obj.pov.st_v)
3964 col.label(
3965 text="SuperTorus Ring Manipulator: " + str(obj.pov.st_ring)
3967 col.label(
3968 text="SuperTorus Cross Manipulator: "
3969 + str(obj.pov.st_cross)
3971 col.label(
3972 text="SuperTorus Internal And External radii: "
3973 + str(obj.pov.st_ie)
3976 col.label(
3977 text="SuperTorus accuracy: " + str(ob.pov.st_accuracy)
3979 col.label(
3980 text="SuperTorus max gradient: "
3981 + str(ob.pov.st_max_gradient)
3984 else:
3985 col.prop(
3986 obj.pov,
3987 "unlock_parameters",
3988 text="Edit exported parameters",
3989 icon='UNLOCKED',
3991 col.label(text="3D view proxy may get out of synch")
3992 col.active = obj.pov.unlock_parameters
3994 layout.operator(
3995 "pov.supertorus_update", text="Update", icon="MESH_TORUS"
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")
4011 class OBJECT_PT_POV_obj_parametric(PovDataButtonsPanel, Panel):
4012 """Use this class to define pov parametric surface primitive parameters buttons."""
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 (
4023 and obj.pov.object_as == 'PARAMETRIC'
4024 and (engine in cls.COMPAT_ENGINES)
4027 def draw(self, context):
4028 layout = self.layout
4030 obj = context.object
4032 col = layout.column()
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',
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))
4050 else:
4051 col.prop(
4052 obj.pov,
4053 "unlock_parameters",
4054 text="Edit exported parameters",
4055 icon='UNLOCKED',
4057 col.label(text="3D view proxy may get out of synch")
4058 col.active = obj.pov.unlock_parameters
4060 layout.operator(
4061 "pov.parametric_update", text="Update", icon="SCRIPTPLUGINS"
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")
4073 class OBJECT_PT_povray_replacement_text(ObjectButtonsPanel, Panel):
4074 """Use this class to define pov object replacement field."""
4076 bl_label = "Custom POV Code"
4077 COMPAT_ENGINES = {'POVRAY_RENDER'}
4079 def draw(self, context):
4080 layout = self.layout
4082 obj = context.object
4084 col = layout.column()
4085 col.label(text="Replace properties with:")
4086 col.prop(obj.pov, "replacement_text", text="")
4089 ###############################################################################
4090 # Add Povray Objects
4091 ###############################################################################
4094 class VIEW_MT_POV_primitives_add(Menu):
4095 """Define the primitives menu with presets"""
4097 bl_idname = "VIEW_MT_POV_primitives_add"
4098 bl_label = "Povray"
4099 COMPAT_ENGINES = {'POVRAY_RENDER'}
4101 @classmethod
4102 def poll(cls, context):
4103 engine = context.scene.render.engine
4104 return engine == 'POVRAY_RENDER'
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"
4112 layout.menu(VIEW_MT_POV_import.bl_idname, text="Import", icon="IMPORT")
4115 class VIEW_MT_POV_Basic_Shapes(Menu):
4116 """Use this class to sort simple primitives menu entries."""
4118 bl_idname = "POVRAY_MT_basic_shape_tools"
4119 bl_label = "Basic_shapes"
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'
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"
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',
4143 layout.operator(
4144 "pov.addheightfield", text="Height Field", icon="RNDCURVE"
4146 layout.operator(
4147 "pov.addspheresweep", text="Sphere Sweep", icon='FORCE_CURVE'
4149 layout.separator()
4150 layout.operator(
4151 "pov.addblobsphere", text="Blob Sphere", icon='META_DATA'
4153 layout.separator()
4154 layout.label(text="Isosurfaces")
4155 layout.operator(
4156 "pov.addisosurfacebox", text="Isosurface Box", icon="META_CUBE"
4158 layout.operator(
4159 "pov.addisosurfacesphere",
4160 text="Isosurface Sphere",
4161 icon="META_BALL",
4163 layout.operator(
4164 "pov.addsupertorus", text="Supertorus", icon="SURFACE_NTORUS"
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",
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"
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"
4189 # layout.separator()
4190 return
4191 else:
4192 layout.operator(
4193 "pov.addparametric", text="Parametric", icon='SCRIPTPLUGINS'
4197 class VIEW_MT_POV_import(Menu):
4198 """Use this class for the import menu."""
4200 bl_idname = "POVRAY_MT_import_tools"
4201 bl_label = "Import"
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")
4209 def 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")
4215 def 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")
4221 ##############Nodes
4223 # def find_node_input(node, name):
4224 # for input in node.inputs:
4225 # if input.name == name:
4226 # return input
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
4236 # ntree = id_data.node_tree
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)
4245 # return True
4248 class NODE_MT_POV_map_create(Menu):
4249 """Create maps"""
4251 bl_idname = "POVRAY_MT_node_map_create"
4252 bl_label = "Create map"
4254 def draw(self, context):
4255 layout = self.layout
4256 layout.operator("node.map_create")
4259 def 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'
4271 tex = mat.active_texture
4272 if tex and context.space_data.tree_type == 'TextureNodeTree':
4273 self.layout.prop(tex.pov, "texture_use_nodes")
4276 ###############################################################################
4277 # Camera Povray Settings
4278 ###############################################################################
4279 class CAMERA_PT_POV_cam_dof(CameraDataButtonsPanel, Panel):
4280 """Use this class for camera depth of field focal blur buttons."""
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
4289 # self.layout.prop(cam.pov, "dof_enable", text="")
4291 def draw(self, context):
4292 layout = self.layout
4294 cam = context.camera
4296 layout.active = cam.dof.use_dof
4297 layout.use_property_split = True # Active single-column layout
4299 flow = layout.grid_flow(
4300 row_major=True,
4301 columns=0,
4302 even_columns=True,
4303 even_rows=False,
4304 align=False,
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)
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")
4321 class CAMERA_PT_POV_cam_nor(CameraDataButtonsPanel, Panel):
4322 """Use this class for camera normal perturbation buttons."""
4324 bl_label = "POV Perturbation"
4325 COMPAT_ENGINES = {'POVRAY_RENDER'}
4327 def draw_header(self, context):
4328 cam = context.camera
4330 self.layout.prop(cam.pov, "normal_enable", text="")
4332 def draw(self, context):
4333 layout = self.layout
4335 cam = context.camera
4337 layout.active = cam.pov.normal_enable
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")
4345 class CAMERA_PT_POV_replacement_text(CameraDataButtonsPanel, Panel):
4346 """Use this class for camera text replacement field."""
4348 bl_label = "Custom POV Code"
4349 COMPAT_ENGINES = {'POVRAY_RENDER'}
4351 def draw(self, context):
4352 layout = self.layout
4354 cam = context.camera
4356 col = layout.column()
4357 col.label(text="Replace properties with:")
4358 col.prop(cam.pov, "replacement_text", text="")
4361 ###############################################################################
4362 # Text Povray Settings
4363 ###############################################################################
4366 class TEXT_OT_POV_insert(Operator):
4367 """Use this class to create blender text editor operator to insert pov snippets like other pov IDEs"""
4369 bl_idname = "text.povray_insert"
4370 bl_label = "Insert"
4372 filepath: bpy.props.StringProperty(name="Filepath", subtype='FILE_PATH')
4374 @classmethod
4375 def poll(cls, context):
4376 # context.area.type == 'TEXT_EDITOR'
4377 return bpy.ops.text.insert.poll()
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())
4384 # places the cursor at the end without scrolling -.-
4385 # context.space_data.text.write(file.read())
4386 file.close()
4387 return {'FINISHED'}
4390 def validinsert(ext):
4391 return ext in {".txt", ".inc", ".pov"}
4394 class TEXT_MT_POV_insert(Menu):
4395 """Use this class to create a menu launcher in text editor for the TEXT_OT_POV_insert operator ."""
4397 bl_label = "Insert"
4398 bl_idname = "TEXT_MT_POV_insert"
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'
4405 prop.filepath = pov_documents
4406 self.layout.separator()
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,
4420 class 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."""
4423 bl_label = "POV"
4424 COMPAT_ENGINES = {'POVRAY_RENDER'}
4426 def draw(self, context):
4427 layout = self.layout
4429 text = context.space_data.text
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"
4443 # layout.separator()
4444 else:
4445 # print(pov_documents)
4446 layout.menu(TEXT_MT_POV_insert.bl_idname)
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")
4467 ###############################################
4468 # Text editor templates from header menu
4471 class TEXT_MT_POV_templates(Menu):
4472 """Use this class to create a menu for the same pov templates scenes as other pov IDEs."""
4474 bl_label = "POV"
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
4480 template_paths = [os.path.join(os.path.dirname(__file__), "templates_pov")]
4482 def draw(self, context):
4483 self.path_menu(
4484 self.template_paths, "text.open", props_default={"internal": True}
4488 def menu_func_templates(self, context):
4489 # Do not depend on POV being active renderer here...
4490 self.layout.menu("TEXT_MT_POV_templates")
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':
4499 bpy.utils.script_paths("addons")
4500 #render_freestyle_svg = os.path.join(bpy.utils.script_paths("addons"), "render_freestyle_svg.py")
4502 render_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
4507 if check_render_freestyle_svg():
4509 snippetsWIP
4510 import myscript
4511 import importlib
4513 importlib.reload(myscript)
4514 myscript.main()
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
4528 #del render_freestyle_svg.RENDER_PT_SVGExporterPanel.bl_parent_id
4531 class RENDER_PT_POV_filter(RenderButtonsPanel, Panel):
4532 """Use this class to invoke stuff like Freestyle UI."""
4534 bl_label = "Freestyle"
4535 bl_options = {'DEFAULT_CLOSED'}
4536 COMPAT_ENGINES = {'POVRAY_RENDER'}
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):
4545 #scene = context.scene
4546 rd = context.scene.render
4547 layout = self.layout
4549 if rd.use_freestyle:
4550 layout.prop(
4551 rd, "use_freestyle", text="", icon='LINE_DATA'
4554 else:
4555 layout.prop(
4556 rd, "use_freestyle", text="", icon='OUTLINER_OB_IMAGE'
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,
4573 flow.prop(rd, "line_thickness_mode", expand=True)
4575 if rd.line_thickness_mode == 'ABSOLUTE':
4576 flow.prop(rd, "line_thickness")
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"
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"
4591 classes = (
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,
4680 def register():
4681 # from bpy.utils import register_class
4683 for cls in classes:
4684 register_class(cls)
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)
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)
4701 def 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)
4706 # from bpy.utils import unregister_class
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)
4717 for cls in reversed(classes):
4718 if cls != TEXTURE_PT_context:
4719 unregister_class(cls)