Page MenuHome

Custom icons for addons patch
AbandonedPublic

Authored by Jonathan Williamson (carter2422) on Jul 13 2014, 12:30 PM.

Details

Summary

This a working patch, however it need some review(missing a way to control wrong path...)

Diff Detail

Event Timeline

There are stylistic/spacing issues, leftover comments, ifdefs debug prints and some algorithm concerns (for instance i variable does not get reset when we reload scripts), but it's not bad, I'll clean this up later.

If this is added it should be possible to name icon's so those names can be used as with existing icon,

layout.operator("some.operator", icon='MY_ICON')

This is possible via dynamic enums.

source/blender/makesrna/intern/rna_ui_api.c
180

Changes here shouldn't be needed.

source/blender/python/intern/bpy.c
72

incorrect string escaping

@Antonis Ryakiotakis (psy-fi) i know, i was so excited to know about this that, i don't clean it up, before uploading XD. For the "i" variable, it's intentional: if you more then one custom icon, you should also occupy new icon slots, if this it's get reset, each time you upload an icon(so each time you run the script) you overwrite the previous one...The problem now is that may create multiple copies of the same icon, a solution is to detect if an icon is already uploaded, i think also it's best to have also an unload icon code, when unregistering the script.

@Campbell Barton (campbellbarton): yeah, this was my first idea, if you search in the wiki proposal you'll find that, but it was hard to "reverse engine" the code and find a way, then i find that there was already to upload icons on startup(see the comment on the code), so i reused this code, and the solution i found is the easiest one... If you tell me how to use dynamic enums i will do that.

Luca Carella (rebellion) updated this revision to Unknown Object (????).Jul 15 2014, 4:48 PM

I've deleted un-relevant comment and some fixes

@Luca Carella (rebellion) what's the syntax for defining the path to the icon? I get a hard crash anytime I attempt to load an icon through the console.

For example, using:

bpy.utils.load_icon("~/icon-name.png")

results in a segmentation fault. I'm using a 16x16 PNG.

I've never done much with file loading through Python, so if it's merely an ignorant syntax mistake please excuse me :)

@Jonathan Williamson (carter2422) on my build I've tried only full path... however the syntax seems correct.

I'm working to improve and complete the code, i need to find a way to detect the file or better the dir where the code it's executed, i need this because in case of relative path, i should be able to detect the absolute path, since add-ons should be shipped with the icon, the passed path should be relative, but at the moment i can't read relative path... if some one have an idea please let me know. Thanks!!

source/blender/python/intern/bpy.c
72

sorry but i can't see the error... can you be more specific please??

Agreed, relative path support is vital for add ons.

I've made some progress on @Campbell Barton (campbellbarton) direction, now it's possible to give it and ID to use in the UI elements, but there are still some issue: in order to do so, i've added an "itemf" to the icon rna enum, doing this way each time an UI element with icon need to be updated, the enum is each time populated with the icons, this slow up the program, plus the enum isn't updated until the at last one UI element with an icon need an update.

static EnumPropertyItem *rna_ui_icon_enum_itemf(
	bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
	EnumPropertyItem *item = NULL, item_temp = {0}, *item_test = NULL;
	int totitem = 0;

	RNA_enum_items_add(&item, &totitem, &icon_items);
	UI_icons_enum_items_add(&item, &totitem);
	//RNA_enum_item_add(&item, &totitem, &item_temp);
	//for (int i = 0; i<600; i++)
	//	item_test = &item[i];
	RNA_enum_item_end(&item, &totitem);

	*r_free = true;

	return item;
}

Another problem i found is that if I call

bpy.types.UILayout.bl_rna.functions['prop'].parameters['icon'].enum_items.keys()

this don't display the updated enum but only the "default one". There is another icon enum in the rna???
Before upload another diff i'll try to fix some other problem. Still remain the relative path problem...

Luca Carella (rebellion) edited edge metadata.

