1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # Authors: nfloyd, Francesco Siddi
6 module_logger
= logging
.getLogger(__name__
)
11 from bpy
.types
import (
17 If view name display is enabled,
18 it will check periodically if the view has been modified
20 get_preferences_timer() is the time in seconds between these checks.
21 It can be increased, if the view become sluggish
22 It is set in the add-on preferences
26 # Utility function get_preferences_timer for update of 3d view draw
27 def get_preferences_timer():
28 # replace the key if the add-on name changes
29 # TODO: expose refresh rate to ui???
30 addon
= bpy
.context
.preferences
.addons
[__package__
]
31 timer_update
= (addon
.preferences
.view_3d_update_rate
if addon
else False)
36 def init_draw(context
=None):
40 if "stored_views_osd" not in context
.window_manager
:
41 context
.window_manager
["stored_views_osd"] = False
43 if not context
.window_manager
["stored_views_osd"]:
44 context
.window_manager
["stored_views_osd"] = True
45 bpy
.ops
.stored_views
.draw()
48 def _draw_callback_px(self
, context
):
49 if context
.area
and context
.area
.type == 'VIEW_3D':
50 r_width
= text_location
= context
.region
.width
51 r_height
= context
.region
.height
52 font_id
= 0 # TODO: need to find out how best to get font_id
54 blf
.size(font_id
, 11, context
.preferences
.system
.dpi
)
55 text_size
= blf
.dimensions(0, self
.view_name
)
57 # compute the text location
59 overlap
= context
.preferences
.system
.use_region_overlap
61 for region
in context
.area
.regions
:
62 if region
.type == "UI":
63 text_location
= r_width
- region
.width
65 text_x
= text_location
- text_size
[0] - 10
66 text_y
= r_height
- text_size
[1] - 8
67 blf
.position(font_id
, text_x
, text_y
, 0)
68 blf
.draw(font_id
, self
.view_name
)
71 class VIEW3D_stored_views_draw(Operator
):
72 bl_idname
= "stored_views.draw"
73 bl_label
= "Show current"
74 bl_description
= "Toggle the display current view name in the view 3D"
80 def handle_add(self
, context
):
81 VIEW3D_stored_views_draw
._handle
= bpy
.types
.SpaceView3D
.draw_handler_add(
82 _draw_callback_px
, (self
, context
), 'WINDOW', 'POST_PIXEL')
83 VIEW3D_stored_views_draw
._timer
= \
84 context
.window_manager
.event_timer_add(get_preferences_timer(), window
=context
.window
)
87 def handle_remove(context
):
88 if VIEW3D_stored_views_draw
._handle
is not None:
89 bpy
.types
.SpaceView3D
.draw_handler_remove(VIEW3D_stored_views_draw
._handle
, 'WINDOW')
90 if VIEW3D_stored_views_draw
._timer
is not None:
91 context
.window_manager
.event_timer_remove(VIEW3D_stored_views_draw
._timer
)
92 VIEW3D_stored_views_draw
._handle
= None
93 VIEW3D_stored_views_draw
._timer
= None
96 def poll(cls
, context
):
97 # return context.mode == 'OBJECT'
100 def modal(self
, context
, event
):
102 context
.area
.tag_redraw()
104 if not context
.area
or context
.area
.type != "VIEW_3D":
105 return {"PASS_THROUGH"}
107 data
= core
.DataStore()
108 stored_views
= context
.scene
.stored_views
110 if len(data
.list) > 0 and \
111 data
.current_index
>= 0 and \
112 not stored_views
.view_modified
:
114 if not stored_views
.view_modified
:
115 sv
= data
.list[data
.current_index
]
116 self
.view_name
= sv
.name
117 if event
.type == 'TIMER':
119 if data
.mode
== 'VIEW':
120 is_modified
= core
.View
.is_modified(context
, sv
)
121 elif data
.mode
== 'POV':
122 is_modified
= core
.POV
.is_modified(context
, sv
)
123 elif data
.mode
== 'LAYERS':
124 is_modified
= core
.Layers
.is_modified(context
, sv
)
125 elif data
.mode
== 'DISPLAY':
126 is_modified
= core
.Display
.is_modified(context
, sv
)
129 'view modified - index: %s name: %s' % (data
.current_index
, sv
.name
)
132 stored_views
.view_modified
= is_modified
134 return {"PASS_THROUGH"}
136 module_logger
.debug('exit')
137 context
.window_manager
["stored_views_osd"] = False
138 VIEW3D_stored_views_draw
.handle_remove(context
)
142 def execute(self
, context
):
143 if context
.area
.type == "VIEW_3D":
145 VIEW3D_stored_views_draw
.handle_add(self
, context
)
146 context
.window_manager
.modal_handler_add(self
)
148 return {"RUNNING_MODAL"}
150 self
.report({"WARNING"}, "View3D not found. Operation Cancelled")
155 class VIEW3D_PT_properties_stored_views(Panel
):
156 bl_label
= "Stored Views"
157 bl_space_type
= "VIEW_3D"
158 bl_region_type
= "UI"
160 bl_options
= {'DEFAULT_CLOSED'}
162 def draw(self
, context
):
163 self
.logger
= logging
.getLogger('%s Properties panel' % __name__
)
166 if bpy
.ops
.view3d
.stored_views_initialize
.poll():
167 layout
.operator("view3d.stored_views_initialize")
170 stored_views
= context
.scene
.stored_views
173 col
= layout
.column(align
=True)
174 col
.prop_enum(stored_views
, "mode", 'VIEW')
175 row
= layout
.row(align
=True)
176 row
.operator("view3d.camera_to_view", text
="Camera To view")
177 row
.operator("stored_views.newcamera")
179 row
= col
.row(align
=True)
180 row
.prop_enum(stored_views
, "mode", 'POV')
181 # row.prop_enum(stored_views, "mode", 'LAYERS')
182 # row.prop_enum(stored_views, "mode", 'DISPLAY')
186 row
.operator("stored_views.save").index
= -1
189 if core
.get_preferences():
190 row
= layout
.row(align
=True)
191 row
.operator("stored_views.import_from_scene", text
="Import from Scene")
192 row
.operator("stored_views.import_blsv", text
="", icon
="IMPORT")
193 row
.operator("stored_views.export_blsv", text
="", icon
="EXPORT")
195 data_store
= core
.DataStore()
196 list = data_store
.list
202 mode
= stored_views
.mode
203 for i
in range(len(list)):
205 icon_string
= "MESH_CUBE" # default icon
206 # TODO: icons for view
208 persp
= list[i
].perspective
210 icon_string
= "MESH_CUBE"
211 elif persp
== 'ORTHO':
212 icon_string
= "MESH_PLANE"
213 elif persp
== 'CAMERA':
214 if list[i
].camera_type
!= 'CAMERA':
215 icon_string
= 'OBJECT_DATAMODE'
217 icon_string
= "OUTLINER_DATA_CAMERA"
219 if list[i
].lock_camera_and_layers
is True:
220 icon_string
= 'SCENE_DATA'
222 icon_string
= 'RENDERLAYERS'
223 if mode
== 'DISPLAY':
224 shade
= list[i
].viewport_shade
225 if shade
== 'TEXTURED':
226 icon_string
= 'TEXTURE_SHADED'
227 if shade
== 'MATERIAL':
228 icon_string
= 'MATERIAL_DATA'
229 elif shade
== 'SOLID':
230 icon_string
= 'SOLID'
231 elif shade
== 'WIREFRAME':
233 elif shade
== 'BOUNDBOX':
235 elif shade
== 'RENDERED':
236 icon_string
= 'MATERIAL'
238 subrow
= box
.row(align
=True)
239 # current view indicator
240 if data_store
.current_index
== i
and context
.scene
.stored_views
.view_modified
is False:
241 subrow
.label(text
="", icon
='CHECKMARK')
242 subrow
.operator("stored_views.set",
243 text
="", icon
=icon_string
).index
= i
244 subrow
.prop(list[i
], "name", text
="")
245 subrow
.operator("stored_views.save",
246 text
="", icon
="REC").index
= i
247 subrow
.operator("stored_views.delete",
248 text
="", icon
="PANEL_CLOSE").index
= i
251 scene
= context
.scene
252 layout
.label(text
="Camera Selector")
253 cameras
= sorted([o
for o
in scene
.objects
if o
.type == 'CAMERA'],
254 key
=lambda o
: o
.name
)
257 for camera
in cameras
:
258 row
= layout
.row(align
=True)
259 row
.context_pointer_set("active_object", camera
)
260 row
.operator("cameraselector.set_scene_camera",
261 text
=camera
.name
, icon
='OUTLINER_DATA_CAMERA')
262 row
.operator("cameraselector.preview_scene_camera",
263 text
='', icon
='RESTRICT_VIEW_OFF')
264 row
.operator("cameraselector.add_camera_marker",
265 text
='', icon
='MARKER')
267 layout
.label(text
="No cameras in this scene")
270 VIEW3D_stored_views_draw
,
271 VIEW3D_PT_properties_stored_views
276 bpy
.utils
.register_class(cls
)
280 bpy
.utils
.unregister_class(cls
)