diff --git a/source/blender/editors/include/ED_previewrender.h b/source/blender/editors/include/ED_previewrender.h index 7e0d71db7e1..b858a269236 100644 --- a/source/blender/editors/include/ED_previewrender.h +++ b/source/blender/editors/include/ED_previewrender.h @@ -72,7 +72,7 @@ void ED_preview_init_dbase(void); void ED_preview_free_dbase(void); void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, struct ID *parent, struct MTex *slot, int sizex, int sizey); -void ED_preview_iconrender(struct Scene *scene, struct ID *id, unsigned int *rect, int sizex, int sizey); +void ED_preview_icon_job(const struct bContext *C, void *owner, struct ID *id, unsigned int *rect, int sizex, int sizey); void ED_preview_draw(const struct bContext *C, void *idp, void *parentp, void *slot, rcti *rect); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 6c4110c8c37..0c11e64c0bb 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -47,6 +47,7 @@ #include "DNA_scene_types.h" #include "DNA_userdef_types.h" +#include "BKE_context.h" #include "BKE_image.h" #include "BKE_icons.h" #include "BKE_utildefines.h" @@ -676,56 +677,6 @@ void UI_icons_init(int first_dyn_id) init_internal_icons(); } -static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect) -{ - struct ImBuf *ima; - unsigned int *drect, *srect; - float scaledx, scaledy; - short ex, ey, dx, dy; - - /* paranoia test */ - if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) - return; - - /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */ - ima = IMB_dupImBuf(ibuf); - - if (!ima) - return; - - if (ima->x > ima->y) { - scaledx = (float)w; - scaledy = ( (float)ima->y/(float)ima->x )*(float)w; - } - else { - scaledx = ( (float)ima->x/(float)ima->y )*(float)h; - scaledy = (float)h; - } - - ex = (short)scaledx; - ey = (short)scaledy; - - dx = (w - ex) / 2; - dy = (h - ey) / 2; - - IMB_scalefastImBuf(ima, ex, ey); - - /* if needed, convert to 32 bits */ - if(ima->rect==NULL) - IMB_rect_from_float(ima); - - srect = ima->rect; - drect = rect; - - drect+= dy*w+dx; - for (;ey > 0; ey--){ - memcpy(drect,srect, ex * sizeof(int)); - drect += w; - srect += ima->x; - } - IMB_freeImBuf(ima); -} - /* Render size for preview images at level miplevel */ static int preview_render_size(int miplevel) { @@ -751,105 +702,20 @@ static void icon_create_mipmap(struct PreviewImage* prv_img, int miplevel) } } -/* create single icon from jpg, png etc. */ -static void icon_from_image(Scene *scene, Image *img, int miplevel) -{ - ImBuf *ibuf= NULL; - ImageUser iuser; - PreviewImage *pi; - unsigned int pr_size; - short image_loaded = 0; - - /* img->ok is zero when Image cannot load */ - if (img==NULL || img->ok==0) - return; - - /* setup dummy image user */ - memset(&iuser, 0, sizeof(ImageUser)); - iuser.ok= iuser.framenr= 1; - iuser.scene= scene; - - /* elubie: this needs to be changed: here image is always loaded if not - already there. Very expensive for large images. Need to find a way to - only get existing ibuf */ - - ibuf = BKE_image_get_ibuf(img, &iuser); - if(ibuf==NULL || ibuf->rect==NULL) { - return; - } - - pi = BKE_previewimg_get((ID*)img); - - if(!pi) { - printf("preview image could'nt be allocated"); - return; - } - /* we can only create the preview rect here, since loading possibly deallocated - old preview */ - icon_create_mipmap(pi, miplevel); - - pr_size = img->preview->w[miplevel]*img->preview->h[miplevel]*sizeof(unsigned int); - - image_loaded = 1; - icon_copy_rect(ibuf, img->preview->w[miplevel], img->preview->h[miplevel], img->preview->rect[miplevel]); -} - -static void set_alpha(char* cp, int sizex, int sizey, char alpha) -{ - int x,y; - for(y=0; yname); return; } - /* no drawing (see last parameter doDraw, just calculate preview image - - hopefully small enough to be fast */ - if (GS(id->name) == ID_IM) - icon_from_image(scene, (struct Image*)id, miplevel); - else { - /* create the preview rect */ - icon_create_mipmap(prv_img, miplevel); + /* create the preview rect */ + icon_create_mipmap(prv_img, miplevel); - ri.curtile= 0; - ri.tottile= 0; - ri.pr_rectx = prv_img->w[miplevel]; - ri.pr_recty = prv_img->h[miplevel]; - pr_size = ri.pr_rectx*ri.pr_recty*sizeof(unsigned int); - ri.rect = MEM_callocN(pr_size, "pr icon rect"); - - ED_preview_iconrender(scene, id, ri.rect, ri.pr_rectx, ri.pr_recty); - - /* world is rendered with alpha=0, so it wasn't displayed - this could be render option for sky to, for later */ - if (GS(id->name) == ID_WO) { - set_alpha( (char*) ri.rect, ri.pr_rectx, ri.pr_recty, 255); - } - else if (GS(id->name) == ID_MA) { - Material* mat = (Material*)id; - if (mat->material_type == MA_TYPE_HALO) { - set_alpha( (char*) ri.rect, ri.pr_rectx, ri.pr_recty, 255); - } - } - - memcpy(prv_img->rect[miplevel], ri.rect, pr_size); - - /* and clean up */ - MEM_freeN(ri.rect); - } + ED_preview_icon_job(C, prv_img, id, prv_img->rect[miplevel], + prv_img->w[miplevel], prv_img->h[miplevel]); } static void icon_draw_rect(float x, float y, int w, int h, float aspect, int rw, int rh, unsigned int *rect) @@ -944,7 +810,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, int mipl } } -void ui_id_icon_render(Scene *scene, ID *id) +void ui_id_icon_render(bContext *C, ID *id) { PreviewImage *pi = BKE_previewimg_get(id); @@ -952,13 +818,13 @@ void ui_id_icon_render(Scene *scene, ID *id) if ((pi->changed[0] ||!pi->rect[0])) /* changed only ever set by dynamic icons */ { /* create the preview rect if necessary */ - icon_set_image(scene, id, pi, 0); + icon_set_image(C, id, pi, 0); pi->changed[0] = 0; } } } -int ui_id_icon_get(Scene *scene, ID *id) +int ui_id_icon_get(bContext *C, ID *id) { int iconid= 0; @@ -972,7 +838,7 @@ int ui_id_icon_get(Scene *scene, ID *id) case ID_LA: /* fall through */ iconid= BKE_icon_getid(id); /* checks if not exists, or changed */ - ui_id_icon_render(scene, id); + ui_id_icon_render(C, id); break; default: break; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 292c85e9072..97bbee0a1c3 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -451,8 +451,8 @@ void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, char *name, int i void uiStyleInit(void); /* interface_icons.c */ -void ui_id_icon_render(struct Scene *scene, struct ID *id); -int ui_id_icon_get(struct Scene *scene, struct ID *id); +void ui_id_icon_render(struct bContext *C, struct ID *id); +int ui_id_icon_get(struct bContext *C, struct ID *id); /* resources.c */ void init_userdef_do_versions(void); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 64a45efc551..e9160e0e416 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1021,7 +1021,6 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname) static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items) { - Scene *scene= CTX_data_scene(C); uiBut *but= arg_but; char *name; int i, iconid; @@ -1030,7 +1029,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, ui RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) { iconid= 0; if(RNA_struct_is_ID(itemptr.type)) - iconid= ui_id_icon_get(scene, itemptr.data); + iconid= ui_id_icon_get((bContext*)C, itemptr.data); name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index af4a4c13c80..d7b136cd661 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -94,7 +94,6 @@ static void id_search_call_cb(bContext *C, void *arg_template, void *item) static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSearchItems *items) { TemplateID *template= (TemplateID*)arg_template; - Scene *scene= CTX_data_scene(C); ListBase *lb= template->idlb; ID *id; int iconid; @@ -102,7 +101,7 @@ static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSea /* ID listbase */ for(id= lb->first; id; id= id->next) { if(BLI_strcasestr(id->name+2, str)) { - iconid= ui_id_icon_get(scene, id); + iconid= ui_id_icon_get((bContext*)C, id); if(!uiSearchItemAdd(items, id->name+2, id, iconid)) break; @@ -1842,6 +1841,36 @@ static void list_item_add(ListBase *lb, ListBase *itemlb, uiLayout *layout, Poin } #endif +static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon) +{ + ID *id= NULL; + int icon; + + if(!itemptr->data) + return rnaicon; + + /* try ID, material or texture slot */ + if(RNA_struct_is_ID(itemptr->type)) { + id= itemptr->id.data; + } + else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) { + id= RNA_pointer_get(itemptr, "material").data; + } + else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) { + id= RNA_pointer_get(itemptr, "texture").data; + } + + /* get icon from ID */ + if(id) { + icon= ui_id_icon_get(C, id); + + if(icon) + return icon; + } + + return rnaicon; +} + ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int listtype) { //Scene *scene= CTX_data_scene(C); @@ -1854,7 +1883,7 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr Panel *pa; ListBase lb, *itemlb; char *name, str[32]; - int icon=0, i= 0, activei= 0, len= 0, items, found, min, max; + int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max; lb.first= lb.last= NULL; @@ -1901,7 +1930,7 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr /* get icon */ if(ptr->data && prop) { ptype= RNA_property_pointer_type(ptr, prop); - icon= RNA_struct_ui_icon(ptype); + rnaicon= RNA_struct_ui_icon(ptype); } /* get active data */ @@ -1921,15 +1950,7 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr if(i == 9) row= uiLayoutRow(col, 0); - if(RNA_struct_is_a(itemptr.type, &RNA_TextureSlot)) { -#if 0 - MTex *mtex= itemptr.data; - - if(mtex && mtex->tex) - icon= ui_id_icon_get(scene, &mtex->tex->id); -#endif - } - + icon= list_item_icon_get(C, &itemptr, rnaicon); uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, ""); //list_item_add(&lb, itemlb, uiLayoutRow(row, 1), &itemptr); @@ -1953,6 +1974,7 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr if(found) { /* create button */ name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); + icon= list_item_icon_get(C, &itemptr, rnaicon); uiItemL(row, (name)? name: "", icon); if(name) @@ -2006,6 +2028,8 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); subrow= uiLayoutRow(col, 0); + + icon= list_item_icon_get(C, &itemptr, rnaicon); /* create button */ if(!icon || icon == ICON_DOT) diff --git a/source/blender/editors/preview/previewrender.c b/source/blender/editors/preview/previewrender.c index 7a4cc1c7865..91928b971f3 100644 --- a/source/blender/editors/preview/previewrender.c +++ b/source/blender/editors/preview/previewrender.c @@ -115,7 +115,7 @@ typedef struct ShaderPreview { MTex *slot; int sizex, sizey; - int *pr_rect; + unsigned int *pr_rect; int pr_method; } ShaderPreview; @@ -509,6 +509,12 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r } } +/* ******************************** Icon Preview **************************** */ + +void ED_preview_icon_draw(const bContext *C, void *idp, void *arg1, void *arg2, rcti *rect) +{ +} + /* *************************** Preview for 3d window *********************** */ void view3d_previewrender_progress(RenderResult *rr, volatile rcti *renrect) @@ -819,7 +825,7 @@ void BIF_view3d_previewdraw(struct ScrArea *sa, struct uiBlock *block) } -/* **************************** New preview system ****************** */ +/* **************************** new shader preview system ****************** */ /* inside thread, called by renderer, sets job update value */ static void shader_preview_draw(void *spv, RenderResult *rr, volatile struct rcti *rect) @@ -906,7 +912,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs /* handle results */ if(sp->pr_method==PR_ICON_RENDER) { if(sp->pr_rect) - RE_ResultGet32(re, (unsigned int *)sp->pr_rect); + RE_ResultGet32(re, sp->pr_rect); } else { /* validate owner */ @@ -919,7 +925,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs preview_prepare_scene(sp->scene, NULL, GS(id->name), NULL); } -/* runs inside thread for material, in foreground for icons */ +/* runs inside thread for material and icons */ static void shader_preview_startjob(void *customdata, short *stop, short *do_update) { ShaderPreview *sp= customdata; @@ -944,6 +950,168 @@ static void shader_preview_free(void *customdata) MEM_freeN(sp); } +/* ************************* icon preview ********************** */ + +static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect) +{ + struct ImBuf *ima; + unsigned int *drect, *srect; + float scaledx, scaledy; + short ex, ey, dx, dy; + + /* paranoia test */ + if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + return; + + /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */ + ima = IMB_dupImBuf(ibuf); + + if (!ima) + return; + + if (ima->x > ima->y) { + scaledx = (float)w; + scaledy = ( (float)ima->y/(float)ima->x )*(float)w; + } + else { + scaledx = ( (float)ima->x/(float)ima->y )*(float)h; + scaledy = (float)h; + } + + ex = (short)scaledx; + ey = (short)scaledy; + + dx = (w - ex) / 2; + dy = (h - ey) / 2; + + IMB_scalefastImBuf(ima, ex, ey); + + /* if needed, convert to 32 bits */ + if(ima->rect==NULL) + IMB_rect_from_float(ima); + + srect = ima->rect; + drect = rect; + + drect+= dy*w+dx; + for (;ey > 0; ey--){ + memcpy(drect,srect, ex * sizeof(int)); + drect += w; + srect += ima->x; + } + + IMB_freeImBuf(ima); +} + +static void set_alpha(char *cp, int sizex, int sizey, char alpha) +{ + int a, size= sizex*sizey; + + for(a=0; aid; + short idtype= GS(id->name); + + if(idtype == ID_IM) { + Image *ima= (Image*)id; + ImBuf *ibuf= NULL; + ImageUser iuser; + + /* ima->ok is zero when Image cannot load */ + if(ima==NULL || ima->ok==0) + return; + + /* setup dummy image user */ + memset(&iuser, 0, sizeof(ImageUser)); + iuser.ok= iuser.framenr= 1; + iuser.scene= sp->scene; + + /* elubie: this needs to be changed: here image is always loaded if not + already there. Very expensive for large images. Need to find a way to + only get existing ibuf */ + ibuf = BKE_image_get_ibuf(ima, &iuser); + if(ibuf==NULL || ibuf->rect==NULL) + return; + + icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); + + *do_update= 1; + } + else { + /* re-use shader job */ + shader_preview_startjob(customdata, stop, do_update); + + /* world is rendered with alpha=0, so it wasn't displayed + this could be render option for sky to, for later */ + if(idtype == ID_WO) { + set_alpha((char*)sp->pr_rect, sp->sizex, sp->sizey, 255); + } + else if(idtype == ID_MA) { + Material* ma = (Material*)id; + + if(ma->material_type == MA_TYPE_HALO) + set_alpha((char*)sp->pr_rect, sp->sizex, sp->sizey, 255); + } + } +} + +/* use same function for icon & shader, so the job manager + does not run two of them at the same time. */ + +static void common_preview_startjob(void *customdata, short *stop, short *do_update) +{ + ShaderPreview *sp= customdata; + + if(sp->pr_method == PR_ICON_RENDER) + icon_preview_startjob(customdata, stop, do_update); + else + shader_preview_startjob(customdata, stop, do_update); +} + +/* exported functions */ + +void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey) +{ + wmJob *steve; + ShaderPreview *sp; + + /* XXX ugly global still, but we can't do preview while rendering */ + if(G.rendering) + return; + + /* XXX this is not correct, can't work with threads */ + if(GS(id->name) == ID_TE) { + ntreeTexSetPreviewFlag(1); + } + + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner); + sp= MEM_callocN(sizeof(ShaderPreview), "shader preview"); + + /* customdata for preview thread */ + sp->scene= CTX_data_scene(C); + sp->owner= owner; + sp->sizex= sizex; + sp->sizey= sizey; + sp->pr_method= PR_ICON_RENDER; + sp->pr_rect= rect; + sp->id = id; + + /* setup job */ + WM_jobs_customdata(steve, sp, shader_preview_free); + WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL); + WM_jobs_callbacks(steve, common_preview_startjob, NULL, NULL); + + WM_jobs_start(CTX_wm_manager(C), steve); + + /* signal to rerender icon in menus */ + BKE_icon_changed(BKE_icon_getid(id)); +} + void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey) { wmJob *steve; @@ -953,6 +1121,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M if(G.rendering) return; + /* XXX this is not correct, can't work with threads */ if(GS(id->name) == ID_TE) { ntreeTexSetPreviewFlag(1); } @@ -973,7 +1142,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M /* setup job */ WM_jobs_customdata(steve, sp, shader_preview_free); WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL); - WM_jobs_callbacks(steve, shader_preview_startjob, NULL, shader_preview_updatejob); + WM_jobs_callbacks(steve, common_preview_startjob, NULL, shader_preview_updatejob); WM_jobs_start(CTX_wm_manager(C), steve); @@ -981,26 +1150,4 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M BKE_icon_changed(BKE_icon_getid(id)); } -/* rect should be allocated, sizex/sizy pixels, 32 bits */ -void ED_preview_iconrender(Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey) -{ - ShaderPreview *sp; - short stop=0, do_update=0; - - sp= MEM_callocN(sizeof(ShaderPreview), "ShaderPreview"); - - /* customdata for preview thread */ - sp->scene= scene; - sp->sizex= sizex; - sp->sizey= sizey; - sp->pr_method= PR_ICON_RENDER; - sp->pr_rect= (int *)rect; /* shouldnt pr_rect be unsigned int also? - Campbell */ - sp->id = id; - - shader_preview_startjob(sp, &stop, &do_update); - - MEM_freeN(sp); -} - -