Import images: add file handler
[blender-addons.git] / render_povray / model_gui.py
blob8c08492456e914e16e3f9877432613d5d53a43ef
1 # SPDX-FileCopyrightText: 2021-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 """User interface for the POV tools"""
7 import bpy
9 import os
11 from bpy.utils import register_class, unregister_class, register_tool, unregister_tool
12 from bpy.types import (
13 # Operator,
14 Menu,
15 Panel,
16 WorkSpaceTool,
19 # Example of wrapping every class 'as is'
20 from bl_ui import properties_data_modifier
22 for member in dir(properties_data_modifier):
23 subclass = getattr(properties_data_modifier, member)
24 if hasattr(subclass, "COMPAT_ENGINES"):
25 subclass.COMPAT_ENGINES.add("POVRAY_RENDER")
26 del properties_data_modifier
29 from bl_ui import properties_data_mesh
31 # These panels are kept
32 properties_data_mesh.DATA_PT_custom_props_mesh.COMPAT_ENGINES.add("POVRAY_RENDER")
33 properties_data_mesh.DATA_PT_context_mesh.COMPAT_ENGINES.add("POVRAY_RENDER")
35 # make some native panels contextual to some object variable
36 # by recreating custom panels inheriting their properties
39 from .scripting_gui import VIEW_MT_POV_import
42 class ModifierButtonsPanel:
43 """Use this class to define buttons from the modifier tab of
44 properties window."""
46 bl_space_type = "PROPERTIES"
47 bl_region_type = "WINDOW"
48 bl_context = "modifier"
49 COMPAT_ENGINES = {"POVRAY_RENDER"}
51 @classmethod
52 def poll(cls, context):
53 mods = context.object.modifiers
54 rd = context.scene.render
55 return mods and (rd.engine in cls.COMPAT_ENGINES)
58 class ObjectButtonsPanel:
59 """Use this class to define buttons from the object tab of
60 properties window."""
62 bl_space_type = "PROPERTIES"
63 bl_region_type = "WINDOW"
64 bl_context = "object"
65 COMPAT_ENGINES = {"POVRAY_RENDER"}
67 @classmethod
68 def poll(cls, context):
69 obj = context.object
70 rd = context.scene.render
71 return obj and (rd.engine in cls.COMPAT_ENGINES)
74 class PovDataButtonsPanel(properties_data_mesh.MeshButtonsPanel):
75 """Use this class to define buttons from the edit data tab of
76 properties window."""
78 COMPAT_ENGINES = {"POVRAY_RENDER"}
79 POV_OBJECT_TYPES = {
80 "PLANE",
81 "BOX",
82 "SPHERE",
83 "CYLINDER",
84 "CONE",
85 "TORUS",
86 "BLOB",
87 "ISOSURFACE_NODE",
88 "ISOSURFACE_VIEW",
89 "SUPERELLIPSOID",
90 "SUPERTORUS",
91 "HEIGHT_FIELD",
92 "PARAMETRIC",
93 "POLYCIRCLE",
96 @classmethod
97 def poll(cls, context):
98 # engine = context.scene.render.engine # XXX Unused
99 obj = context.object
100 # We use our parent class poll func too, avoids to re-define too much things...
101 return (
102 super(PovDataButtonsPanel, cls).poll(context)
103 and obj
104 and obj.pov.object_as not in cls.POV_OBJECT_TYPES
108 # We cannot inherit from RNA classes (like e.g. properties_data_mesh.DATA_PT_vertex_groups).
109 # Complex py/bpy/rna interactions (with metaclass and all) simply do not allow it to work.
110 # So we simply have to explicitly copy here the interesting bits. ;)
111 class DATA_PT_POV_texture_space(PovDataButtonsPanel, Panel):
112 bl_label = properties_data_mesh.DATA_PT_texture_space.bl_label
113 bl_options = properties_data_mesh.DATA_PT_texture_space.bl_options
115 draw = properties_data_mesh.DATA_PT_texture_space.draw
118 class DATA_PT_POV_vertex_groups(PovDataButtonsPanel, Panel):
119 bl_label = properties_data_mesh.DATA_PT_vertex_groups.bl_label
121 draw = properties_data_mesh.DATA_PT_vertex_groups.draw
124 class DATA_PT_POV_shape_keys(PovDataButtonsPanel, Panel):
125 bl_label = properties_data_mesh.DATA_PT_shape_keys.bl_label
127 draw = properties_data_mesh.DATA_PT_shape_keys.draw
130 class DATA_PT_POV_uv_texture(PovDataButtonsPanel, Panel):
131 bl_label = properties_data_mesh.DATA_PT_uv_texture.bl_label
133 draw = properties_data_mesh.DATA_PT_uv_texture.draw
136 class DATA_PT_POV_vertex_colors(PovDataButtonsPanel, Panel):
137 bl_label = properties_data_mesh.DATA_PT_vertex_colors.bl_label
139 draw = properties_data_mesh.DATA_PT_vertex_colors.draw
142 class DATA_PT_POV_customdata(PovDataButtonsPanel, Panel):
143 bl_label = properties_data_mesh.DATA_PT_customdata.bl_label
144 bl_options = properties_data_mesh.DATA_PT_customdata.bl_options
145 draw = properties_data_mesh.DATA_PT_customdata.draw
148 del properties_data_mesh
151 class MODIFIERS_PT_POV_modifiers(ModifierButtonsPanel, Panel):
152 """Use this class to define pov modifier buttons. (For booleans)"""
154 bl_label = "POV-Ray"
156 # def draw_header(self, context):
157 # scene = context.scene
158 # self.layout.prop(scene.pov, "boolean_mod", text="")
160 def draw(self, context):
161 # scene = context.scene
162 layout = self.layout
163 ob = context.object
164 col = layout.column()
165 # Find Boolean Modifiers for displaying CSG option
166 once_csg = 0
167 for mod in ob.modifiers:
168 if once_csg == 0 and mod:
169 if mod.type == "BOOLEAN":
170 col.prop(ob.pov, "boolean_mod")
171 once_csg = 1
173 if ob.pov.boolean_mod == "POV":
174 # split = layout.split() # better ?
175 col = layout.column()
176 # Inside Vector for CSG
177 col.prop(ob.pov, "inside_vector")
180 class OBJECT_PT_POV_obj_parameters(ObjectButtonsPanel, Panel):
181 """Use this class to define pov specific object level options buttons."""
183 bl_label = "POV"
185 @classmethod
186 def poll(cls, context):
188 engine = context.scene.render.engine
189 return engine in cls.COMPAT_ENGINES
191 def draw(self, context):
192 layout = self.layout
194 obj = context.object
196 split = layout.split()
198 col = split.column(align=True)
200 col.label(text="Radiosity:")
201 col.prop(obj.pov, "importance_value", text="Importance")
202 col.label(text="Photons:")
203 col.prop(obj.pov, "collect_photons", text="Receive Photon Caustics")
204 if obj.pov.collect_photons:
205 col.prop(obj.pov, "spacing_multiplier", text="Photons Spacing Multiplier")
207 split = layout.split()
209 col = split.column()
210 col.prop(obj.pov, "hollow")
211 col.prop(obj.pov, "double_illuminate")
213 if obj.type == "META" or obj.pov.curveshape == "lathe":
214 # if obj.pov.curveshape == 'sor'
215 col.prop(obj.pov, "sturm")
216 col.prop(obj.pov, "no_shadow")
217 col.prop(obj.pov, "no_image")
218 col.prop(obj.pov, "no_reflection")
219 col.prop(obj.pov, "no_radiosity")
220 col.prop(obj.pov, "inverse")
221 col.prop(obj.pov, "hierarchy")
222 # col.prop(obj.pov,"boundorclip",text="Bound / Clip")
223 # if obj.pov.boundorclip != "none":
224 # col.prop_search(obj.pov,"boundorclipob",context.blend_data,"objects",text="Object")
225 # text = "Clipped by"
226 # if obj.pov.boundorclip == "clipped_by":
227 # text = "Bounded by"
228 # col.prop(obj.pov,"addboundorclip",text=text)
231 class OBJECT_PT_POV_obj_sphere(PovDataButtonsPanel, Panel):
232 """Use this class to define pov sphere primitive parameters buttons."""
234 bl_label = "POV Sphere"
235 COMPAT_ENGINES = {"POVRAY_RENDER"}
236 # bl_options = {'HIDE_HEADER'}
238 @classmethod
239 def poll(cls, context):
240 engine = context.scene.render.engine
241 obj = context.object
242 return obj and obj.pov.object_as == "SPHERE" and (engine in cls.COMPAT_ENGINES)
244 def draw(self, context):
245 layout = self.layout
247 obj = context.object
249 col = layout.column()
251 if obj.pov.object_as == "SPHERE":
252 if not obj.pov.unlock_parameters:
253 col.prop(
254 obj.pov, "unlock_parameters", text="Exported parameters below", icon="LOCKED"
256 col.label(text="Sphere radius: " + str(obj.pov.sphere_radius))
258 else:
259 col.prop(
260 obj.pov, "unlock_parameters", text="Edit exported parameters", icon="UNLOCKED"
262 col.label(text="3D view proxy may get out of synch")
263 col.active = obj.pov.unlock_parameters
265 layout.operator("pov.sphere_update", text="Update", icon="SHADING_RENDERED")
267 # col.label(text="Parameters:")
268 col.prop(obj.pov, "sphere_radius", text="Radius of Sphere")
271 class OBJECT_PT_POV_obj_cylinder(PovDataButtonsPanel, Panel):
272 """Use this class to define pov cylinder primitive parameters buttons."""
274 bl_label = "POV Cylinder"
275 COMPAT_ENGINES = {"POVRAY_RENDER"}
276 # bl_options = {'HIDE_HEADER'}
278 @classmethod
279 def poll(cls, context):
280 engine = context.scene.render.engine
281 obj = context.object
282 return obj and obj.pov.object_as == "CYLINDER" and (engine in cls.COMPAT_ENGINES)
284 def draw(self, context):
285 layout = self.layout
287 obj = context.object
289 col = layout.column()
291 if obj.pov.object_as == "CYLINDER":
292 if not obj.pov.unlock_parameters:
293 col.prop(
294 obj.pov, "unlock_parameters", text="Exported parameters below", icon="LOCKED"
296 col.label(text="Cylinder radius: " + str(obj.pov.cylinder_radius))
297 col.label(text="Cylinder cap location: " + str(obj.pov.cylinder_location_cap))
299 else:
300 col.prop(
301 obj.pov, "unlock_parameters", text="Edit exported parameters", icon="UNLOCKED"
303 col.label(text="3D view proxy may get out of synch")
304 col.active = obj.pov.unlock_parameters
306 layout.operator("pov.cylinder_update", text="Update", icon="MESH_CYLINDER")
308 # col.label(text="Parameters:")
309 col.prop(obj.pov, "cylinder_radius")
310 col.prop(obj.pov, "cylinder_location_cap")
313 class OBJECT_PT_POV_obj_cone(PovDataButtonsPanel, Panel):
314 """Use this class to define pov cone primitive parameters buttons."""
316 bl_label = "POV Cone"
317 COMPAT_ENGINES = {"POVRAY_RENDER"}
318 # bl_options = {'HIDE_HEADER'}
320 @classmethod
321 def poll(cls, context):
322 engine = context.scene.render.engine
323 obj = context.object
324 return obj and obj.pov.object_as == "CONE" and (engine in cls.COMPAT_ENGINES)
326 def draw(self, context):
327 layout = self.layout
329 obj = context.object
331 col = layout.column()
333 if obj.pov.object_as == "CONE":
334 if not obj.pov.unlock_parameters:
335 col.prop(
336 obj.pov, "unlock_parameters", text="Exported parameters below", icon="LOCKED"
338 col.label(text="Cone base radius: " + str(obj.pov.cone_base_radius))
339 col.label(text="Cone cap radius: " + str(obj.pov.cone_cap_radius))
340 col.label(text="Cone proxy segments: " + str(obj.pov.cone_segments))
341 col.label(text="Cone height: " + str(obj.pov.cone_height))
342 else:
343 col.prop(
344 obj.pov, "unlock_parameters", text="Edit exported parameters", icon="UNLOCKED"
346 col.label(text="3D view proxy may get out of synch")
347 col.active = obj.pov.unlock_parameters
349 layout.operator("pov.cone_update", text="Update", icon="MESH_CONE")
351 # col.label(text="Parameters:")
352 col.prop(obj.pov, "cone_base_radius", text="Radius of Cone Base")
353 col.prop(obj.pov, "cone_cap_radius", text="Radius of Cone Cap")
354 col.prop(obj.pov, "cone_segments", text="Segmentation of Cone proxy")
355 col.prop(obj.pov, "cone_height", text="Height of the cone")
358 class OBJECT_PT_POV_obj_superellipsoid(PovDataButtonsPanel, Panel):
359 """Use this class to define pov superellipsoid primitive parameters buttons."""
361 bl_label = "POV Superquadric ellipsoid"
362 COMPAT_ENGINES = {"POVRAY_RENDER"}
363 # bl_options = {'HIDE_HEADER'}
365 @classmethod
366 def poll(cls, context):
367 engine = context.scene.render.engine
368 obj = context.object
369 return obj and obj.pov.object_as == "SUPERELLIPSOID" and (engine in cls.COMPAT_ENGINES)
371 def draw(self, context):
372 layout = self.layout
374 obj = context.object
376 col = layout.column()
378 if obj.pov.object_as == "SUPERELLIPSOID":
379 if not obj.pov.unlock_parameters:
380 col.prop(
381 obj.pov, "unlock_parameters", text="Exported parameters below", icon="LOCKED"
383 col.label(text="Radial segmentation: " + str(obj.pov.se_u))
384 col.label(text="Lateral segmentation: " + str(obj.pov.se_v))
385 col.label(text="Ring shape: " + str(obj.pov.se_n1))
386 col.label(text="Cross-section shape: " + str(obj.pov.se_n2))
387 col.label(text="Fill up and down: " + str(obj.pov.se_edit))
388 else:
389 col.prop(
390 obj.pov, "unlock_parameters", text="Edit exported parameters", icon="UNLOCKED"
392 col.label(text="3D view proxy may get out of synch")
393 col.active = obj.pov.unlock_parameters
395 layout.operator("pov.superellipsoid_update", text="Update", icon="MOD_SUBSURF")
397 # col.label(text="Parameters:")
398 col.prop(obj.pov, "se_u")
399 col.prop(obj.pov, "se_v")
400 col.prop(obj.pov, "se_n1")
401 col.prop(obj.pov, "se_n2")
402 col.prop(obj.pov, "se_edit")
405 class OBJECT_PT_POV_obj_torus(PovDataButtonsPanel, Panel):
406 """Use this class to define pov torus primitive parameters buttons."""
408 bl_label = "POV Torus"
409 COMPAT_ENGINES = {"POVRAY_RENDER"}
410 # bl_options = {'HIDE_HEADER'}
412 @classmethod
413 def poll(cls, context):
414 engine = context.scene.render.engine
415 obj = context.object
416 return obj and obj.pov.object_as == "TORUS" and (engine in cls.COMPAT_ENGINES)
418 def draw(self, context):
419 layout = self.layout
421 obj = context.object
423 col = layout.column()
425 if obj.pov.object_as == "TORUS":
426 if not obj.pov.unlock_parameters:
427 col.prop(
428 obj.pov, "unlock_parameters", text="Exported parameters below", icon="LOCKED"
430 col.label(text="Torus major radius: " + str(obj.pov.torus_major_radius))
431 col.label(text="Torus minor radius: " + str(obj.pov.torus_minor_radius))
432 col.label(text="Torus major segments: " + str(obj.pov.torus_major_segments))
433 col.label(text="Torus minor segments: " + str(obj.pov.torus_minor_segments))
434 else:
435 col.prop(
436 obj.pov, "unlock_parameters", text="Edit exported parameters", icon="UNLOCKED"
438 col.label(text="3D view proxy may get out of synch")
439 col.active = obj.pov.unlock_parameters
441 layout.operator("pov.torus_update", text="Update", icon="MESH_TORUS")
443 # col.label(text="Parameters:")
444 col.prop(obj.pov, "torus_major_radius")
445 col.prop(obj.pov, "torus_minor_radius")
446 col.prop(obj.pov, "torus_major_segments")
447 col.prop(obj.pov, "torus_minor_segments")
450 class OBJECT_PT_POV_obj_supertorus(PovDataButtonsPanel, Panel):
451 """Use this class to define pov supertorus primitive parameters buttons."""
453 bl_label = "POV SuperTorus"
454 COMPAT_ENGINES = {"POVRAY_RENDER"}
455 # bl_options = {'HIDE_HEADER'}
457 @classmethod
458 def poll(cls, context):
459 engine = context.scene.render.engine
460 obj = context.object
461 return obj and obj.pov.object_as == "SUPERTORUS" and (engine in cls.COMPAT_ENGINES)
463 def draw(self, context):
464 layout = self.layout
466 obj = context.object
468 col = layout.column()
470 if obj.pov.object_as == "SUPERTORUS":
471 if not obj.pov.unlock_parameters:
472 col.prop(
473 obj.pov, "unlock_parameters", text="Exported parameters below", icon="LOCKED"
475 col.label(text="SuperTorus major radius: " + str(obj.pov.st_major_radius))
476 col.label(text="SuperTorus minor radius: " + str(obj.pov.st_minor_radius))
477 col.label(text="SuperTorus major segments: " + str(obj.pov.st_u))
478 col.label(text="SuperTorus minor segments: " + str(obj.pov.st_v))
480 col.label(text="SuperTorus Ring Manipulator: " + str(obj.pov.st_ring))
481 col.label(text="SuperTorus Cross Manipulator: " + str(obj.pov.st_cross))
482 col.label(text="SuperTorus Internal And External radii: " + str(obj.pov.st_ie))
484 col.label(text="SuperTorus accuracy: " + str(obj.pov.st_accuracy))
485 col.label(text="SuperTorus max gradient: " + str(obj.pov.st_max_gradient))
487 else:
488 col.prop(
489 obj.pov, "unlock_parameters", text="Edit exported parameters", icon="UNLOCKED"
491 col.label(text="3D view proxy may get out of synch")
492 col.active = obj.pov.unlock_parameters
494 layout.operator("pov.supertorus_update", text="Update", icon="MESH_TORUS")
496 # col.label(text="Parameters:")
497 col.prop(obj.pov, "st_major_radius")
498 col.prop(obj.pov, "st_minor_radius")
499 col.prop(obj.pov, "st_u")
500 col.prop(obj.pov, "st_v")
501 col.prop(obj.pov, "st_ring")
502 col.prop(obj.pov, "st_cross")
503 col.prop(obj.pov, "st_ie")
504 # col.prop(obj.pov, "st_edit") #?
505 col.prop(obj.pov, "st_accuracy")
506 col.prop(obj.pov, "st_max_gradient")
509 class OBJECT_PT_POV_obj_isosurface(PovDataButtonsPanel, Panel):
510 """Use this class to define pov generic isosurface primitive function user field."""
512 bl_label = "POV Isosurface"
513 COMPAT_ENGINES = {"POVRAY_RENDER"}
514 # bl_options = {'HIDE_HEADER'}
516 @classmethod
517 def poll(cls, context):
518 engine = context.scene.render.engine
519 obj = context.object
520 return obj and obj.pov.object_as == "ISOSURFACE_VIEW" and (engine in cls.COMPAT_ENGINES)
522 def draw(self, context):
523 layout = self.layout
525 obj = context.object
527 col = layout.column()
529 if obj.pov.object_as == "ISOSURFACE_VIEW":
530 col.prop(obj.pov, "isosurface_eq")
533 class OBJECT_PT_POV_obj_parametric(PovDataButtonsPanel, Panel):
534 """Use this class to define pov parametric surface primitive parameters buttons."""
536 bl_label = "POV Parametric surface"
537 # bl_options = {'HIDE_HEADER'}
539 @classmethod
540 def poll(cls, context):
541 engine = context.scene.render.engine
542 obj = context.object
543 return obj and obj.pov.object_as == "PARAMETRIC" and (engine in cls.COMPAT_ENGINES)
545 def draw(self, context):
546 layout = self.layout
548 obj = context.object
550 col = layout.column()
552 if obj.pov.object_as == "PARAMETRIC":
553 if not obj.pov.unlock_parameters:
554 col.prop(
555 obj.pov, "unlock_parameters", text="Exported parameters below", icon="LOCKED"
557 col.label(text="Minimum U: " + str(obj.pov.u_min))
558 col.label(text="Minimum V: " + str(obj.pov.v_min))
559 col.label(text="Maximum U: " + str(obj.pov.u_max))
560 col.label(text="Minimum V: " + str(obj.pov.v_min))
561 col.label(text="X Function: " + str(obj.pov.x_eq))
562 col.label(text="Y Function: " + str(obj.pov.y_eq))
563 col.label(text="Z Function: " + str(obj.pov.x_eq))
565 else:
566 col.prop(
567 obj.pov, "unlock_parameters", text="Edit exported parameters", icon="UNLOCKED"
569 col.label(text="3D view proxy may get out of synch")
570 col.active = obj.pov.unlock_parameters
572 layout.operator("pov.parametric_update", text="Update", icon="SCRIPTPLUGINS")
574 col.prop(obj.pov, "u_min", text="Minimum U")
575 col.prop(obj.pov, "v_min", text="Minimum V")
576 col.prop(obj.pov, "u_max", text="Maximum U")
577 col.prop(obj.pov, "v_max", text="Minimum V")
578 col.prop(obj.pov, "x_eq", text="X Function")
579 col.prop(obj.pov, "y_eq", text="Y Function")
580 col.prop(obj.pov, "z_eq", text="Z Function")
583 class OBJECT_PT_povray_replacement_text(ObjectButtonsPanel, Panel):
584 """Use this class to define pov object replacement field."""
586 bl_label = "Custom POV Code"
587 COMPAT_ENGINES = {"POVRAY_RENDER"}
589 def draw(self, context):
590 layout = self.layout
592 obj = context.object
594 col = layout.column()
595 col.label(text="Replace properties with:")
596 col.prop(obj.pov, "replacement_text", text="")
599 # ---------------------------------------------------------------- #
600 # Add POV objects
601 # ---------------------------------------------------------------- #
602 def check_add_mesh_extra_objects():
603 """Test if Add mesh extra objects addon is activated
605 This addon is currently used to generate the proxy for POV parametric
606 surface which is almost the same principle as its Math xyz surface
608 return "add_mesh_extra_objects" in bpy.context.preferences.addons.keys()
611 def menu_func_add(self, context):
612 """Append the POV primitives submenu to blender add objects menu"""
613 engine = context.scene.render.engine
614 if engine == "POVRAY_RENDER":
615 self.layout.menu("VIEW_MT_POV_primitives_add", icon="PLUGIN")
618 class VIEW_MT_POV_primitives_add(Menu):
619 """Define the primitives menu with presets"""
621 bl_idname = "VIEW_MT_POV_primitives_add"
622 bl_label = "Povray"
623 COMPAT_ENGINES = {"POVRAY_RENDER"}
625 @classmethod
626 def poll(cls, context):
627 engine = context.scene.render.engine
628 return engine == "POVRAY_RENDER"
630 def draw(self, context):
631 layout = self.layout
632 layout.operator_context = "INVOKE_REGION_WIN"
633 layout.menu(VIEW_MT_POV_Basic_Shapes.bl_idname, text="Primitives", icon="GROUP")
634 layout.menu(VIEW_MT_POV_import.bl_idname, text="Import", icon="IMPORT")
637 class VIEW_MT_POV_Basic_Shapes(Menu):
638 """Use this class to sort simple primitives menu entries."""
640 bl_idname = "POVRAY_MT_basic_shape_tools"
641 bl_label = "Basic_shapes"
643 def draw(self, context):
644 layout = self.layout
645 layout.operator_context = "INVOKE_REGION_WIN"
646 layout.operator("pov.addplane", text="Infinite Plane", icon="MESH_PLANE")
647 layout.operator("pov.addbox", text="Box", icon="MESH_CUBE")
648 layout.operator("pov.addsphere", text="Sphere", icon="SHADING_RENDERED")
649 layout.operator("pov.addcylinder", text="Cylinder", icon="MESH_CYLINDER")
650 layout.operator("pov.addcone", text="Cone", icon="MESH_CONE")
651 layout.operator("pov.addtorus", text="Torus", icon="MESH_TORUS")
652 layout.separator()
653 layout.operator("pov.addrainbow", text="Rainbow", icon="COLOR")
654 layout.operator("pov.addlathe", text="Lathe", icon="MOD_SCREW")
655 layout.operator("pov.addprism", text="Prism", icon="MOD_SOLIDIFY")
656 layout.operator("pov.addsuperellipsoid", text="Superquadric Ellipsoid", icon="MOD_SUBSURF")
657 layout.operator("pov.addheightfield", text="Height Field", icon="RNDCURVE")
658 layout.operator("pov.addspheresweep", text="Sphere Sweep", icon="FORCE_CURVE")
659 layout.separator()
660 layout.operator("pov.addblobsphere", text="Blob Sphere", icon="META_DATA")
661 layout.separator()
662 layout.label(text="Isosurfaces")
663 layout.operator("pov.addisosurfacebox", text="Isosurface Box", icon="META_CUBE")
664 layout.operator("pov.addisosurfacesphere", text="Isosurface Sphere", icon="META_BALL")
665 layout.operator("pov.addsupertorus", text="Supertorus", icon="SURFACE_NTORUS")
666 layout.separator()
667 layout.label(text="Macro based")
668 layout.operator(
669 "pov.addpolygontocircle", text="Polygon To Circle Blending", icon="MOD_CAST"
671 layout.operator("pov.addloft", text="Loft", icon="SURFACE_NSURFACE")
672 layout.separator()
673 # Warning if the Add Advanced Objects addon containing
674 # Add mesh extra objects is not enabled
675 if not check_add_mesh_extra_objects():
676 # col = box.column()
677 layout.label(text="Please enable Add Mesh: Extra Objects addon", icon="INFO")
678 # layout.separator()
679 layout.operator(
680 "preferences.addon_show",
681 text="Go to Add Mesh: Extra Objects addon",
682 icon="PREFERENCES",
683 ).module = "add_mesh_extra_objects"
685 # layout.separator()
686 return
687 layout.operator("pov.addparametric", text="Parametric", icon="SCRIPTPLUGINS")
690 # ------------ Tool bar button------------ #
691 icon_path = os.path.join(os.path.dirname(__file__), "icons")
694 class VIEW_WT_POV_plane_add(WorkSpaceTool):
695 bl_space_type = "VIEW_3D"
696 bl_context_mode = "OBJECT"
698 # The prefix of the idname should be your add-on name.
699 bl_idname = "pov.addplane"
700 bl_label = "Add POV plane"
702 bl_description = "add a plane of infinite dimension for POV"
703 bl_icon = os.path.join(icon_path, "pov.add.infinite_plane")
704 bl_widget = None
705 bl_keymap = (("pov.addplane", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
708 class VIEW_WT_POV_box_add(WorkSpaceTool):
709 bl_space_type = "VIEW_3D"
710 bl_context_mode = "OBJECT"
712 # The prefix of the idname should be your add-on name.
713 bl_idname = "pov.addbox"
714 bl_label = "Add POV box"
716 bl_description = "add a POV box solid primitive"
717 bl_icon = os.path.join(icon_path, "pov.add.box")
718 bl_widget = None
719 bl_keymap = (("pov.addbox", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
722 class VIEW_WT_POV_sphere_add(WorkSpaceTool):
723 bl_space_type = "VIEW_3D"
724 bl_context_mode = "OBJECT"
726 # The prefix of the idname should be your add-on name.
727 bl_idname = "pov.addsphere"
728 bl_label = "Add POV sphere"
730 bl_description = "add an untesselated sphere for POV"
731 bl_icon = os.path.join(icon_path, "pov.add.sphere")
732 bl_widget = None
733 bl_keymap = (("pov.addsphere", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
736 class VIEW_WT_POV_cylinder_add(WorkSpaceTool):
737 bl_space_type = "VIEW_3D"
738 bl_context_mode = "OBJECT"
740 # The prefix of the idname should be your add-on name.
741 bl_idname = "pov.addcylinder"
742 bl_label = "Add POV cylinder"
744 bl_description = "add an untesselated cylinder for POV"
745 bl_icon = os.path.join(icon_path, "pov.add.cylinder")
746 bl_widget = None
747 bl_keymap = (
748 ("pov.addcylinder", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
752 class VIEW_WT_POV_cone_add(WorkSpaceTool):
753 bl_space_type = "VIEW_3D"
754 bl_context_mode = "OBJECT"
756 # The prefix of the idname should be your add-on name.
757 bl_idname = "pov.addcone"
758 bl_label = "Add POV cone"
760 bl_description = "add an untesselated cone for POV"
761 bl_icon = os.path.join(icon_path, "pov.add.cone")
762 bl_widget = None
763 bl_keymap = (("pov.addcone", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
766 class VIEW_WT_POV_torus_add(WorkSpaceTool):
767 bl_space_type = "VIEW_3D"
768 bl_context_mode = "OBJECT"
770 # The prefix of the idname should be your add-on name.
771 bl_idname = "pov.addtorus"
772 bl_label = "Add POV torus"
774 bl_description = "add an untesselated torus for POV"
775 bl_icon = os.path.join(icon_path, "pov.add.torus")
776 bl_widget = None
777 bl_keymap = (("pov.addtorus", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
780 class VIEW_WT_POV_rainbow_add(WorkSpaceTool):
781 bl_space_type = "VIEW_3D"
782 bl_context_mode = "OBJECT"
784 # The prefix of the idname should be your add-on name.
785 bl_idname = "pov.addrainbow"
786 bl_label = "Add POV rainbow"
788 bl_description = "add a POV rainbow primitive"
789 bl_icon = os.path.join(icon_path, "pov.add.rainbow")
790 bl_widget = None
791 bl_keymap = (("pov.addrainbow", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
794 class VIEW_WT_POV_lathe_add(WorkSpaceTool):
795 bl_space_type = "VIEW_3D"
796 bl_context_mode = "OBJECT"
798 # The prefix of the idname should be your add-on name.
799 bl_idname = "pov.addlathe"
800 bl_label = "Add POV lathe"
802 bl_description = "add a POV lathe primitive"
803 bl_icon = os.path.join(icon_path, "pov.add.lathe")
804 bl_widget = None
805 bl_keymap = (("pov.addlathe", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
808 class VIEW_WT_POV_prism_add(WorkSpaceTool):
809 bl_space_type = "VIEW_3D"
810 bl_context_mode = "OBJECT"
812 # The prefix of the idname should be your add-on name.
813 bl_idname = "pov.addprism"
814 bl_label = "Add POV prism"
816 bl_description = "add a POV prism primitive"
817 bl_icon = os.path.join(icon_path, "pov.add.prism")
818 bl_widget = None
819 bl_keymap = (("pov.addprism", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
822 class VIEW_WT_POV_heightfield_add(WorkSpaceTool):
823 bl_space_type = "VIEW_3D"
824 bl_context_mode = "OBJECT"
826 # The prefix of the idname should be your add-on name.
827 bl_idname = "pov.addheightfield"
828 bl_label = "Add POV heightfield"
830 bl_description = "add a POV heightfield primitive"
831 bl_icon = os.path.join(icon_path, "pov.add.heightfield")
832 bl_widget = None
833 bl_keymap = (
834 ("pov.addheightfield", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
838 class VIEW_WT_POV_superellipsoid_add(WorkSpaceTool):
839 bl_space_type = "VIEW_3D"
840 bl_context_mode = "OBJECT"
842 # The prefix of the idname should be your add-on name.
843 bl_idname = "pov.addsuperellipsoid"
844 bl_label = "Add POV superquadric ellipsoid"
846 bl_description = "add a POV superquadric ellipsoid primitive"
847 bl_icon = os.path.join(icon_path, "pov.add.superellipsoid")
848 bl_widget = None
849 bl_keymap = (
850 ("pov.addsuperellipsoid", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
854 class VIEW_WT_POV_spheresweep_add(WorkSpaceTool):
855 bl_space_type = "VIEW_3D"
856 bl_context_mode = "OBJECT"
858 # The prefix of the idname should be your add-on name.
859 bl_idname = "pov.addspheresweep"
860 bl_label = "Add POV spheresweep"
862 bl_description = "add a POV spheresweep primitive"
863 bl_icon = os.path.join(icon_path, "pov.add.spheresweep")
864 bl_widget = None
865 bl_keymap = (
866 ("pov.addspheresweep", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
870 class VIEW_WT_POV_loft_add(WorkSpaceTool):
871 bl_space_type = "VIEW_3D"
872 bl_context_mode = "OBJECT"
874 # The prefix of the idname should be your add-on name.
875 bl_idname = "pov.addloft"
876 bl_label = "Add POV loft macro"
878 bl_description = "add a POV loft macro between editable spline cross sections"
879 bl_icon = os.path.join(icon_path, "pov.add.loft")
880 bl_widget = None
881 bl_keymap = (("pov.addloft", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),)
884 class VIEW_WT_POV_polytocircle_add(WorkSpaceTool):
885 bl_space_type = "VIEW_3D"
886 bl_context_mode = "OBJECT"
888 # The prefix of the idname should be your add-on name.
889 bl_idname = "pov.addpolygontocircle"
890 bl_label = "Add POV poly to circle macro"
892 bl_description = "add a POV regular polygon to circle blending macro"
893 bl_icon = os.path.join(icon_path, "pov.add.polygontocircle")
894 bl_widget = None
895 bl_keymap = (
896 ("pov.addpolygontocircle", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
900 class VIEW_WT_POV_parametric_add(WorkSpaceTool):
901 bl_space_type = "VIEW_3D"
902 bl_context_mode = "OBJECT"
904 # The prefix of the idname should be your add-on name.
905 bl_idname = "pov.addparametric"
906 bl_label = "Add POV parametric surface"
908 bl_description = "add a POV parametric surface primitive shaped from three equations (for x, y, z directions)"
909 bl_icon = os.path.join(icon_path, "pov.add.parametric")
910 bl_widget = None
911 bl_keymap = (
912 ("pov.addparametric", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
916 class VIEW_WT_POV_isosurface_add(WorkSpaceTool):
917 bl_space_type = "VIEW_3D"
918 bl_context_mode = "OBJECT"
920 # The prefix of the idname should be your add-on name.
921 bl_idname = "pov.addisosurface"
922 bl_label = "Add POV generic isosurface"
924 bl_description = "add a POV generic shaped isosurface primitive"
925 bl_icon = os.path.join(icon_path, "pov.add.isosurface")
926 bl_widget = None
927 bl_keymap = (
928 ("pov.addisosurface", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
932 class VIEW_WT_POV_isosurfacebox_add(WorkSpaceTool):
933 bl_space_type = "VIEW_3D"
934 bl_context_mode = "OBJECT"
936 # The prefix of the idname should be your add-on name.
937 bl_idname = "pov.addisosurfacebox"
938 bl_label = "Add POV isosurface box"
940 bl_description = "add a POV box shaped isosurface primitive"
941 bl_icon = os.path.join(icon_path, "pov.add.isosurfacebox")
942 bl_widget = None
943 bl_keymap = (
944 ("pov.addisosurfacebox", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
948 class VIEW_WT_POV_isosurfacesphere_add(WorkSpaceTool):
949 bl_space_type = "VIEW_3D"
950 bl_context_mode = "OBJECT"
952 # The prefix of the idname should be your add-on name.
953 bl_idname = "pov.addisosurfacesphere"
954 bl_label = "Add POV isosurface sphere"
956 bl_description = "add a POV sphere shaped isosurface primitive"
957 bl_icon = os.path.join(icon_path, "pov.add.isosurfacesphere")
958 bl_widget = None
959 bl_keymap = (
960 ("pov.addisosurfacesphere", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
964 class VIEW_WT_POV_isosurfacesupertorus_add(WorkSpaceTool):
965 bl_space_type = "VIEW_3D"
966 bl_context_mode = "OBJECT"
968 # The prefix of the idname should be your add-on name.
969 bl_idname = "pov.addsupertorus"
970 bl_label = "Add POV isosurface supertorus"
972 bl_description = "add a POV torus shaped isosurface primitive"
973 bl_icon = os.path.join(icon_path, "pov.add.isosurfacesupertorus")
974 bl_widget = None
975 bl_keymap = (
976 ("pov.addsupertorus", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
980 class VIEW_WT_POV_blobsphere_add(WorkSpaceTool):
981 bl_space_type = "VIEW_3D"
982 bl_context_mode = "OBJECT"
984 # The prefix of the idname should be your add-on name.
985 bl_idname = "pov.addblobsphere"
986 bl_label = "Add POV blob sphere"
988 bl_description = "add a POV sphere shaped blob primitive"
989 bl_icon = os.path.join(icon_path, "pov.add.blobsphere")
990 bl_widget = None
991 bl_keymap = (
992 ("pov.addblobsphere", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
996 class VIEW_WT_POV_blobcapsule_add(WorkSpaceTool):
997 bl_space_type = "VIEW_3D"
998 bl_context_mode = "OBJECT"
1000 # The prefix of the idname should be your add-on name.
1001 bl_idname = "pov.addblobcapsule"
1002 bl_label = "Add POV blob capsule"
1004 bl_description = "add a POV capsule shaped blob primitive"
1005 bl_icon = os.path.join(icon_path, "pov.add.blobcapsule")
1006 bl_widget = None
1007 bl_keymap = (
1008 ("pov.addblobcapsule", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
1012 class VIEW_WT_POV_blobplane_add(WorkSpaceTool):
1013 bl_space_type = "VIEW_3D"
1014 bl_context_mode = "OBJECT"
1016 # The prefix of the idname should be your add-on name.
1017 bl_idname = "pov.addblobplane"
1018 bl_label = "Add POV blob plane"
1020 bl_description = "add a POV plane shaped blob primitive"
1021 bl_icon = os.path.join(icon_path, "pov.add.blobplane")
1022 bl_widget = None
1023 bl_keymap = (
1024 ("pov.addblobplane", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
1028 class VIEW_WT_POV_blobellipsoid_add(WorkSpaceTool):
1029 bl_space_type = "VIEW_3D"
1030 bl_context_mode = "OBJECT"
1032 # The prefix of the idname should be your add-on name.
1033 bl_idname = "pov.addblobellipsoid"
1034 bl_label = "Add POV blob ellipsoid"
1036 bl_description = "add a POV ellipsoid shaped blob primitive"
1037 bl_icon = os.path.join(icon_path, "pov.add.blobellipsoid")
1038 bl_widget = None
1039 bl_keymap = (
1040 ("pov.addblobellipsoid", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
1044 class VIEW_WT_POV_blobcube_add(WorkSpaceTool):
1045 bl_space_type = "VIEW_3D"
1046 bl_context_mode = "OBJECT"
1048 # The prefix of the idname should be your add-on name.
1049 bl_idname = "pov.addsblobcube"
1050 bl_label = "Add POV blob cube"
1052 bl_description = "add a POV cube shaped blob primitive"
1053 bl_icon = os.path.join(icon_path, "pov.add.blobcube")
1054 bl_widget = None
1055 bl_keymap = (
1056 ("pov.addblobcube", {"type": "LEFTMOUSE", "value": "PRESS"}, {"properties": None}),
1060 classes = (
1061 # ObjectButtonsPanel,
1062 # PovDataButtonsPanel,
1063 DATA_PT_POV_texture_space,
1064 DATA_PT_POV_vertex_groups,
1065 DATA_PT_POV_shape_keys,
1066 DATA_PT_POV_uv_texture,
1067 DATA_PT_POV_vertex_colors,
1068 DATA_PT_POV_customdata,
1069 MODIFIERS_PT_POV_modifiers,
1070 OBJECT_PT_POV_obj_parameters,
1071 OBJECT_PT_POV_obj_sphere,
1072 OBJECT_PT_POV_obj_cylinder,
1073 OBJECT_PT_POV_obj_cone,
1074 OBJECT_PT_POV_obj_superellipsoid,
1075 OBJECT_PT_POV_obj_torus,
1076 OBJECT_PT_POV_obj_supertorus,
1077 OBJECT_PT_POV_obj_isosurface,
1078 OBJECT_PT_POV_obj_parametric,
1079 OBJECT_PT_povray_replacement_text,
1080 VIEW_MT_POV_primitives_add,
1081 VIEW_MT_POV_Basic_Shapes,
1083 tool_classes = (
1084 VIEW_WT_POV_plane_add,
1085 VIEW_WT_POV_box_add,
1086 VIEW_WT_POV_sphere_add,
1087 VIEW_WT_POV_cylinder_add,
1088 VIEW_WT_POV_cone_add,
1089 VIEW_WT_POV_torus_add,
1090 VIEW_WT_POV_prism_add,
1091 VIEW_WT_POV_lathe_add,
1092 VIEW_WT_POV_spheresweep_add,
1093 VIEW_WT_POV_heightfield_add,
1094 VIEW_WT_POV_superellipsoid_add,
1095 VIEW_WT_POV_rainbow_add,
1096 VIEW_WT_POV_loft_add,
1097 VIEW_WT_POV_polytocircle_add,
1098 VIEW_WT_POV_parametric_add,
1099 VIEW_WT_POV_isosurface_add,
1100 VIEW_WT_POV_isosurfacebox_add,
1101 VIEW_WT_POV_isosurfacesphere_add,
1102 VIEW_WT_POV_isosurfacesupertorus_add,
1103 VIEW_WT_POV_blobsphere_add,
1104 VIEW_WT_POV_blobcapsule_add,
1105 VIEW_WT_POV_blobplane_add,
1106 VIEW_WT_POV_blobellipsoid_add,
1107 VIEW_WT_POV_blobcube_add,
1111 def register():
1112 for cls in classes:
1113 register_class(cls)
1115 # Register tools
1116 last_tool = {"builtin.measure"}
1117 for index, wtl in enumerate(tool_classes):
1118 # Only separate first and 12th tools and hide subtools only in 8th (isosurfaces)
1119 register_tool(
1120 wtl, after=last_tool, separator=index in {0, 7, 11, 12, 14, 19}, group=index == 15
1122 last_tool = {wtl.bl_idname}
1124 bpy.types.VIEW3D_MT_add.prepend(menu_func_add)
1125 # Below was used for parametric objects but made the other addon unreachable on
1126 # unregister for other tools to use. Created a user action call instead
1127 # addon_utils.enable("add_mesh_extra_objects", default_set=False, persistent=True)
1130 def unregister():
1131 # addon_utils.disable("add_mesh_extra_objects", default_set=False)
1132 bpy.types.VIEW3D_MT_add.remove(menu_func_add)
1134 for wtl in reversed(tool_classes):
1135 unregister_tool(wtl)
1137 for cls in reversed(classes):
1138 unregister_class(cls)