Cleanup: trailing space
[blender-addons.git] / render_povray / base_ui.py
blob5ecf53b6af05026e36c6f3059bbf7751c57902b1
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # <pep8 compliant>
5 """User interface imports and preferences for the addon."""
7 # import addon_utils
8 # from time import sleep
9 import bpy
10 import os
12 from bpy.app.handlers import persistent
13 from pathlib import Path
15 # from bpy.utils import register_class, unregister_class
16 # from bpy.types import (
17 # Operator,
18 # Menu,
19 # UIList,
20 # Panel,
21 # Brush,
22 # Material,
23 # Light,
24 # World,
25 # ParticleSettings,
26 # FreestyleLineStyle,
27 # )
29 # from bl_operators.presets import AddPresetBase
31 from . import (
32 render_gui,
33 scenography_gui,
34 object_gui,
35 shading_gui,
36 texturing_gui,
37 shading_nodes, # for POV specific nodes
38 scripting_gui,
39 update_files,
43 # ------------ POV-Centric WORKSPACE ------------ #
44 @persistent
45 def pov_centric_moray_like_workspace(dummy):
46 """Set up a POV centric Workspace if addon was activated and saved as default renderer.
48 This would bring a ’_RestrictData’ error because UI needs to be fully loaded before
49 workspace changes so registering this function in bpy.app.handlers is needed.
50 By default handlers are freed when loading new files, but here we want the handler
51 to stay running across multiple files as part of this add-on. That is why the
52 bpy.app.handlers.persistent decorator is used (@persistent) above.
53 """
54 # Scripting workspace may have been altered from factory though, so should
55 # we put all within a Try... Except AttributeErrors ? Any better solution ?
56 # Should it simply not run when opening existing file? be a preferences operator to create
57 # Moray like workspace
59 available_workspaces = bpy.data.workspaces
61 if all(tabs in available_workspaces for tabs in ['POV-Mo', 'POV-Ed']):
62 print("\nPOV-Mo and POV-Ed tabs respectively provide GUI and TEXT\n"
63 "oriented POV workspaces akin to Moray and POVWIN")
64 else:
65 if 'POV-Ed'not in available_workspaces:
66 print(
67 "\nTo use POV centric workspaces you can set POV render option\n"
68 "and save it with File > Defaults > Save Startup File menu"
70 try:
71 if all(othertabs not in available_workspaces for othertabs in ['Geometry Nodes', 'POV-Ed']):
72 bpy.ops.workspace.append_activate(
73 idname='Geometry Nodes',
74 filepath=os.path.join(bpy.utils.user_resource('CONFIG'), 'startup.blend')
76 except BaseException as e:
77 print(e.__doc__)
78 print('An exception occurred: {}'.format(e))
79 try:
80 # Last resort: try to import from the blender templates
81 for p in Path(next(bpy.utils.app_template_paths())).rglob("startup.blend"):
82 bpy.ops.workspace.append_activate(
83 idname=self.targetWorkspace,
84 filepath=str(p))
85 except BaseException as e:
86 print(e.__doc__)
87 print('An exception occurred: {}'.format(e))
88 # Giving up as prerequisites can't be found
89 print(
90 "\nFactory Geometry Nodes workspace needed for POV text centric"
91 "\nworkspace to activate when POV is set as default renderer"
93 finally:
94 # Create POVWIN like editor (text oriented editing)
95 if 'POV-Ed' not in available_workspaces and 'Geometry Nodes' in available_workspaces:
96 wsp = available_workspaces.get('Geometry Nodes')
97 context = bpy.context
98 if context.scene.render.engine == 'POVRAY_RENDER' and wsp is not None:
99 bpy.ops.workspace.duplicate({'workspace': wsp})
100 available_workspaces['Geometry Nodes.001'].name = 'POV-Ed'
101 # May be already done, but explicitly make this workspace the active one
102 context.window.workspace = available_workspaces['POV-Ed']
103 pov_screen = available_workspaces['POV-Ed'].screens[0]
104 pov_workspace = pov_screen.areas
105 pov_window = context.window
106 # override = bpy.context.copy() # crashes
107 override = {}
108 properties_area = pov_workspace[0]
109 nodes_to_3dview_area = pov_workspace[1]
110 view3d_to_text_area = pov_workspace[2]
111 spreadsheet_to_console_area = pov_workspace[3]
113 try:
114 nodes_to_3dview_area.ui_type = 'VIEW_3D'
115 override['window'] = pov_window
116 override['screen'] = bpy.context.screen
117 override['area'] = nodes_to_3dview_area
118 override['region'] = nodes_to_3dview_area.regions[-1]
119 bpy.ops.screen.space_type_set_or_cycle(
120 override, 'INVOKE_DEFAULT', space_type='VIEW_3D'
122 space = nodes_to_3dview_area.spaces.active
123 space.region_3d.view_perspective = 'CAMERA'
125 override['window'] = pov_window
126 override['screen'] = bpy.context.screen
127 override['area'] = view3d_to_text_area
128 override['region'] = view3d_to_text_area .regions[-1]
129 override['scene'] = bpy.context.scene
130 override['space_data'] = view3d_to_text_area .spaces.active
131 bpy.ops.screen.space_type_set_or_cycle(
132 override, 'INVOKE_DEFAULT', space_type='TEXT_EDITOR'
134 view3d_to_text_area.spaces.active.show_region_ui = True
136 spreadsheet_to_console_area.ui_type = 'CONSOLE'
137 override['window'] = pov_window
138 override['screen'] = bpy.context.screen
139 override['area'] = spreadsheet_to_console_area
140 override['region'] = spreadsheet_to_console_area.regions[-1]
141 bpy.ops.screen.space_type_set_or_cycle(
142 override, 'INVOKE_DEFAULT', space_type='CONSOLE'
144 space = properties_area.spaces.active
145 space.context = 'RENDER'
146 bpy.ops.workspace.reorder_to_front({'workspace': available_workspaces['POV-Ed']})
147 except AttributeError:
148 # In case necessary area types lack in existing blend files
149 pass
151 if 'POV-Mo'not in available_workspaces:
152 try:
153 if all(tab not in available_workspaces for tab in ['Rendering', 'POV-Mo']):
154 bpy.ops.workspace.append_activate(
155 idname='Rendering',
156 filepath=os.path.join(bpy.utils.user_resource('CONFIG'), 'startup.blend')
158 except BaseException as e:
159 print(e.__doc__)
160 print('An exception occurred: {}'.format(e))
161 try:
162 # Last resort: try to import from the blender templates
163 for p in Path(next(bpy.utils.app_template_paths())).rglob("startup.blend"):
164 bpy.ops.workspace.append_activate(
165 idname=self.targetWorkspace,
166 filepath=str(p))
167 except BaseException as e:
168 print(e.__doc__)
169 print('An exception occurred: {}'.format(e))
170 # Giving up
171 print(
172 "\nFactory 'Rendering' workspace needed for POV GUI centric"
173 "\nworkspace to activate when POV is set as default renderer"
175 finally:
176 # Create Moray like workspace (GUI oriented editing)
177 if 'POV-Mo' not in available_workspaces and 'Rendering' in available_workspaces:
178 wsp1 = available_workspaces.get('Rendering')
179 context = bpy.context
180 if context.scene.render.engine == 'POVRAY_RENDER' and wsp1 is not None:
181 bpy.ops.workspace.duplicate({'workspace': wsp1})
182 available_workspaces['Rendering.001'].name = 'POV-Mo'
183 # Already done it would seem, but explicitly make this workspace the active one
184 context.window.workspace = available_workspaces['POV-Mo']
185 pov_screen = available_workspaces['POV-Mo'].screens[0]
186 pov_workspace = pov_screen.areas
187 pov_window = context.window
188 # override = bpy.context.copy() # crashes
189 override = {}
190 properties_area = pov_workspace[0]
191 image_editor_to_view3d_area = pov_workspace[2]
193 try:
194 image_editor_to_view3d_area.ui_type = 'VIEW_3D'
195 override['window'] = pov_window
196 override['screen'] = bpy.context.screen
197 override['area'] = image_editor_to_view3d_area
198 override['region'] = image_editor_to_view3d_area.regions[-1]
199 bpy.ops.screen.space_type_set_or_cycle(
200 override, 'INVOKE_DEFAULT', space_type='VIEW_3D'
202 space = image_editor_to_view3d_area.spaces.active # Uncomment For non quad view
203 space.region_3d.view_perspective = 'CAMERA' # Uncomment For non quad view
204 space.show_region_toolbar = True
205 # bpy.ops.view3d.camera_to_view(override) # Uncomment For non quad view ?
206 for num, reg in enumerate(image_editor_to_view3d_area.regions):
207 if reg.type != 'view3d':
208 override['region'] = image_editor_to_view3d_area.regions[num]
209 bpy.ops.screen.region_quadview(override) # Comment out for non quad
210 propspace = properties_area.spaces.active
211 propspace.context = 'MATERIAL'
212 bpy.ops.workspace.reorder_to_front({'workspace': available_workspaces['POV-Mo']})
213 except (AttributeError, TypeError):
214 # In case necessary types lack in existing blend files
215 pass
216 # available_workspaces.update()
218 # -----------------------------------UTF-8---------------------------------- #
219 # Check and fix all strings in current .blend file to be valid UTF-8 Unicode
220 # sometimes needed for old, 2.4x / 2.6x area files
221 try:
222 bpy.ops.wm.blend_strings_utf8_validate()
223 except BaseException as e:
224 print(e.__doc__)
225 print('An exception occurred: {}'.format(e))
226 pass
229 def check_material(mat):
230 """Allow use of material properties buttons rather than nodes."""
231 if mat is not None:
232 if mat.use_nodes:
233 return not mat.node_tree
234 return True
235 return False
238 def simple_material(mat):
239 """Test if a material is nodeless."""
240 return (mat is not None) and (not mat.use_nodes)
243 def pov_context_texblock(context):
244 """Recreate texture context type as deprecated in blender 2.8."""
245 idblock = context.brush
246 if idblock and context.scene.texture_context == 'OTHER':
247 return idblock
249 # idblock = bpy.context.active_object.active_material
250 idblock = context.view_layer.objects.active.active_material
251 if idblock and context.scene.texture_context == 'MATERIAL':
252 return idblock
254 idblock = context.scene.world
255 if idblock and context.scene.texture_context == 'WORLD':
256 return idblock
258 idblock = context.light
259 if idblock and context.scene.texture_context == 'LIGHT':
260 return idblock
262 if context.particle_system and context.scene.texture_context == 'PARTICLES':
263 idblock = context.particle_system.settings
264 return idblock
266 idblock = context.line_style
267 if idblock and context.scene.texture_context == 'LINESTYLE':
268 return idblock
271 # class TextureTypePanel(TextureButtonsPanel):
273 # @classmethod
274 # def poll(cls, context):
275 # tex = context.texture
276 # engine = context.scene.render.engine
277 # return tex and ((tex.type == cls.tex_type and not tex.use_nodes) and (engine in cls.COMPAT_ENGINES))
280 def register():
281 update_files.register()
282 render_gui.register()
283 scenography_gui.register()
284 object_gui.register()
285 shading_gui.register()
286 texturing_gui.register()
287 shading_nodes.register()
288 scripting_gui.register()
290 if pov_centric_moray_like_workspace not in bpy.app.handlers.load_post:
291 bpy.app.handlers.load_post.append(pov_centric_moray_like_workspace)
294 def unregister():
295 if pov_centric_moray_like_workspace in bpy.app.handlers.load_post:
296 bpy.app.handlers.load_post.remove(pov_centric_moray_like_workspace)
298 scripting_gui.unregister()
299 shading_nodes.unregister()
300 texturing_gui.unregister()
301 shading_gui.unregister()
302 object_gui.unregister()
303 scenography_gui.unregister()
304 render_gui.unregister()
305 update_files.unregister()