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."""
8 # from time import sleep
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 (
29 # from bl_operators.presets import AddPresetBase
37 nodes
, # for POV specific nodes
43 # ------------ POV-Centric WORKSPACE ------------ #
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.
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
64 bpy
.ops
.wm
.blend_strings_utf8_validate()
65 except BaseException
as e
:
67 print("An exception occurred: {}".format(e
))
69 # --------------------------------Workspaces------------------------------- #
71 # If this file is not the default do nothing so as to not mess up project dependant workspaces
75 available_workspaces
= bpy
.data
.workspaces
77 if all(tabs
in available_workspaces
for tabs
in ["POV-Mo", "POV-Ed"]):
79 "\nPOV-Mo and POV-Ed tabs respectively provide GUI and TEXT\n"
80 "oriented POV workspaces akin to Moray and POVWIN"
83 if "POV-Ed" not in available_workspaces
:
85 "\nTo use POV centric workspaces you can set POV render option\n"
86 "and save it with File > Defaults > Save Startup File menu"
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
:
99 print("An exception occurred: {}".format(e
))
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
:
106 print("An exception occurred: {}".format(e
))
107 # Giving up as prerequisites can't be found
109 "\nFactory Geometry Nodes workspace needed for POV text centric"
110 "\nworkspace to activate when POV is set as default renderer"
113 # Create POVWIN like editor (text oriented editing)
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()
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
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]
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
177 if "POV-Mo" not in available_workspaces
:
179 if all(tab
not in available_workspaces
for tab
in ["Rendering", "POV-Mo"]):
180 bpy
.ops
.workspace
.append_activate(
182 filepath
=os
.path
.join(bpy
.utils
.user_resource("CONFIG"), "startup.blend"),
184 except BaseException
as e
:
186 print("An exception occurred: {}".format(e
))
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
:
193 print("An exception occurred: {}".format(e
))
196 "\nFactory 'Rendering' workspace needed for POV GUI centric"
197 "\nworkspace to activate when POV is set as default renderer"
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()
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
217 properties_area
= pov_workspace
[0]
218 image_editor_to_view3d_area
= pov_workspace
[2]
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"
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
249 # available_workspaces.update()
252 # class TextureTypePanel(TextureButtonsPanel):
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))
262 update_files
.register()
263 render_gui
.register()
264 scenography_gui
.register()
266 shading_gui
.register()
267 texturing_gui
.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
)
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()
281 texturing_gui
.unregister()
282 shading_gui
.unregister()
283 model_gui
.unregister()
284 scenography_gui
.unregister()
285 render_gui
.unregister()
286 update_files
.unregister()