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