Cleanup: simplify file name incrementing logic
[blender-addons.git] / space_view3d_stored_views / ui.py
blobc4c41707b619fd878d363675f261c6ed4eb732d8
1 # gpl authors: nfloyd, Francesco Siddi
3 import logging
4 module_logger = logging.getLogger(__name__)
6 import bpy
7 import blf
8 from . import core
9 from bpy.types import (
10 Operator,
11 Panel,
14 """
15 If view name display is enabled,
16 it will check periodically if the view has been modified
17 since last set.
18 get_preferences_timer() is the time in seconds between these checks.
19 It can be increased, if the view become sluggish
20 It is set in the add-on preferences
21 """
24 # Utility function get_preferences_timer for update of 3d view draw
25 def get_preferences_timer():
26 # replace the key if the add-on name changes
27 # TODO: expose refresh rate to ui???
28 addon = bpy.context.preferences.addons[__package__]
29 timer_update = (addon.preferences.view_3d_update_rate if addon else False)
31 return timer_update
34 def init_draw(context=None):
35 if context is None:
36 context = bpy.context
38 if "stored_views_osd" not in context.window_manager:
39 context.window_manager["stored_views_osd"] = False
41 if not context.window_manager["stored_views_osd"]:
42 context.window_manager["stored_views_osd"] = True
43 bpy.ops.stored_views.draw()
46 def _draw_callback_px(self, context):
47 if context.area and context.area.type == 'VIEW_3D':
48 r_width = text_location = context.region.width
49 r_height = context.region.height
50 font_id = 0 # TODO: need to find out how best to get font_id
52 blf.size(font_id, 11, context.preferences.system.dpi)
53 text_size = blf.dimensions(0, self.view_name)
55 # compute the text location
56 text_location = 0
57 overlap = context.preferences.system.use_region_overlap
58 if overlap:
59 for region in context.area.regions:
60 if region.type == "UI":
61 text_location = r_width - region.width
63 text_x = text_location - text_size[0] - 10
64 text_y = r_height - text_size[1] - 8
65 blf.position(font_id, text_x, text_y, 0)
66 blf.draw(font_id, self.view_name)
69 class VIEW3D_stored_views_draw(Operator):
70 bl_idname = "stored_views.draw"
71 bl_label = "Show current"
72 bl_description = "Toggle the display current view name in the view 3D"
74 _handle = None
75 _timer = None
77 @staticmethod
78 def handle_add(self, context):
79 VIEW3D_stored_views_draw._handle = bpy.types.SpaceView3D.draw_handler_add(
80 _draw_callback_px, (self, context), 'WINDOW', 'POST_PIXEL')
81 VIEW3D_stored_views_draw._timer = \
82 context.window_manager.event_timer_add(get_preferences_timer(), window=context.window)
84 @staticmethod
85 def handle_remove(context):
86 if VIEW3D_stored_views_draw._handle is not None:
87 bpy.types.SpaceView3D.draw_handler_remove(VIEW3D_stored_views_draw._handle, 'WINDOW')
88 if VIEW3D_stored_views_draw._timer is not None:
89 context.window_manager.event_timer_remove(VIEW3D_stored_views_draw._timer)
90 VIEW3D_stored_views_draw._handle = None
91 VIEW3D_stored_views_draw._timer = None
93 @classmethod
94 def poll(cls, context):
95 # return context.mode == 'OBJECT'
96 return True
98 def modal(self, context, event):
99 if context.area:
100 context.area.tag_redraw()
102 if not context.area or context.area.type != "VIEW_3D":
103 return {"PASS_THROUGH"}
105 data = core.DataStore()
106 stored_views = context.scene.stored_views
108 if len(data.list) > 0 and \
109 data.current_index >= 0 and \
110 not stored_views.view_modified:
112 if not stored_views.view_modified:
113 sv = data.list[data.current_index]
114 self.view_name = sv.name
115 if event.type == 'TIMER':
116 is_modified = False
117 if data.mode == 'VIEW':
118 is_modified = core.View.is_modified(context, sv)
119 elif data.mode == 'POV':
120 is_modified = core.POV.is_modified(context, sv)
121 elif data.mode == 'LAYERS':
122 is_modified = core.Layers.is_modified(context, sv)
123 elif data.mode == 'DISPLAY':
124 is_modified = core.Display.is_modified(context, sv)
125 if is_modified:
126 module_logger.debug(
127 'view modified - index: %s name: %s' % (data.current_index, sv.name)
129 self.view_name = ""
130 stored_views.view_modified = is_modified
132 return {"PASS_THROUGH"}
133 else:
134 module_logger.debug('exit')
135 context.window_manager["stored_views_osd"] = False
136 VIEW3D_stored_views_draw.handle_remove(context)
138 return {'FINISHED'}
140 def execute(self, context):
141 if context.area.type == "VIEW_3D":
142 self.view_name = ""
143 VIEW3D_stored_views_draw.handle_add(self, context)
144 context.window_manager.modal_handler_add(self)
146 return {"RUNNING_MODAL"}
147 else:
148 self.report({"WARNING"}, "View3D not found. Operation Cancelled")
150 return {"CANCELLED"}
153 class VIEW3D_PT_properties_stored_views(Panel):
154 bl_label = "Stored Views"
155 bl_space_type = "VIEW_3D"
156 bl_region_type = "UI"
157 bl_category = "View"
158 bl_options = {'DEFAULT_CLOSED'}
160 def draw(self, context):
161 self.logger = logging.getLogger('%s Properties panel' % __name__)
162 layout = self.layout
164 if bpy.ops.view3d.stored_views_initialize.poll():
165 layout.operator("view3d.stored_views_initialize")
166 return
168 stored_views = context.scene.stored_views
170 # UI : mode
171 col = layout.column(align=True)
172 col.prop_enum(stored_views, "mode", 'VIEW')
173 row = layout.row(align=True)
174 row.operator("view3d.camera_to_view", text="Camera To view")
175 row.operator("stored_views.newcamera")
177 row = col.row(align=True)
178 row.prop_enum(stored_views, "mode", 'POV')
179 # row.prop_enum(stored_views, "mode", 'LAYERS')
180 # row.prop_enum(stored_views, "mode", 'DISPLAY')
182 # UI : operators
183 row = layout.row()
184 row.operator("stored_views.save").index = -1
186 # IO Operators
187 if core.get_preferences():
188 row = layout.row(align=True)
189 row.operator("stored_views.import_from_scene", text="Import from Scene")
190 row.operator("stored_views.import_blsv", text="", icon="IMPORT")
191 row.operator("stored_views.export_blsv", text="", icon="EXPORT")
193 data_store = core.DataStore()
194 list = data_store.list
195 # UI : items list
196 if len(list) > 0:
197 row = layout.row()
198 box = row.box()
199 # items list
200 mode = stored_views.mode
201 for i in range(len(list)):
202 # associated icon
203 icon_string = "MESH_CUBE" # default icon
204 # TODO: icons for view
205 if mode == 'POV':
206 persp = list[i].perspective
207 if persp == 'PERSP':
208 icon_string = "MESH_CUBE"
209 elif persp == 'ORTHO':
210 icon_string = "MESH_PLANE"
211 elif persp == 'CAMERA':
212 if list[i].camera_type != 'CAMERA':
213 icon_string = 'OBJECT_DATAMODE'
214 else:
215 icon_string = "OUTLINER_DATA_CAMERA"
216 if mode == 'LAYERS':
217 if list[i].lock_camera_and_layers is True:
218 icon_string = 'SCENE_DATA'
219 else:
220 icon_string = 'RENDERLAYERS'
221 if mode == 'DISPLAY':
222 shade = list[i].viewport_shade
223 if shade == 'TEXTURED':
224 icon_string = 'TEXTURE_SHADED'
225 if shade == 'MATERIAL':
226 icon_string = 'MATERIAL_DATA'
227 elif shade == 'SOLID':
228 icon_string = 'SOLID'
229 elif shade == 'WIREFRAME':
230 icon_string = "WIRE"
231 elif shade == 'BOUNDBOX':
232 icon_string = 'BBOX'
233 elif shade == 'RENDERED':
234 icon_string = 'MATERIAL'
235 # stored view row
236 subrow = box.row(align=True)
237 # current view indicator
238 if data_store.current_index == i and context.scene.stored_views.view_modified is False:
239 subrow.label(text="", icon='SMALL_TRI_RIGHT_VEC')
240 subrow.operator("stored_views.set",
241 text="", icon=icon_string).index = i
242 subrow.prop(list[i], "name", text="")
243 subrow.operator("stored_views.save",
244 text="", icon="REC").index = i
245 subrow.operator("stored_views.delete",
246 text="", icon="PANEL_CLOSE").index = i
248 layout = self.layout
249 scene = context.scene
250 layout.label(text="Camera Selector")
251 cameras = sorted([o for o in scene.objects if o.type == 'CAMERA'],
252 key=lambda o: o.name)
254 if len(cameras) > 0:
255 for camera in cameras:
256 row = layout.row(align=True)
257 row.context_pointer_set("active_object", camera)
258 row.operator("cameraselector.set_scene_camera",
259 text=camera.name, icon='OUTLINER_DATA_CAMERA')
260 row.operator("cameraselector.preview_scene_camera",
261 text='', icon='RESTRICT_VIEW_OFF')
262 row.operator("cameraselector.add_camera_marker",
263 text='', icon='MARKER')
264 else:
265 layout.label(text="No cameras in this scene")
267 classes = (
268 VIEW3D_stored_views_draw,
269 VIEW3D_PT_properties_stored_views
272 def register():
273 for cls in classes:
274 bpy.utils.register_class(cls)
276 def unregister():
277 for cls in classes:
278 bpy.utils.unregister_class(cls)