diff options
Diffstat (limited to 'space_view3d_stored_views/ui.py')
-rw-r--r-- | space_view3d_stored_views/ui.py | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/space_view3d_stored_views/ui.py b/space_view3d_stored_views/ui.py new file mode 100644 index 00000000..43f3d470 --- /dev/null +++ b/space_view3d_stored_views/ui.py @@ -0,0 +1,277 @@ +# gpl authors: nfloyd, Francesco Siddi + +import logging +module_logger = logging.getLogger(__name__) + +import bpy +import blf +from . import core +from bpy.types import ( + Operator, + Panel, +) + +""" + If view name display is enabled, + it will check periodically if the view has been modified + since last set. + get_preferences_timer() is the time in seconds between these checks. + It can be increased, if the view become sluggish + It is set in the add-on preferences +""" + + +# Utility function get_preferences_timer for update of 3d view draw +def get_preferences_timer(): + # replace the key if the add-on name changes + # TODO: expose refresh rate to ui??? + addon = bpy.context.preferences.addons[__package__] + timer_update = (addon.preferences.view_3d_update_rate if addon else False) + + return timer_update + + +def init_draw(context=None): + if context is None: + context = bpy.context + + if "stored_views_osd" not in context.window_manager: + context.window_manager["stored_views_osd"] = False + + if not context.window_manager["stored_views_osd"]: + context.window_manager["stored_views_osd"] = True + bpy.ops.stored_views.draw() + + +def _draw_callback_px(self, context): + if context.area and context.area.type == 'VIEW_3D': + r_width = text_location = context.region.width + r_height = context.region.height + font_id = 0 # TODO: need to find out how best to get font_id + + blf.size(font_id, 11, context.preferences.system.dpi) + text_size = blf.dimensions(0, self.view_name) + + # compute the text location + text_location = 0 + overlap = context.preferences.system.use_region_overlap + if overlap: + for region in context.area.regions: + if region.type == "UI": + text_location = r_width - region.width + + text_x = text_location - text_size[0] - 10 + text_y = r_height - text_size[1] - 8 + blf.position(font_id, text_x, text_y, 0) + blf.draw(font_id, self.view_name) + + +class VIEW3D_stored_views_draw(Operator): + bl_idname = "stored_views.draw" + bl_label = "Show current" + bl_description = "Toggle the display current view name in the view 3D" + + _handle = None + _timer = None + + @staticmethod + def handle_add(self, context): + VIEW3D_stored_views_draw._handle = bpy.types.SpaceView3D.draw_handler_add( + _draw_callback_px, (self, context), 'WINDOW', 'POST_PIXEL') + VIEW3D_stored_views_draw._timer = \ + context.window_manager.event_timer_add(get_preferences_timer(), window=context.window) + + @staticmethod + def handle_remove(context): + if VIEW3D_stored_views_draw._handle is not None: + bpy.types.SpaceView3D.draw_handler_remove(VIEW3D_stored_views_draw._handle, 'WINDOW') + if VIEW3D_stored_views_draw._timer is not None: + context.window_manager.event_timer_remove(VIEW3D_stored_views_draw._timer) + VIEW3D_stored_views_draw._handle = None + VIEW3D_stored_views_draw._timer = None + + @classmethod + def poll(cls, context): + # return context.mode == 'OBJECT' + return True + + def modal(self, context, event): + if context.area: + context.area.tag_redraw() + + if not context.area or context.area.type != "VIEW_3D": + return {"PASS_THROUGH"} + + data = core.DataStore() + stored_views = context.scene.stored_views + + if len(data.list) > 0 and \ + data.current_index >= 0 and \ + not stored_views.view_modified: + + if not stored_views.view_modified: + sv = data.list[data.current_index] + self.view_name = sv.name + if event.type == 'TIMER': + is_modified = False + if data.mode == 'VIEW': + is_modified = core.View.is_modified(context, sv) + elif data.mode == 'POV': + is_modified = core.POV.is_modified(context, sv) + elif data.mode == 'LAYERS': + is_modified = core.Layers.is_modified(context, sv) + elif data.mode == 'DISPLAY': + is_modified = core.Display.is_modified(context, sv) + if is_modified: + module_logger.debug( + 'view modified - index: %s name: %s' % (data.current_index, sv.name) + ) + self.view_name = "" + stored_views.view_modified = is_modified + + return {"PASS_THROUGH"} + else: + module_logger.debug('exit') + context.window_manager["stored_views_osd"] = False + VIEW3D_stored_views_draw.handle_remove(context) + + return {'FINISHED'} + + def execute(self, context): + if context.area.type == "VIEW_3D": + self.view_name = "" + VIEW3D_stored_views_draw.handle_add(self, context) + context.window_manager.modal_handler_add(self) + + return {"RUNNING_MODAL"} + else: + self.report({"WARNING"}, "View3D not found. Operation Cancelled") + + return {"CANCELLED"} + + +class VIEW3D_PT_properties_stored_views(Panel): + bl_label = "Stored Views" + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + bl_category = "StoredViews" + + def draw(self, context): + self.logger = logging.getLogger('%s Properties panel' % __name__) + layout = self.layout + + if bpy.ops.view3d.stored_views_initialize.poll(): + layout.operator("view3d.stored_views_initialize") + return + + stored_views = context.scene.stored_views + + # UI : mode + col = layout.column(align=True) + col.prop_enum(stored_views, "mode", 'VIEW') + row = layout.row(align=True) + row.operator("view3d.camera_to_view", text="Camera To view") + row.operator("stored_views.newcamera") + + row = col.row(align=True) + row.prop_enum(stored_views, "mode", 'POV') + # row.prop_enum(stored_views, "mode", 'LAYERS') + # row.prop_enum(stored_views, "mode", 'DISPLAY') + + # UI : operators + row = layout.row() + row.operator("stored_views.save").index = -1 + + # IO Operators + if core.get_preferences(): + row = layout.row(align=True) + row.operator("stored_views.import_from_scene", text="Import from Scene") + row.operator("stored_views.import_blsv", text="", icon="IMPORT") + row.operator("stored_views.export_blsv", text="", icon="EXPORT") + + data_store = core.DataStore() + list = data_store.list + # UI : items list + if len(list) > 0: + row = layout.row() + box = row.box() + # items list + mode = stored_views.mode + for i in range(len(list)): + # associated icon + icon_string = "MESH_CUBE" # default icon + # TODO: icons for view + if mode == 'POV': + persp = list[i].perspective + if persp == 'PERSP': + icon_string = "MESH_CUBE" + elif persp == 'ORTHO': + icon_string = "MESH_PLANE" + elif persp == 'CAMERA': + if list[i].camera_type != 'CAMERA': + icon_string = 'OBJECT_DATAMODE' + else: + icon_string = "OUTLINER_DATA_CAMERA" + if mode == 'LAYERS': + if list[i].lock_camera_and_layers is True: + icon_string = 'SCENE_DATA' + else: + icon_string = 'RENDERLAYERS' + if mode == 'DISPLAY': + shade = list[i].viewport_shade + if shade == 'TEXTURED': + icon_string = 'TEXTURE_SHADED' + if shade == 'MATERIAL': + icon_string = 'MATERIAL_DATA' + elif shade == 'SOLID': + icon_string = 'SOLID' + elif shade == 'WIREFRAME': + icon_string = "WIRE" + elif shade == 'BOUNDBOX': + icon_string = 'BBOX' + elif shade == 'RENDERED': + icon_string = 'MATERIAL' + # stored view row + subrow = box.row(align=True) + # current view indicator + if data_store.current_index == i and context.scene.stored_views.view_modified is False: + subrow.label(text="", icon='SMALL_TRI_RIGHT_VEC') + subrow.operator("stored_views.set", + text="", icon=icon_string).index = i + subrow.prop(list[i], "name", text="") + subrow.operator("stored_views.save", + text="", icon="REC").index = i + subrow.operator("stored_views.delete", + text="", icon="PANEL_CLOSE").index = i + + layout = self.layout + scene = context.scene + layout.label(text="Camera Selector") + cameras = sorted([o for o in scene.objects if o.type == 'CAMERA'], + key=lambda o: o.name) + + if len(cameras) > 0: + for camera in cameras: + row = layout.row(align=True) + row.context_pointer_set("active_object", camera) + row.operator("cameraselector.set_scene_camera", + text=camera.name, icon='OUTLINER_DATA_CAMERA') + row.operator("cameraselector.preview_scene_camera", + text='', icon='RESTRICT_VIEW_OFF') + row.operator("cameraselector.add_camera_marker", + text='', icon='MARKER') + else: + layout.label(text="No cameras in this scene") + +classes = ( + VIEW3D_stored_views_draw, + VIEW3D_PT_properties_stored_views +) + +def register(): + for cls in classes: + bpy.utils.register_class(cls) + +def unregister(): + for cls in classes: + bpy.utils.unregister_class(cls) |