Import images: add file handler
[blender-addons.git] / render_povray / ui_core.py
blobe621e8a45a60c289bf5d9e586f0ee45274ff8aa4
1 # SPDX-FileCopyrightText: 2022-2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
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 model_gui,
35 shading_gui,
36 texturing_gui,
37 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
60 # -----------------------------------UTF-8---------------------------------- #
61 # Check and fix all strings in current .blend file to be valid UTF-8 Unicode
62 # sometimes needed for old, 2.4x / 2.6x area files
63 try:
64 bpy.ops.wm.blend_strings_utf8_validate()
65 except BaseException as e:
66 print(e.__doc__)
67 print("An exception occurred: {}".format(e))
68 pass
69 # --------------------------------Workspaces------------------------------- #
71 # If this file is not the default do nothing so as to not mess up project dependant workspaces
72 if bpy.data.filepath:
73 return
75 available_workspaces = bpy.data.workspaces
77 if all(tabs in available_workspaces for tabs in ["POV-Mo", "POV-Ed"]):
78 print(
79 "\nPOV-Mo and POV-Ed tabs respectively provide GUI and TEXT\n"
80 "oriented POV workspaces akin to Moray and POVWIN"
82 return
83 if "POV-Ed" not in available_workspaces:
84 print(
85 "\nTo use POV centric workspaces you can set POV render option\n"
86 "and save it with File > Defaults > Save Startup File menu"
88 try:
89 if all(
90 othertabs not in available_workspaces
91 for othertabs in ["Geometry Nodes", "POV-Ed"]
93 bpy.ops.workspace.append_activate(
94 idname="Geometry Nodes",
95 filepath=os.path.join(bpy.utils.user_resource("CONFIG"), "startup.blend"),
97 except BaseException as e:
98 print(e.__doc__)
99 print("An exception occurred: {}".format(e))
100 try:
101 # Last resort: try to import from the blender templates
102 for p in Path(next(bpy.utils.app_template_paths())).rglob("startup.blend"):
103 bpy.ops.workspace.append_activate(idname="Geometry Nodes", filepath=str(p))
104 except BaseException as e:
105 print(e.__doc__)
106 print("An exception occurred: {}".format(e))
107 # Giving up as prerequisites can't be found
108 print(
109 "\nFactory Geometry Nodes workspace needed for POV text centric"
110 "\nworkspace to activate when POV is set as default renderer"
112 finally:
113 # Create POVWIN like editor (text oriented editing)
114 if (
115 "POV-Ed" not in available_workspaces
116 and "Geometry Nodes" in available_workspaces
118 wsp = available_workspaces.get("Geometry Nodes")
119 context = bpy.context
120 if context.scene.render.engine == "POVRAY_RENDER" and wsp is not None:
121 context_override = {"workspace": wsp}
122 with context.temp_override(**context_override):
123 bpy.ops.workspace.duplicate()
124 del context_override
125 available_workspaces["Geometry Nodes.001"].name = "POV-Ed"
126 # May be already done, but explicitly make this workspace the active one
127 context.window.workspace = available_workspaces["POV-Ed"]
128 pov_screen = available_workspaces["POV-Ed"].screens[0]
129 pov_workspace = pov_screen.areas
130 pov_window = context.window
131 # override = bpy.context.copy() # crashes
132 override = {}
133 properties_area = pov_workspace[0]
134 nodes_to_3dview_area = pov_workspace[1]
135 view3d_to_text_area = pov_workspace[2]
136 spreadsheet_to_console_area = pov_workspace[3]
138 try:
139 nodes_to_3dview_area.ui_type = "VIEW_3D"
140 override["window"] = pov_window
141 override["screen"] = bpy.context.screen
142 override["area"] = nodes_to_3dview_area
143 override["region"] = nodes_to_3dview_area.regions[-1]
144 bpy.ops.screen.space_type_set_or_cycle(
145 override, "INVOKE_DEFAULT", space_type="VIEW_3D"
147 space = nodes_to_3dview_area.spaces.active
148 space.region_3d.view_perspective = "CAMERA"
150 override["window"] = pov_window
151 override["screen"] = bpy.context.screen
152 override["area"] = view3d_to_text_area
153 override["region"] = view3d_to_text_area.regions[-1]
154 override["scene"] = bpy.context.scene
155 override["space_data"] = view3d_to_text_area.spaces.active
156 bpy.ops.screen.space_type_set_or_cycle(
157 override, "INVOKE_DEFAULT", space_type="TEXT_EDITOR"
159 view3d_to_text_area.spaces.active.show_region_ui = True
161 spreadsheet_to_console_area.ui_type = "CONSOLE"
162 override["window"] = pov_window
163 override["screen"] = bpy.context.screen
164 override["area"] = spreadsheet_to_console_area
165 override["region"] = spreadsheet_to_console_area.regions[-1]
166 bpy.ops.screen.space_type_set_or_cycle(
167 override, "INVOKE_DEFAULT", space_type="CONSOLE"
169 space = properties_area.spaces.active
170 space.context = "RENDER"
171 bpy.ops.workspace.reorder_to_front(
172 {"workspace": available_workspaces["POV-Ed"]}
174 except AttributeError:
175 # In case necessary area types lack in existing blend files
176 pass
177 if "POV-Mo" not in available_workspaces:
178 try:
179 if all(tab not in available_workspaces for tab in ["Rendering", "POV-Mo"]):
180 bpy.ops.workspace.append_activate(
181 idname="Rendering",
182 filepath=os.path.join(bpy.utils.user_resource("CONFIG"), "startup.blend"),
184 except BaseException as e:
185 print(e.__doc__)
186 print("An exception occurred: {}".format(e))
187 try:
188 # Last resort: try to import from the blender templates
189 for p in Path(next(bpy.utils.app_template_paths())).rglob("startup.blend"):
190 bpy.ops.workspace.append_activate(idname="Rendering", filepath=str(p))
191 except BaseException as e:
192 print(e.__doc__)
193 print("An exception occurred: {}".format(e))
194 # Giving up
195 print(
196 "\nFactory 'Rendering' workspace needed for POV GUI centric"
197 "\nworkspace to activate when POV is set as default renderer"
199 finally:
200 # Create Moray like workspace (GUI oriented editing)
201 if "POV-Mo" not in available_workspaces and "Rendering" in available_workspaces:
202 wsp1 = available_workspaces.get("Rendering")
203 context = bpy.context
204 if context.scene.render.engine == "POVRAY_RENDER" and wsp1 is not None:
205 context_override = {"workspace": wsp1}
206 with context.temp_override(**context_override):
207 bpy.ops.workspace.duplicate()
208 del context_override
209 available_workspaces["Rendering.001"].name = "POV-Mo"
210 # Already done it would seem, but explicitly make this workspace the active one
211 context.window.workspace = available_workspaces["POV-Mo"]
212 pov_screen = available_workspaces["POV-Mo"].screens[0]
213 pov_workspace = pov_screen.areas
214 pov_window = context.window
215 # override = bpy.context.copy() # crashes
216 override = {}
217 properties_area = pov_workspace[0]
218 image_editor_to_view3d_area = pov_workspace[2]
220 try:
221 image_editor_to_view3d_area.ui_type = "VIEW_3D"
222 override["window"] = pov_window
223 override["screen"] = bpy.context.screen
224 override["area"] = image_editor_to_view3d_area
225 override["region"] = image_editor_to_view3d_area.regions[-1]
226 bpy.ops.screen.space_type_set_or_cycle(
227 override, "INVOKE_DEFAULT", space_type="VIEW_3D"
229 space = (
230 image_editor_to_view3d_area.spaces.active
231 ) # Uncomment For non quad view
232 space.region_3d.view_perspective = (
233 "CAMERA" # Uncomment For non quad view
235 space.show_region_toolbar = True
236 # bpy.ops.view3d.camera_to_view(override) # Uncomment For non quad view ?
237 for num, reg in enumerate(image_editor_to_view3d_area.regions):
238 if reg.type != "view3d":
239 override["region"] = image_editor_to_view3d_area.regions[num]
240 bpy.ops.screen.region_quadview(override) # Comment out for non quad
241 propspace = properties_area.spaces.active
242 propspace.context = "MATERIAL"
243 bpy.ops.workspace.reorder_to_front(
244 {"workspace": available_workspaces["POV-Mo"]}
246 except (AttributeError, TypeError):
247 # In case necessary types lack in existing blend files
248 pass
249 # available_workspaces.update()
252 # class TextureTypePanel(TextureButtonsPanel):
254 # @classmethod
255 # def poll(cls, context):
256 # tex = context.texture
257 # engine = context.scene.render.engine
258 # return tex and ((tex.type == cls.tex_type and not tex.use_nodes) and (engine in cls.COMPAT_ENGINES))
261 def register():
262 update_files.register()
263 render_gui.register()
264 scenography_gui.register()
265 model_gui.register()
266 shading_gui.register()
267 texturing_gui.register()
268 nodes.register()
269 scripting_gui.register()
271 if pov_centric_moray_like_workspace not in bpy.app.handlers.load_post:
272 bpy.app.handlers.load_post.append(pov_centric_moray_like_workspace)
275 def unregister():
276 if pov_centric_moray_like_workspace in bpy.app.handlers.load_post:
277 bpy.app.handlers.load_post.remove(pov_centric_moray_like_workspace)
279 scripting_gui.unregister()
280 nodes.unregister()
281 texturing_gui.unregister()
282 shading_gui.unregister()
283 model_gui.unregister()
284 scenography_gui.unregister()
285 render_gui.unregister()
286 update_files.unregister()