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 #####
23 "name": "Icon Viewer",
24 "description": "Click an icon to copy its name to the clipboard",
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"
47 prefs
= bpy
.context
.user_preferences
.system
48 return prefs
.dpi
* prefs
.pixel_size
/ DPI
52 return bpy
.context
.user_preferences
.addons
[__name__
].preferences
56 def __init__(self
, is_popup
=False):
57 self
._filtered
_icons
= None
60 self
.selected_icon
= ""
61 self
.is_popup
= is_popup
68 def filter(self
, value
):
69 if self
._filter
== value
:
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()
83 icons
= bpy
.types
.UILayout
.bl_rna
.functions
[
84 "prop"].parameters
["icon"].enum_items
.keys()
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
:
93 self
._filtered
_icons
.append(icon
)
95 return self
._filtered
_icons
99 return len(self
.filtered_icons
)
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):
108 filtered_icons
= reversed(icons
)
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
119 for i
, icon
in enumerate(filtered_icons
):
121 IV_OT_icon_select
.bl_idname
, "",
122 icon
=icon
, emboss
=icon
== selected_icon
)
124 p
.force_copy_on_select
= not self
.is_popup
127 if col_idx
> num_cols
- 1:
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
:
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
):
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",
160 get
=lambda s
: s
.panel_icons
.filter,
161 set=set_panel_filter
,
162 options
={'TEXTEDIT_UPDATE'})
163 show_panel_icons
= bpy
.props
.BoolProperty(
165 description
="Show icons", default
=True)
166 show_history
= bpy
.props
.BoolProperty(
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,
173 show_matcap_icons
= bpy
.props
.BoolProperty(
174 name
="Show Matcap Icons",
175 description
="Show matcap icons", default
=True,
177 show_colorset_icons
= bpy
.props
.BoolProperty(
178 name
="Show Colorset Icons",
179 description
="Show colorset icons", default
=True,
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",
187 "Close the popup on click.\n"
188 "Not supported by some windows (User Preferences, Render)"
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(
196 description
="Show the panel in the Text Editor", default
=True)
197 show_header
= bpy
.props
.BoolProperty(
199 description
="Show the header in the Python Console",
202 def draw(self
, context
):
206 row
.operator(IV_OT_icons_show
.bl_idname
)
210 col
= row
.column(True)
212 col
.prop(self
, "show_matcap_icons")
213 col
.prop(self
, "show_brush_icons")
214 col
.prop(self
, "show_colorset_icons")
216 col
.prop(self
, "show_history")
218 col
= row
.column(True)
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)
227 col
.prop(self
, "show_panel")
229 col
.prop(self
, "show_panel_icons")
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"
243 wm
= bpy
.context
.window_manager
248 for a
in w
.screen
.areas
:
249 if a
.type == 'TEXT_EDITOR':
254 def draw(self
, context
):
256 row
= self
.layout
.row(True)
257 if pr
.show_panel_icons
:
258 row
.prop(pr
, "panel_filter", "", icon
='VIEWZOOM')
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
)
269 (context
.region
.width
- PANEL_PADDING
) //
270 math
.ceil(ui_scale() * region_scale
* ICON_SIZE
))
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
)
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
:
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"
300 bl_description
= "Menu"
301 bl_options
= {'INTERNAL'}
303 def menu(self
, menu
, context
):
306 layout
.prop(pr
, "show_panel_icons")
307 layout
.prop(pr
, "show_history")
309 if not pr
.show_panel_icons
:
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")
322 class IV_OT_icon_select(bpy
.types
.Operator
):
323 bl_idname
= "iv.icon_select"
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
):
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()
342 if self
.icon
in HISTORY
:
343 HISTORY
.remove(self
.icon
)
344 if len(HISTORY
) >= HISTORY_SIZE
:
346 HISTORY
.append(self
.icon
)
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"
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,
369 options
={'TEXTEDIT_UPDATE', 'SKIP_SAVE'})
370 filter = bpy
.props
.StringProperty(
371 description
="Filter",
372 get
=lambda s
: prefs().popup_icons
.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
):
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')
394 pr
, "copy_on_select", "",
395 icon
='BORDER_RECT', toggle
=True)
396 if pr
.copy_on_select
:
398 if bpy
.context
.window
.screen
.name
== "temp":
401 pr
, "close_on_select", "",
402 icon
='RESTRICT_SELECT_OFF', toggle
=True)
404 pr
, "auto_focus_filter", "",
405 icon
='OUTLINER_DATA_FONT', toggle
=True)
408 if self
.auto_focusable
and pr
.auto_focus_filter
:
409 row
.prop(self
, "filter_auto_focus", "", icon
='VIEWZOOM')
411 row
.prop(self
, "filter", "", icon
='VIEWZOOM')
413 if self
.selected_icon
:
415 row
.prop(self
, "selected_icon", "", icon
=self
.selected_icon
)
417 def draw(self
, context
):
420 self
.draw_header(col
)
422 history_num_cols
= int(
423 (self
.width
- POPUP_PADDING
) / (ui_scale() * ICON_SIZE
))
425 self
.get_num_cols(len(pr
.popup_icons
.filtered_icons
)),
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
)
436 bpy
.context
.window
.screen
= bpy
.context
.window
.screen
438 def check(self
, context
):
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
:
448 IV_OT_icons_show
.instance
= None
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()
459 def invoke(self
, context
, event
):
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
))
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
)
475 if bpy
.app
.background
:
478 bpy
.utils
.register_module(__name__
)
482 if bpy
.app
.background
:
485 bpy
.utils
.unregister_module(__name__
)