This should be the last, It work perfectly, with all error management. So give it a try and tell me what it's need to be fixed. Unfortunately relative path will not be supported due to an "issue" I've found this morning in bpy_interface.c: when running the script(from built-in text editor), only the file name is passed to python and not the complete path, this make impossible from the blender text editor rebuild the absolute path of the script(for example using void PyC_FileAndNum(const char **filename, int *lineno) to get the base path). It's my opinion to change this. Should submit another DIFF??

Ok, for this month I'm unavailable, so you have all time to review this XD. At September, if there are any issue or problem, i'll work on it!

source/blender/makesrna/intern/rna_ui_api.c
181

forgot to change this file...

Update from August 3rd UI Meeting

This was discussed during today's meeting. This is a good thing to support and should get implemented. Per comments from @Campbell Barton (campbellbarton) the main issue right now is the heavy enum loading, need to find a way to speed this up.

@Luca Carella (rebellion), I cannot speak to the bpy_interface.c changes but getting Relative Paths working is vital. Perhaps @Campbell Barton (campbellbarton) or @Antonis Ryakiotakis (psy-fi) can speak more to this issue?

Just to be clear: relative path work by getting a base path(in this case the addon path) and the relative path, then from this take the absolute path of the file to open, this is what i understand from blender code. In fact IMB_loadiffname don't understand path like this :"../pathtoicon.png ". The only way i found is to pass os.syspath.absolute(FILE) to the python function load_icon, but this don't work because FILE contain only the file name. The strange thing is that it work if the addon is loaded from the user preference!! So at this point i don't know if it's a problem of the blender text editor or the error comes also when the script is runned externally. The only thing that fixes this issue is to change few lines in bpy_interface.c. So yeah i would like to hear campbell and psy-fi opinion or idea on this. If there is another meeting maybe i can partecipate, so i can discuss better this.

Campbell Barton (campbellbarton) requested changes to this revision.EditedAug 25 2014, 12:34 PM
Campbell Barton (campbellbarton) edited edge metadata.

Talked with Sergey, and we're not so happy with the method currently used by the patch.

Lazy Loading

Firstly the API is setup so its loading icons as addons load.
Once this extends to 50+ icons it can noticeably slow down blenders startup time.
OpenOffice traced slow load times to reading lots of files on disk - see: https://www.youtube.com/watch?v=d0140g6pF3w

So I would rather this use something more like Python's modules, where there is an icon search path, eg bpy.app.icon_paths, so scripts just have to ensure their own paths are added, Then the icons themselves are loaded on demand using lookups based on their identifiers.

Icon Storage

(This could be done later) ideally custom icons would be stored in a texture atlas (as font's are already). - generated on demand by checking the search-path and and caching results.
This isn't all that complicated, see: blf_glyph_cache_texture

Dynamic Enum

The RNA API's itemf callbacks are really not very efficient, generating and freeing an entire array for every icon lookup (in practice many times per redraw).
I think for this patch to be acceptable we will need to extend the RNA api to support enum lookups which don't have this limitation.


Realize these aren't trivial changes, but since this is fairly significant UI feature I think it should be well supported and not something we need to redo again.

This revision now requires changes to proceed.Aug 25 2014, 12:34 PM

OK I'll see what i can do! However i have some doubt on your first request("Lazy Loading"): basically you want that the first time the UI element with the icon is parsed, it load the icon, then this is cached for reuse, right?? So how i can assign an ID to the icon if i load only the paths of the file? maybe it's best to use the same module, so instead of loading the icon it self it only load the path. Then when it's time for the icon to be used, it's loaded once and cached.

Hi, how is the patch doing? With many addons being developed freely or on the cgcookie market, it would be great to have this finally added to trunk. Addon devs do their best to find a default Icon that pass to their developed functions, but often it's really not suited at all and misleading because of complete different functionalities being visualized with the same symbol. Not as shiny as volumetrics for cycles but really helpful to reduce headaches and improve workflow.
Please polish the little diamond Blender is.