Fix T52833: OBJ triangulate doesn't match viewport
[blender-addons.git] / development_icon_get.py
bloba7740c3181404cec284538250abf6a491596c245
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
22 bl_info = {
23 "name": "Icon Viewer",
24 "description": "Click an icon to copy its name to the clipboard",
25 "author": "roaoao",
26 "version": (1, 3, 2),
27 "blender": (2, 75, 0),
28 "location": "Spacebar > Icon Viewer, Text Editor > Properties",
29 "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6"
30 "/Py/Scripts/Development/Display_All_Icons",
31 "category": "Development"
34 import bpy
35 import math
37 DPI = 72
38 POPUP_PADDING = 10
39 PANEL_PADDING = 44
40 WIN_PADDING = 32
41 ICON_SIZE = 20
42 HISTORY_SIZE = 100
43 HISTORY = []
46 def ui_scale():
47 prefs = bpy.context.user_preferences.system
48 return prefs.dpi * prefs.pixel_size / DPI
51 def prefs():
52 return bpy.context.user_preferences.addons[__name__].preferences
55 class Icons:
56 def __init__(self, is_popup=False):
57 self._filtered_icons = None
58 self._filter = ""
59 self.filter = ""
60 self.selected_icon = ""
61 self.is_popup = is_popup
63 @property
64 def filter(self):
65 return self._filter
67 @filter.setter
68 def filter(self, value):
69 if self._filter == value:
70 return
72 self._filter = value
73 self.update()
75 @property
76 def filtered_icons(self):
77 if self._filtered_icons is None:
78 self._filtered_icons = []
79 icon_filter = self._filter.upper()
80 self.filtered_icons.clear()
81 pr = prefs()
83 icons = bpy.types.UILayout.bl_rna.functions[
84 "prop"].parameters["icon"].enum_items.keys()
85 for icon in icons:
86 if icon == 'NONE' or \
87 icon_filter and icon_filter not in icon or \
88 not pr.show_brush_icons and "BRUSH_" in icon and \
89 icon != 'BRUSH_DATA' or \
90 not pr.show_matcap_icons and "MATCAP_" in icon or \
91 not pr.show_colorset_icons and "COLORSET_" in icon:
92 continue
93 self._filtered_icons.append(icon)
95 return self._filtered_icons
97 @property
98 def num_icons(self):
99 return len(self.filtered_icons)
101 def update(self):
102 if self._filtered_icons is not None:
103 self._filtered_icons.clear()
104 self._filtered_icons = None
106 def draw(self, layout, num_cols=0, icons=None):
107 if icons:
108 filtered_icons = reversed(icons)
109 else:
110 filtered_icons = self.filtered_icons
112 column = layout.column(True)
113 row = column.row(True)
114 row.alignment = 'CENTER'
116 selected_icon = self.selected_icon if self.is_popup else \
117 bpy.context.window_manager.clipboard
118 col_idx = 0
119 for i, icon in enumerate(filtered_icons):
120 p = row.operator(
121 IV_OT_icon_select.bl_idname, "",
122 icon=icon, emboss=icon == selected_icon)
123 p.icon = icon
124 p.force_copy_on_select = not self.is_popup
126 col_idx += 1
127 if col_idx > num_cols - 1:
128 if icons:
129 break
130 col_idx = 0
131 if i < len(filtered_icons) - 1:
132 row = column.row(True)
133 row.alignment = 'CENTER'
135 if col_idx != 0 and not icons and i >= num_cols:
136 sub = row.row(True)
137 sub.scale_x = num_cols - col_idx
138 sub.label("", icon='BLANK1')
140 if not filtered_icons:
141 row.label("No icons were found")
144 class IV_Preferences(bpy.types.AddonPreferences):
145 bl_idname = __name__
147 panel_icons = Icons()
148 popup_icons = Icons(is_popup=True)
150 def update_icons(self, context):
151 self.panel_icons.update()
152 self.popup_icons.update()
154 def set_panel_filter(self, value):
155 self.panel_icons.filter = value
157 panel_filter = bpy.props.StringProperty(
158 description="Filter",
159 default="",
160 get=lambda s: s.panel_icons.filter,
161 set=set_panel_filter,
162 options={'TEXTEDIT_UPDATE'})
163 show_panel_icons = bpy.props.BoolProperty(
164 name="Show Icons",
165 description="Show icons", default=True)
166 show_history = bpy.props.BoolProperty(
167 name="Show History",
168 description="Show history", default=True)
169 show_brush_icons = bpy.props.BoolProperty(
170 name="Show Brush Icons",
171 description="Show brush icons", default=True,
172 update=update_icons)
173 show_matcap_icons = bpy.props.BoolProperty(
174 name="Show Matcap Icons",
175 description="Show matcap icons", default=True,
176 update=update_icons)
177 show_colorset_icons = bpy.props.BoolProperty(
178 name="Show Colorset Icons",
179 description="Show colorset icons", default=True,
180 update=update_icons)
181 copy_on_select = bpy.props.BoolProperty(
182 name="Copy Icon On Click",
183 description="Copy icon on click", default=True)
184 close_on_select = bpy.props.BoolProperty(
185 name="Close Popup On Click",
186 description=(
187 "Close the popup on click.\n"
188 "Not supported by some windows (User Preferences, Render)"
190 default=False)
191 auto_focus_filter = bpy.props.BoolProperty(
192 name="Auto Focus Input Field",
193 description="Auto focus input field", default=True)
194 show_panel = bpy.props.BoolProperty(
195 name="Show Panel",
196 description="Show the panel in the Text Editor", default=True)
197 show_header = bpy.props.BoolProperty(
198 name="Show Header",
199 description="Show the header in the Python Console",
200 default=True)
202 def draw(self, context):
203 layout = self.layout
204 row = layout.row()
205 row.scale_y = 1.5
206 row.operator(IV_OT_icons_show.bl_idname)
208 row = layout.row()
210 col = row.column(True)
211 col.label("Icons:")
212 col.prop(self, "show_matcap_icons")
213 col.prop(self, "show_brush_icons")
214 col.prop(self, "show_colorset_icons")
215 col.separator()
216 col.prop(self, "show_history")
218 col = row.column(True)
219 col.label("Popup:")
220 col.prop(self, "auto_focus_filter")
221 col.prop(self, "copy_on_select")
222 if self.copy_on_select:
223 col.prop(self, "close_on_select")
225 col = row.column(True)
226 col.label("Panel:")
227 col.prop(self, "show_panel")
228 if self.show_panel:
229 col.prop(self, "show_panel_icons")
231 col.separator()
232 col.label("Header:")
233 col.prop(self, "show_header")
236 class IV_PT_icons(bpy.types.Panel):
237 bl_space_type = "TEXT_EDITOR"
238 bl_region_type = "UI"
239 bl_label = "Icon Viewer"
241 @staticmethod
242 def tag_redraw():
243 wm = bpy.context.window_manager
244 if not wm:
245 return
247 for w in wm.windows:
248 for a in w.screen.areas:
249 if a.type == 'TEXT_EDITOR':
250 for r in a.regions:
251 if r.type == 'UI':
252 r.tag_redraw()
254 def draw(self, context):
255 pr = prefs()
256 row = self.layout.row(True)
257 if pr.show_panel_icons:
258 row.prop(pr, "panel_filter", "", icon='VIEWZOOM')
259 else:
260 row.operator(IV_OT_icons_show.bl_idname)
261 row.operator(IV_OT_panel_menu_call.bl_idname, "", icon='COLLAPSEMENU')
263 _, y0 = context.region.view2d.region_to_view(0, 0)
264 _, y1 = context.region.view2d.region_to_view(0, 10)
265 region_scale = 10 / abs(y0 - y1)
267 num_cols = max(
269 (context.region.width - PANEL_PADDING) //
270 math.ceil(ui_scale() * region_scale * ICON_SIZE))
272 col = None
273 if HISTORY and pr.show_history:
274 col = self.layout.column(True)
275 pr.panel_icons.draw(col.box(), num_cols, HISTORY)
277 if pr.show_panel_icons:
278 col = col or self.layout.column(True)
279 pr.panel_icons.draw(col.box(), num_cols)
281 @classmethod
282 def poll(cls, context):
283 return prefs().show_panel
286 class IV_HT_icons(bpy.types.Header):
287 bl_space_type = 'CONSOLE'
289 def draw(self, context):
290 if not prefs().show_header:
291 return
292 layout = self.layout
293 layout.separator()
294 layout.operator(IV_OT_icons_show.bl_idname)
297 class IV_OT_panel_menu_call(bpy.types.Operator):
298 bl_idname = "iv.panel_menu_call"
299 bl_label = ""
300 bl_description = "Menu"
301 bl_options = {'INTERNAL'}
303 def menu(self, menu, context):
304 pr = prefs()
305 layout = menu.layout
306 layout.prop(pr, "show_panel_icons")
307 layout.prop(pr, "show_history")
309 if not pr.show_panel_icons:
310 return
312 layout.separator()
313 layout.prop(pr, "show_matcap_icons")
314 layout.prop(pr, "show_brush_icons")
315 layout.prop(pr, "show_colorset_icons")
317 def execute(self, context):
318 context.window_manager.popup_menu(self.menu, "Icon Viewer")
319 return {'FINISHED'}
322 class IV_OT_icon_select(bpy.types.Operator):
323 bl_idname = "iv.icon_select"
324 bl_label = ""
325 bl_description = "Select the icon"
326 bl_options = {'INTERNAL'}
328 icon = bpy.props.StringProperty()
329 force_copy_on_select = bpy.props.BoolProperty()
331 def execute(self, context):
332 pr = prefs()
333 pr.popup_icons.selected_icon = self.icon
334 if pr.copy_on_select or self.force_copy_on_select:
335 context.window_manager.clipboard = self.icon
336 self.report({'INFO'}, self.icon)
338 if pr.close_on_select and IV_OT_icons_show.instance:
339 IV_OT_icons_show.instance.close()
341 if pr.show_history:
342 if self.icon in HISTORY:
343 HISTORY.remove(self.icon)
344 if len(HISTORY) >= HISTORY_SIZE:
345 HISTORY.pop(0)
346 HISTORY.append(self.icon)
347 return {'FINISHED'}
350 class IV_OT_icons_show(bpy.types.Operator):
351 bl_idname = "iv.icons_show"
352 bl_label = "Icon Viewer"
353 bl_description = "Icon viewer"
354 bl_property = "filter_auto_focus"
356 instance = None
358 def set_filter(self, value):
359 prefs().popup_icons.filter = value
361 def set_selected_icon(self, value):
362 if IV_OT_icons_show.instance:
363 IV_OT_icons_show.instance.auto_focusable = False
365 filter_auto_focus = bpy.props.StringProperty(
366 description="Filter",
367 get=lambda s: prefs().popup_icons.filter,
368 set=set_filter,
369 options={'TEXTEDIT_UPDATE', 'SKIP_SAVE'})
370 filter = bpy.props.StringProperty(
371 description="Filter",
372 get=lambda s: prefs().popup_icons.filter,
373 set=set_filter,
374 options={'TEXTEDIT_UPDATE'})
375 selected_icon = bpy.props.StringProperty(
376 description="Selected Icon",
377 get=lambda s: prefs().popup_icons.selected_icon,
378 set=set_selected_icon)
380 def get_num_cols(self, num_icons):
381 return round(1.3 * math.sqrt(num_icons))
383 def draw_header(self, layout):
384 pr = prefs()
385 header = layout.box()
386 header = header.split(0.75) if self.selected_icon else header.row()
387 row = header.row(True)
388 row.prop(pr, "show_matcap_icons", "", icon='SMOOTH')
389 row.prop(pr, "show_brush_icons", "", icon='BRUSH_DATA')
390 row.prop(pr, "show_colorset_icons", "", icon='COLOR')
391 row.separator()
393 row.prop(
394 pr, "copy_on_select", "",
395 icon='BORDER_RECT', toggle=True)
396 if pr.copy_on_select:
397 sub = row.row(True)
398 if bpy.context.window.screen.name == "temp":
399 sub.alert = True
400 sub.prop(
401 pr, "close_on_select", "",
402 icon='RESTRICT_SELECT_OFF', toggle=True)
403 row.prop(
404 pr, "auto_focus_filter", "",
405 icon='OUTLINER_DATA_FONT', toggle=True)
406 row.separator()
408 if self.auto_focusable and pr.auto_focus_filter:
409 row.prop(self, "filter_auto_focus", "", icon='VIEWZOOM')
410 else:
411 row.prop(self, "filter", "", icon='VIEWZOOM')
413 if self.selected_icon:
414 row = header.row()
415 row.prop(self, "selected_icon", "", icon=self.selected_icon)
417 def draw(self, context):
418 pr = prefs()
419 col = self.layout
420 self.draw_header(col)
422 history_num_cols = int(
423 (self.width - POPUP_PADDING) / (ui_scale() * ICON_SIZE))
424 num_cols = min(
425 self.get_num_cols(len(pr.popup_icons.filtered_icons)),
426 history_num_cols)
428 subcol = col.column(True)
430 if HISTORY and pr.show_history:
431 pr.popup_icons.draw(subcol.box(), history_num_cols, HISTORY)
433 pr.popup_icons.draw(subcol.box(), num_cols)
435 def close(self):
436 bpy.context.window.screen = bpy.context.window.screen
438 def check(self, context):
439 return True
441 def cancel(self, context):
442 IV_OT_icons_show.instance = None
443 IV_PT_icons.tag_redraw()
445 def execute(self, context):
446 if not IV_OT_icons_show.instance:
447 return {'CANCELLED'}
448 IV_OT_icons_show.instance = None
450 pr = prefs()
451 if self.selected_icon and not pr.copy_on_select:
452 context.window_manager.clipboard = self.selected_icon
453 self.report({'INFO'}, self.selected_icon)
454 pr.popup_icons.selected_icon = ""
456 IV_PT_icons.tag_redraw()
457 return {'FINISHED'}
459 def invoke(self, context, event):
460 pr = prefs()
461 pr.popup_icons.selected_icon = ""
462 pr.popup_icons.filter = ""
463 IV_OT_icons_show.instance = self
464 self.auto_focusable = True
466 num_cols = self.get_num_cols(len(pr.popup_icons.filtered_icons))
467 self.width = min(
468 ui_scale() * (num_cols * ICON_SIZE + POPUP_PADDING),
469 context.window.width - WIN_PADDING)
471 return context.window_manager.invoke_props_dialog(self, self.width)
474 def register():
475 if bpy.app.background:
476 return
478 bpy.utils.register_module(__name__)
481 def unregister():
482 if bpy.app.background:
483 return
485 bpy.utils.unregister_module(__name__)