Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface_icons.c
| Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_icons.h" | #include "BKE_icons.h" | ||||
| #include "BKE_appdir.h" | #include "BKE_appdir.h" | ||||
| #include "IMB_imbuf.h" | #include "IMB_imbuf.h" | ||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| #include "IMB_thumbs.h" | |||||
| #include "BIF_gl.h" | #include "BIF_gl.h" | ||||
| #include "BIF_glutil.h" | #include "BIF_glutil.h" | ||||
| #include "ED_datafiles.h" | #include "ED_datafiles.h" | ||||
| #include "ED_render.h" | #include "ED_render.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| ▲ Show 20 Lines • Show All 833 Lines • ▼ Show 20 Lines | |||||
| #endif | #endif | ||||
| } | } | ||||
| /* Render size for preview images and icons | /* Render size for preview images and icons | ||||
| */ | */ | ||||
| static int preview_render_size(enum eIconSizes size) | static int preview_render_size(enum eIconSizes size) | ||||
| { | { | ||||
| switch (size) { | switch (size) { | ||||
| case ICON_SIZE_ICON: return 32; | case ICON_SIZE_ICON: | ||||
| case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT; | return ICON_RENDER_DEFAULT_HEIGHT; | ||||
| } | case ICON_SIZE_PREVIEW: | ||||
| return PREVIEW_RENDER_DEFAULT_HEIGHT; | |||||
| default: | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | |||||
| /* Create rect for the icon | /* Create rect for the icon | ||||
| */ | */ | ||||
| static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) | static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) | ||||
| { | { | ||||
| unsigned int render_size = preview_render_size(size); | unsigned int render_size = preview_render_size(size); | ||||
| if (!prv_img) { | if (!prv_img) { | ||||
| if (G.debug & G_DEBUG) | if (G.debug & G_DEBUG) | ||||
| printf("%s, error: requested preview image does not exist", __func__); | printf("%s, error: requested preview image does not exist", __func__); | ||||
| } | } | ||||
| else if (!prv_img->rect[size]) { | else if (!prv_img->rect[size]) { | ||||
| prv_img->w[size] = render_size; | prv_img->w[size] = render_size; | ||||
| prv_img->h[size] = render_size; | prv_img->h[size] = render_size; | ||||
| prv_img->changed[size] = 1; | prv_img->flag[size] |= PRV_CHANGED; | ||||
| prv_img->changed_timestamp[size] = 0; | prv_img->changed_timestamp[size] = 0; | ||||
| prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(unsigned int), "prv_rect"); | prv_img->rect[size] = MEM_callocN(render_size * render_size * sizeof(unsigned int), "prv_rect"); | ||||
| } | } | ||||
| } | } | ||||
| void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big) | |||||
| { | |||||
| Icon *icon = BKE_icon_get(icon_id); | |||||
| if (icon) { | |||||
| DrawInfo *di = (DrawInfo *)icon->drawinfo; | |||||
| if (!di) { | |||||
| di = icon_create_drawinfo(); | |||||
| icon->drawinfo = di; | |||||
| icon->drawinfo_free = UI_icons_free_drawinfo; | |||||
| } | |||||
| if (di) { | |||||
| if (di->type == ICON_TYPE_PREVIEW) { | |||||
| PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; | |||||
| if (prv) { | |||||
| const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; | |||||
| if (!prv->use_deferred || prv->rect[size] || (prv->flag[size] & PRV_USER_EDITED)) { | |||||
| return; | |||||
| } | |||||
| icon_create_rect(prv, size); | |||||
| /* Always using job (background) version. */ | |||||
| ED_preview_icon_job(C, prv, NULL, prv->rect[size], prv->w[size], prv->h[size]); | |||||
| prv->flag[size] &= ~PRV_CHANGED; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /* only called when icon has changed */ | /* only called when icon has changed */ | ||||
| /* only call with valid pointer from UI_icon_draw */ | /* only call with valid pointer from UI_icon_draw */ | ||||
| static void icon_set_image( | static void icon_set_image( | ||||
| const bContext *C, Scene *scene, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job) | const bContext *C, Scene *scene, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job) | ||||
| { | { | ||||
| if (!prv_img) { | if (!prv_img) { | ||||
| if (G.debug & G_DEBUG) | if (G.debug & G_DEBUG) | ||||
| printf("%s: no preview image for this ID: %s\n", __func__, id->name); | printf("%s: no preview image for this ID: %s\n", __func__, id->name); | ||||
| return; | return; | ||||
| } | } | ||||
| if (prv_img->flag[size] & PRV_USER_EDITED) { | |||||
| /* user-edited preview, do not auto-update! */ | |||||
| return; | |||||
| } | |||||
| icon_create_rect(prv_img, size); | icon_create_rect(prv_img, size); | ||||
| if (use_job) { | if (use_job) { | ||||
| /* Job (background) version */ | /* Job (background) version */ | ||||
| ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); | ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); | ||||
| } | } | ||||
| else { | else { | ||||
| if (!scene) { | if (!scene) { | ||||
| scene = CTX_data_scene(C); | scene = CTX_data_scene(C); | ||||
| } | } | ||||
| /* Immediate version */ | /* Immediate version */ | ||||
| ED_preview_icon_render(scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); | ED_preview_icon_render(scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); | ||||
| } | } | ||||
| } | } | ||||
| PreviewImage *UI_icon_to_preview(int icon_id) | PreviewImage *UI_icon_to_preview(int icon_id) | ||||
| { | { | ||||
| Icon *icon = BKE_icon_get(icon_id); | Icon *icon = BKE_icon_get(icon_id); | ||||
| if (icon) { | if (icon) { | ||||
| DrawInfo *di = (DrawInfo *)icon->drawinfo; | DrawInfo *di = (DrawInfo *)icon->drawinfo; | ||||
| if (di && di->data.buffer.image) { | if (di) { | ||||
| if (di->type == ICON_TYPE_PREVIEW) { | |||||
| PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; | |||||
| if (prv) { | |||||
| return BKE_previewimg_copy(prv); | |||||
| } | |||||
| } | |||||
| else if (di->data.buffer.image) { | |||||
| ImBuf *bbuf; | ImBuf *bbuf; | ||||
| bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, IB_rect, NULL, "<matcap buffer>"); | bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, | ||||
| IB_rect, NULL, __func__); | |||||
| if (bbuf) { | if (bbuf) { | ||||
| PreviewImage *prv = BKE_previewimg_create(); | PreviewImage *prv = BKE_previewimg_create(); | ||||
| prv->rect[0] = bbuf->rect; | prv->rect[0] = bbuf->rect; | ||||
| prv->w[0] = bbuf->x; | prv->w[0] = bbuf->x; | ||||
| prv->h[0] = bbuf->y; | prv->h[0] = bbuf->y; | ||||
| bbuf->rect = NULL; | bbuf->rect = NULL; | ||||
| IMB_freeImBuf(bbuf); | IMB_freeImBuf(bbuf); | ||||
| return prv; | return prv; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, | static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, | ||||
| unsigned int *rect, float alpha, const float rgb[3], const bool is_preview) | unsigned int *rect, float alpha, const float rgb[3], const bool is_preview) | ||||
| { | { | ||||
| ImBuf *ima = NULL; | ImBuf *ima = NULL; | ||||
| int draw_w = w; | |||||
| int draw_h = h; | |||||
| int draw_x = x; | |||||
| int draw_y = y; | |||||
| /* sanity check */ | /* sanity check */ | ||||
| if (w <= 0 || h <= 0 || w > 2000 || h > 2000) { | if (w <= 0 || h <= 0 || w > 2000 || h > 2000) { | ||||
| printf("%s: icons are %i x %i pixels?\n", __func__, w, h); | printf("%s: icons are %i x %i pixels?\n", __func__, w, h); | ||||
| BLI_assert(!"invalid icon size"); | BLI_assert(!"invalid icon size"); | ||||
| return; | return; | ||||
| } | } | ||||
| /* modulate color */ | /* modulate color */ | ||||
| if (alpha != 1.0f) | if (alpha != 1.0f) | ||||
| glPixelTransferf(GL_ALPHA_SCALE, alpha); | glPixelTransferf(GL_ALPHA_SCALE, alpha); | ||||
| if (rgb) { | if (rgb) { | ||||
| glPixelTransferf(GL_RED_SCALE, rgb[0]); | glPixelTransferf(GL_RED_SCALE, rgb[0]); | ||||
| glPixelTransferf(GL_GREEN_SCALE, rgb[1]); | glPixelTransferf(GL_GREEN_SCALE, rgb[1]); | ||||
| glPixelTransferf(GL_BLUE_SCALE, rgb[2]); | glPixelTransferf(GL_BLUE_SCALE, rgb[2]); | ||||
| } | } | ||||
| /* rect contains image in 'rendersize', we only scale if needed */ | /* rect contains image in 'rendersize', we only scale if needed */ | ||||
| if (rw != w && rh != h) { | if (rw != w || rh != h) { | ||||
| /* preserve aspect ratio and center */ | |||||
| if (rw > rh) { | |||||
| draw_w = w; | |||||
| draw_h = (int)(((float)rh / (float)rw) * (float)w); | |||||
| draw_y += (h - draw_h) / 2; | |||||
| } | |||||
| else if (rw < rh) { | |||||
| draw_w = (int)(((float)rw / (float)rh) * (float)h); | |||||
| draw_h = h; | |||||
| draw_x += (w - draw_w) / 2; | |||||
| } | |||||
| /* if the image is squared, the draw_ initialization values are good */ | |||||
| /* first allocate imbuf for scaling and copy preview into it */ | /* first allocate imbuf for scaling and copy preview into it */ | ||||
| ima = IMB_allocImBuf(rw, rh, 32, IB_rect); | ima = IMB_allocImBuf(rw, rh, 32, IB_rect); | ||||
| memcpy(ima->rect, rect, rw * rh * sizeof(unsigned int)); | memcpy(ima->rect, rect, rw * rh * sizeof(unsigned int)); | ||||
| IMB_scaleImBuf(ima, w, h); /* scale it */ | IMB_scaleImBuf(ima, draw_w, draw_h); /* scale it */ | ||||
| rect = ima->rect; | rect = ima->rect; | ||||
| } | } | ||||
| /* draw */ | /* draw */ | ||||
| if (is_preview) { | if (is_preview) { | ||||
| glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, rect); | glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect); | ||||
| } | } | ||||
| else { | else { | ||||
| glRasterPos2f(x, y); | glRasterPos2f(draw_x, draw_y); | ||||
| glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect); | glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect); | ||||
| } | } | ||||
| if (ima) | if (ima) | ||||
| IMB_freeImBuf(ima); | IMB_freeImBuf(ima); | ||||
| /* restore color */ | /* restore color */ | ||||
| if (alpha != 0.0f) | if (alpha != 0.0f) | ||||
| glPixelTransferf(GL_ALPHA_SCALE, 1.0f); | glPixelTransferf(GL_ALPHA_SCALE, 1.0f); | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | static void icon_draw_texture( | ||||
| glBindTexture(GL_TEXTURE_2D, 0); | glBindTexture(GL_TEXTURE_2D, 0); | ||||
| glDisable(GL_TEXTURE_2D); | glDisable(GL_TEXTURE_2D); | ||||
| } | } | ||||
| /* Drawing size for preview images */ | /* Drawing size for preview images */ | ||||
| static int get_draw_size(enum eIconSizes size) | static int get_draw_size(enum eIconSizes size) | ||||
| { | { | ||||
| switch (size) { | switch (size) { | ||||
| case ICON_SIZE_ICON: return ICON_DEFAULT_HEIGHT; | case ICON_SIZE_ICON: | ||||
| case ICON_SIZE_PREVIEW: return PREVIEW_DEFAULT_HEIGHT; | return ICON_DEFAULT_HEIGHT; | ||||
| } | case ICON_SIZE_PREVIEW: | ||||
| return PREVIEW_DEFAULT_HEIGHT; | |||||
| default: | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | |||||
| static void icon_draw_size( | static void icon_draw_size( | ||||
| float x, float y, int icon_id, float aspect, float alpha, const float rgb[3], | float x, float y, int icon_id, float aspect, float alpha, const float rgb[3], | ||||
| enum eIconSizes size, int draw_size, const bool UNUSED(nocreate), const bool is_preview) | enum eIconSizes size, int draw_size, const bool UNUSED(nocreate), const bool is_preview) | ||||
| { | { | ||||
| bTheme *btheme = UI_GetTheme(); | bTheme *btheme = UI_GetTheme(); | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
| #endif | #endif | ||||
| if (!iimg->rect) return; /* something has gone wrong! */ | if (!iimg->rect) return; /* something has gone wrong! */ | ||||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
| icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview); | icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview); | ||||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
| } | } | ||||
| else if (di->type == ICON_TYPE_PREVIEW) { | else if (di->type == ICON_TYPE_PREVIEW) { | ||||
| PreviewImage *pi = BKE_previewimg_get((ID *)icon->obj); | PreviewImage *pi = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; | ||||
| if (pi) { | if (pi) { | ||||
| /* Do deferred loading/generation if needed. */ | |||||
| // BKE_previewimg_ensure(pi, size); | |||||
| /* no create icon on this level in code */ | /* no create icon on this level in code */ | ||||
| if (!pi->rect[size]) return; /* something has gone wrong! */ | if (!pi->rect[size]) return; /* something has gone wrong! */ | ||||
| /* preview images use premul alpha ... */ | /* preview images use premul alpha ... */ | ||||
| glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); | ||||
| icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], 1.0f, NULL, is_preview); | icon_draw_rect(x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], 1.0f, NULL, is_preview); | ||||
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void ui_id_preview_image_render_size( | static void ui_id_preview_image_render_size( | ||||
| const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job) | const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job) | ||||
| { | { | ||||
| if ((pi->changed[size] || !pi->rect[size])) { /* changed only ever set by dynamic icons */ | if (((pi->flag[size] & PRV_CHANGED) || !pi->rect[size])) { /* changed only ever set by dynamic icons */ | ||||
| /* create the rect if necessary */ | /* create the rect if necessary */ | ||||
| icon_set_image(C, scene, id, pi, size, use_job); | icon_set_image(C, scene, id, pi, size, use_job); | ||||
| pi->changed[size] = 0; | pi->flag[size] &= ~PRV_CHANGED; | ||||
| } | } | ||||
| } | } | ||||
| void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job) | void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job) | ||||
| { | { | ||||
| PreviewImage *pi = BKE_previewimg_get(id); | PreviewImage *pi = BKE_previewimg_id_ensure(id); | ||||
| if (pi) { | if (pi) { | ||||
| if (big) | if (big) | ||||
| ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_PREVIEW, use_job); /* bigger preview size */ | ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_PREVIEW, use_job); /* bigger preview size */ | ||||
| else | else | ||||
| ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_ICON, use_job); /* icon size */ | ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_ICON, use_job); /* icon size */ | ||||
| } | } | ||||
| } | } | ||||
| static void ui_id_brush_render(const bContext *C, ID *id) | static void ui_id_brush_render(const bContext *C, ID *id) | ||||
| { | { | ||||
| PreviewImage *pi = BKE_previewimg_get(id); | PreviewImage *pi = BKE_previewimg_id_ensure(id); | ||||
| enum eIconSizes i; | enum eIconSizes i; | ||||
| if (!pi) | if (!pi) | ||||
| return; | return; | ||||
| for (i = 0; i < NUM_ICON_SIZES; i++) { | for (i = 0; i < NUM_ICON_SIZES; i++) { | ||||
| /* check if rect needs to be created; changed | /* check if rect needs to be created; changed | ||||
| * only set by dynamic icons */ | * only set by dynamic icons */ | ||||
| if ((pi->changed[i] || !pi->rect[i])) { | if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) { | ||||
| icon_set_image(C, NULL, id, pi, i, true); | icon_set_image(C, NULL, id, pi, i, true); | ||||
| pi->changed[i] = 0; | pi->flag[i] &= ~PRV_CHANGED; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static int ui_id_brush_get_icon(const bContext *C, ID *id) | static int ui_id_brush_get_icon(const bContext *C, ID *id) | ||||
| { | { | ||||
| Brush *br = (Brush *)id; | Brush *br = (Brush *)id; | ||||
| if (br->flag & BRUSH_CUSTOM_ICON) { | if (br->flag & BRUSH_CUSTOM_ICON) { | ||||
| BKE_icon_getid(id); | BKE_icon_id_ensure(id); | ||||
| ui_id_brush_render(C, id); | ui_id_brush_render(C, id); | ||||
| } | } | ||||
| else { | else { | ||||
| Object *ob = CTX_data_active_object(C); | Object *ob = CTX_data_active_object(C); | ||||
| SpaceImage *sima; | SpaceImage *sima; | ||||
| EnumPropertyItem *items = NULL; | EnumPropertyItem *items = NULL; | ||||
| int tool, mode = 0; | int tool, mode = 0; | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | switch (GS(id->name)) { | ||||
| case ID_BR: | case ID_BR: | ||||
| iconid = ui_id_brush_get_icon(C, id); | iconid = ui_id_brush_get_icon(C, id); | ||||
| break; | break; | ||||
| case ID_MA: /* fall through */ | case ID_MA: /* fall through */ | ||||
| case ID_TE: /* fall through */ | case ID_TE: /* fall through */ | ||||
| case ID_IM: /* fall through */ | case ID_IM: /* fall through */ | ||||
| case ID_WO: /* fall through */ | case ID_WO: /* fall through */ | ||||
| case ID_LA: /* fall through */ | case ID_LA: /* fall through */ | ||||
| iconid = BKE_icon_getid(id); | iconid = BKE_icon_id_ensure(id); | ||||
| /* checks if not exists, or changed */ | /* checks if not exists, or changed */ | ||||
| UI_id_icon_render(C, NULL, id, big, true); | UI_id_icon_render(C, NULL, id, big, true); | ||||
| break; | break; | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| return iconid; | return iconid; | ||||
| ▲ Show 20 Lines • Show All 85 Lines • Show Last 20 Lines | |||||