UI: IDSearch Image Thumbnail Tooltips #118945
|
@ -153,6 +153,12 @@ bool BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser);
|
|||
struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock);
|
||||
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock);
|
||||
|
||||
/**
|
||||
* Return image buffer of preview for given image
|
||||
* width_r & *height_r are optional and return the _original size_ of the image.
|
||||
*/
|
||||
struct ImBuf *BKE_image_preview(struct Image *ima, short max, short *width_r, short *height_r);
|
||||
|
||||
struct ImagePool *BKE_image_pool_new(void);
|
||||
void BKE_image_pool_free(struct ImagePool *pool);
|
||||
struct ImBuf *BKE_image_pool_acquire_ibuf(struct Image *ima,
|
||||
|
|
|
@ -4800,6 +4800,31 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
|
|||
return ibuf != nullptr;
|
||||
}
|
||||
|
||||
ImBuf *BKE_image_preview(struct Image *ima, short max, short *width_r, short *height_r)
|
||||
{
|
||||
void *lock;
|
||||
ImBuf *image_ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock);
|
||||
ImBuf *preview = nullptr;
|
||||
|
||||
if (image_ibuf) {
|
||||
preview = IMB_dupImBuf(image_ibuf);
|
||||
float scale = float(max) / float(std::max(image_ibuf->x, image_ibuf->y));
|
||||
if (width_r) {
|
||||
*width_r = image_ibuf->x;
|
||||
}
|
||||
if (height_r) {
|
||||
*height_r = image_ibuf->y;
|
||||
}
|
||||
BKE_image_release_ibuf(ima, image_ibuf, lock);
|
||||
|
||||
/* Resize. */
|
||||
IMB_scaleImBuf(preview, scale * image_ibuf->x, scale * image_ibuf->y);
|
||||
IMB_rect_from_float(preview);
|
||||
}
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -3302,12 +3302,8 @@ ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz);
|
|||
void UI_tooltip_free(bContext *C, bScreen *screen, ARegion *region);
|
||||
|
||||
struct uiSearchItemTooltipData {
|
||||
/** A description for the item, e.g. what happens when selecting it. */
|
||||
char description[UI_MAX_DRAW_STR];
|
||||
/* The full name of the item, without prefixes or suffixes (e.g. hint with UI_SEP_CHARP). */
|
||||
const char *name;
|
||||
/** Additional info about the item (e.g. library name of a linked data-block). */
|
||||
char hint[UI_MAX_DRAW_STR];
|
||||
ID *id;
|
||||
StructRNA *type;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,28 +31,34 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_screen.hh"
|
||||
|
||||
#include "BIF_glutil.hh"
|
||||
|
||||
#include "DNA_vfont_types.h"
|
||||
|
||||
#include "GPU_immediate.hh"
|
||||
#include "GPU_immediate_util.hh"
|
||||
#include "GPU_state.hh"
|
||||
|
||||
#include "IMB_imbuf.hh"
|
||||
#include "IMB_imbuf_types.hh"
|
||||
#include "IMB_thumbs.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_path.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
|
||||
|
@ -1502,23 +1508,196 @@ ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
|
|||
return ui_tooltip_create_with_data(C, data, init_position, nullptr, aspect);
|
||||
}
|
||||
|
||||
static void ui_tooltip_from_image(Image *ima, uiTooltipData *data)
|
||||
{
|
||||
if (ima->filepath[0]) {
|
||||
char root[FILE_MAX];
|
||||
BLI_path_split_dir_part(ima->filepath, root, FILE_MAX);
|
||||
UI_tooltip_text_field_add(data, root, {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL);
|
||||
}
|
||||
|
||||
std::string image_type;
|
||||
switch (ima->source) {
|
||||
case IMA_SRC_FILE:
|
||||
image_type = TIP_("Single Image");
|
||||
break;
|
||||
case IMA_SRC_SEQUENCE:
|
||||
image_type = TIP_("Image Sequence");
|
||||
break;
|
||||
case IMA_SRC_MOVIE:
|
||||
image_type = TIP_("Movie");
|
||||
break;
|
||||
case IMA_SRC_GENERATED:
|
||||
image_type = TIP_("Generated");
|
||||
break;
|
||||
case IMA_SRC_VIEWER:
|
||||
image_type = TIP_("Viewer");
|
||||
break;
|
||||
case IMA_SRC_TILED:
|
||||
image_type = TIP_("UDIM Tiles");
|
||||
break;
|
||||
}
|
||||
UI_tooltip_text_field_add(data, image_type, {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL);
|
||||
|
||||
short w;
|
||||
short h;
|
||||
ImBuf *ibuf = BKE_image_preview(ima, 200.0f * UI_SCALE_FAC, &w, &h);
|
||||
|
||||
if (ibuf) {
|
||||
UI_tooltip_text_field_add(
|
||||
data, fmt::format("{} \u00D7 {}", w, h), {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL);
|
||||
}
|
||||
|
||||
if (BKE_image_has_anim(ima)) {
|
||||
ImBufAnim *anim = ((ImageAnim *)ima->anims.first)->anim;
|
||||
if (anim) {
|
||||
int duration = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN);
|
||||
UI_tooltip_text_field_add(
|
||||
data, fmt::format("Frames: {}", duration), {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
UI_tooltip_text_field_add(
|
||||
data, ima->colorspace_settings.name, {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL);
|
||||
|
||||
UI_tooltip_text_field_add(
|
||||
data, fmt::format(TIP_("Users: {}"), ima->id.us), {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL);
|
||||
|
||||
if (ibuf) {
|
||||
uiTooltipImage image_data;
|
||||
image_data.width = int(ibuf->x);
|
||||
image_data.height = int(ibuf->y);
|
||||
image_data.ibuf = ibuf;
|
||||
image_data.border = true;
|
||||
image_data.background = uiTooltipImageBackground::Checkerboard_Themed;
|
||||
image_data.premultiplied = true;
|
||||
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, UI_TIP_LC_NORMAL);
|
||||
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, UI_TIP_LC_NORMAL);
|
||||
UI_tooltip_image_field_add(data, image_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_tooltip_from_clip(MovieClip *clip, uiTooltipData *data)
|
||||
{
|
||||
if (clip->filepath[0]) {
|
||||
char root[FILE_MAX];
|
||||
BLI_path_split_dir_part(clip->filepath, root, FILE_MAX);
|
||||
UI_tooltip_text_field_add(data, root, {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL);
|
||||
}
|
||||
|
||||
std::string image_type;
|
||||
switch (clip->source) {
|
||||
case IMA_SRC_SEQUENCE:
|
||||
image_type = TIP_("Image Sequence");
|
||||
break;
|
||||
case IMA_SRC_MOVIE:
|
||||
image_type = TIP_("Movie");
|
||||
break;
|
||||
}
|
||||
UI_tooltip_text_field_add(data, image_type, {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL);
|
||||
|
||||
if (clip->anim) {
|
||||
ImBufAnim *anim = clip->anim;
|
||||
|
||||
UI_tooltip_text_field_add(data,
|
||||
fmt::format("{} \u00D7 {}",
|
||||
IMB_anim_get_image_width(anim),
|
||||
IMB_anim_get_image_height(anim)),
|
||||
{},
|
||||
UI_TIP_STYLE_NORMAL,
|
||||
UI_TIP_LC_NORMAL);
|
||||
|
||||
UI_tooltip_text_field_add(
|
||||
data,
|
||||
fmt::format("Frames: {}", IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN)),
|
||||
{},
|
||||
UI_TIP_STYLE_NORMAL,
|
||||
UI_TIP_LC_NORMAL);
|
||||
|
||||
ImBuf *ibuf = IMB_anim_previewframe(anim);
|
||||
|
||||
if (ibuf) {
|
||||
/* Resize. */
|
||||
float scale = float(200.0f * UI_SCALE_FAC) / float(std::max(ibuf->x, ibuf->y));
|
||||
IMB_scaleImBuf(ibuf, scale * ibuf->x, scale * ibuf->y);
|
||||
IMB_rect_from_float(ibuf);
|
||||
|
||||
uiTooltipImage image_data;
|
||||
image_data.width = int(ibuf->x);
|
||||
image_data.height = int(ibuf->y);
|
||||
image_data.ibuf = ibuf;
|
||||
image_data.border = true;
|
||||
image_data.background = uiTooltipImageBackground::Checkerboard_Themed;
|
||||
image_data.premultiplied = true;
|
||||
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, UI_TIP_LC_NORMAL);
|
||||
UI_tooltip_text_field_add(data, {}, {}, UI_TIP_STYLE_SPACER, UI_TIP_LC_NORMAL);
|
||||
UI_tooltip_image_field_add(data, image_data);
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_tooltip_from_vfont(VFont *font, uiTooltipData *data)
|
||||
{
|
||||
if (!font->filepath[0]) {
|
||||
/* Let's not bother with packed files _for now_.*/
|
||||
return;
|
||||
}
|
||||
|
||||
float color[4];
|
||||
const uiWidgetColors *theme = ui_tooltip_get_theme();
|
||||
rgba_uchar_to_float(color, theme->text);
|
||||
ImBuf *ibuf = IMB_font_preview(font->filepath, 200 * UI_SCALE_FAC, color);
|
||||
if (ibuf) {
|
||||
uiTooltipImage image_data;
|
||||
image_data.width = ibuf->x;
|
||||
image_data.height = ibuf->y;
|
||||
image_data.ibuf = ibuf;
|
||||
image_data.border = false;
|
||||
image_data.background = uiTooltipImageBackground::None;
|
||||
image_data.premultiplied = false;
|
||||
image_data.text_color = true;
|
||||
UI_tooltip_image_field_add(data, image_data);
|
||||
IMB_freeImBuf(ibuf);
|
||||
}
|
||||
}
|
||||
|
||||
static uiTooltipData *ui_tooltip_data_from_search_item_tooltip_data(
|
||||
const uiSearchItemTooltipData *item_tooltip_data)
|
||||
bContext *C, const uiSearchItemTooltipData *item_tooltip_data)
|
||||
{
|
||||
uiTooltipData *data = MEM_new<uiTooltipData>(__func__);
|
||||
const ID_Type type_id = GS(item_tooltip_data->id->name);
|
||||
|
||||
if (item_tooltip_data->description[0]) {
|
||||
UI_tooltip_text_field_add(
|
||||
data, item_tooltip_data->description, {}, UI_TIP_STYLE_HEADER, UI_TIP_LC_NORMAL, true);
|
||||
UI_tooltip_text_field_add(
|
||||
data, item_tooltip_data->id->name + 2, {}, UI_TIP_STYLE_HEADER, UI_TIP_LC_MAIN);
|
||||
|
||||
if (type_id == ID_IM) {
|
||||
ui_tooltip_from_image(reinterpret_cast<Image *>(item_tooltip_data->id), data);
|
||||
}
|
||||
else if (type_id == ID_MC) {
|
||||
ui_tooltip_from_clip(reinterpret_cast<MovieClip *>(item_tooltip_data->id), data);
|
||||
}
|
||||
else if (type_id == ID_VF) {
|
||||
ui_tooltip_from_vfont(reinterpret_cast<VFont *>(item_tooltip_data->id), data);
|
||||
}
|
||||
else {
|
||||
UI_tooltip_text_field_add(data,
|
||||
fmt::format(TIP_("Choose {} data-block to be assigned to this user"),
|
||||
RNA_struct_ui_name(item_tooltip_data->type)),
|
||||
{},
|
||||
UI_TIP_STYLE_NORMAL,
|
||||
UI_TIP_LC_NORMAL);
|
||||
}
|
||||
|
||||
if (item_tooltip_data->name && item_tooltip_data->name[0]) {
|
||||
UI_tooltip_text_field_add(
|
||||
data, item_tooltip_data->name, {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_VALUE, true);
|
||||
}
|
||||
if (item_tooltip_data->hint[0]) {
|
||||
UI_tooltip_text_field_add(
|
||||
data, item_tooltip_data->hint, {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_NORMAL, true);
|
||||
/** Additional info about the item (e.g. library name of a linked data-block). */
|
||||
if (ID_IS_LINKED(item_tooltip_data->id)) {
|
||||
UI_tooltip_text_field_add(data,
|
||||
fmt::format(TIP_("Source library: {}\n{}"),
|
||||
item_tooltip_data->id->lib->id.name + 2,
|
||||
item_tooltip_data->id->lib->filepath),
|
||||
{},
|
||||
UI_TIP_STYLE_NORMAL,
|
||||
UI_TIP_LC_NORMAL);
|
||||
}
|
||||
|
||||
if (data->fields.is_empty()) {
|
||||
|
@ -1534,7 +1713,7 @@ ARegion *UI_tooltip_create_from_search_item_generic(
|
|||
const rcti *item_rect,
|
||||
const uiSearchItemTooltipData *item_tooltip_data)
|
||||
{
|
||||
uiTooltipData *data = ui_tooltip_data_from_search_item_tooltip_data(item_tooltip_data);
|
||||
uiTooltipData *data = ui_tooltip_data_from_search_item_tooltip_data(C, item_tooltip_data);
|
||||
if (data == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -504,17 +504,8 @@ static ARegion *template_ID_search_menu_item_tooltip(
|
|||
StructRNA *type = RNA_property_pointer_type(&template_ui->ptr, template_ui->prop);
|
||||
|
||||
uiSearchItemTooltipData tooltip_data = {{0}};
|
||||
|
||||
tooltip_data.name = active_id->name + 2;
|
||||
SNPRINTF(tooltip_data.description,
|
||||
TIP_("Choose %s data-block to be assigned to this user"),
|
||||
RNA_struct_ui_name(type));
|
||||
if (ID_IS_LINKED(active_id)) {
|
||||
SNPRINTF(tooltip_data.hint,
|
||||
TIP_("Source library: %s\n%s"),
|
||||
active_id->lib->id.name + 2,
|
||||
active_id->lib->filepath);
|
||||
}
|
||||
tooltip_data.id = active_id;
|
||||
tooltip_data.type = type;
|
||||
|
||||
return UI_tooltip_create_from_search_item_generic(C, region, item_rect, &tooltip_data);
|
||||
}
|
||||
|
|
|
@ -91,6 +91,8 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const
|
|||
ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y);
|
||||
bool IMB_thumb_load_font_get_hash(char *r_hash);
|
||||
|
||||
ImBuf *IMB_font_preview(const char *filename, unsigned int width, float color[4]);
|
||||
|
||||
/* Threading */
|
||||
|
||||
void IMB_thumb_locks_acquire();
|
||||
|
|
|
@ -45,3 +45,46 @@ bool IMB_thumb_load_font_get_hash(char *r_hash)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
ImBuf *IMB_font_preview(const char *filename, unsigned int width, float color[4])
|
||||
{
|
||||
int font_id = (filename[0] != '<') ? BLF_load(filename) : 0;
|
||||
const char sample[] = "ABCDEFGH\nabcdefg123";
|
||||
|
||||
BLF_buffer_col(font_id, color);
|
||||
|
||||
BLF_size(font_id, 50.0f);
|
||||
BLF_enable(font_id, BLF_WORD_WRAP);
|
||||
float name_w;
|
||||
float name_h;
|
||||
BLF_width_and_height(font_id, sample, sizeof(sample), &name_w, &name_h);
|
||||
float scale = float(width) / name_w;
|
||||
BLF_size(font_id, scale * 50.0f);
|
||||
name_w *= scale;
|
||||
name_h *= scale;
|
||||
|
||||
int height = int(name_h * 1.3f);
|
||||
ImBuf *ibuf = IMB_allocImBuf(width, height, 32, IB_rect);
|
||||
/* fill with white and zero alpha */
|
||||
const float col[4] = {1.0f, 1.0f, 1.0f, 0.0f};
|
||||
IMB_rectfill(ibuf, col);
|
||||
|
||||
BLF_buffer(font_id,
|
||||
ibuf->float_buffer.data,
|
||||
ibuf->byte_buffer.data,
|
||||
width,
|
||||
height,
|
||||
ibuf->channels,
|
||||
nullptr);
|
||||
|
||||
BLF_position(font_id, 0.0f, name_h * 0.8f, 0.0f);
|
||||
BLF_draw_buffer(font_id, sample, 1024);
|
||||
|
||||
BLF_buffer(font_id, nullptr, nullptr, 0, 0, 0, nullptr);
|
||||
|
||||
if (font_id != 0) {
|
||||
BLF_unload_id(font_id);
|
||||
}
|
||||
|
||||
return ibuf;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue