diff --git a/source/blender/editors/space_file/file_draw.cc b/source/blender/editors/space_file/file_draw.cc index b223c75192d..ba846e63139 100644 --- a/source/blender/editors/space_file/file_draw.cc +++ b/source/blender/editors/space_file/file_draw.cc @@ -509,48 +509,9 @@ void file_calc_previews(const bContext *C, ARegion *region) UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height); } -static void file_add_preview_drag_but(const SpaceFile *sfile, - uiBlock *block, - FileLayout *layout, - const FileDirEntry *file, - const char *path, - const rcti *tile_draw_rect, - const ImBuf *preview_image, - const int icon, - const float scale) -{ - /* Invisible button for dragging. */ - rcti drag_rect = *tile_draw_rect; - /* A bit smaller than the full tile, to increase the gap between items that users can drag from - * for box select. */ - BLI_rcti_pad(&drag_rect, -layout->tile_border_x, -layout->tile_border_y); - - uiBut *but = uiDefBut(block, - UI_BTYPE_LABEL, - 0, - "", - drag_rect.xmin, - drag_rect.ymin, - BLI_rcti_size_x(&drag_rect), - BLI_rcti_size_y(&drag_rect), - nullptr, - 0.0, - 0.0, - nullptr); - file_but_enable_drag(but, sfile, file, path, preview_image, icon, scale); - - if (file->asset) { - UI_but_func_tooltip_set(but, file_draw_asset_tooltip_func, file->asset, nullptr); - } - else { - UI_but_func_tooltip_custom_set( - but, file_draw_tooltip_custom_func, file_tooltip_data_create(sfile, file), MEM_freeN); - } -} - static std::tuple preview_image_scaled_dimensions_get(const int image_width, const int image_height, - FileLayout &layout, + const FileLayout &layout, const bool never_scale_up) { const float ui_imbx = image_width * UI_SCALE_FAC; @@ -581,19 +542,60 @@ static std::tuple preview_image_scaled_dimensions_get(const int return std::make_tuple(int(scaledx), int(scaledy), scale); } -static void file_draw_preview(const FileList *files, - const FileDirEntry *file, +static void file_add_preview_drag_but(const SpaceFile *sfile, + uiBlock *block, + FileLayout *layout, + const FileDirEntry *file, + const char *path, + const rcti *tile_draw_rect, + const ImBuf *preview_image, + const int icon, + const bool is_special_file_image) +{ + /* Invisible button for dragging. */ + rcti drag_rect = *tile_draw_rect; + /* A bit smaller than the full tile, to increase the gap between items that users can drag from + * for box select. */ + BLI_rcti_pad(&drag_rect, -layout->tile_border_x, -layout->tile_border_y); + + uiBut *but = uiDefBut(block, + UI_BTYPE_LABEL, + 0, + "", + drag_rect.xmin, + drag_rect.ymin, + BLI_rcti_size_x(&drag_rect), + BLI_rcti_size_y(&drag_rect), + nullptr, + 0.0, + 0.0, + nullptr); + + /* Unlike thumbnails, icons are not scaled up. */ + const bool never_scale_up = is_special_file_image; + + const auto [scaled_width, scaled_height, scale] = preview_image_scaled_dimensions_get( + preview_image->x, preview_image->y, *layout, never_scale_up); + file_but_enable_drag(but, sfile, file, path, preview_image, icon, scale); + + if (file->asset) { + UI_but_func_tooltip_set(but, file_draw_asset_tooltip_func, file->asset, nullptr); + } + else { + UI_but_func_tooltip_custom_set( + but, file_draw_tooltip_custom_func, file_tooltip_data_create(sfile, file), MEM_freeN); + } +} + +static void file_draw_preview(const FileDirEntry *file, const rcti *tile_draw_rect, const float icon_aspect, const ImBuf *imb, const int file_type_icon, FileLayout *layout, const bool is_special_file_image, - const bool dimmed, - float *r_scale) + const bool dimmed) { - const bool is_loading = filelist_file_is_preview_pending(files, file); - BLI_assert(imb != nullptr); /* Unlike thumbnails, icons are not scaled up. */ @@ -641,43 +643,39 @@ static void file_draw_preview(const FileList *files, GPU_blend(GPU_BLEND_ALPHA_PREMULT); } - if (!is_loading) { - /* Don't show outer document image if loading - too flashy. */ - if (is_special_file_image) { - /* Draw large folder or document icon. */ - const int icon_large = (file->typeflag & FILE_TYPE_DIR) ? ICON_FILE_FOLDER_LARGE : - ICON_FILE_LARGE; - uchar icon_col[4]; - rgba_float_to_uchar(icon_col, document_img_col); - float icon_x = float(xmin) + - (file->typeflag & FILE_TYPE_DIR ? 0.0f : scaled_width * -0.142f); - float icon_y = float(ymin) + (file->typeflag & FILE_TYPE_DIR ? scaled_width * -0.11f : 0.0f); - UI_icon_draw_ex(icon_x, - icon_y, - icon_large, - icon_aspect / 4.0f / UI_SCALE_FAC, - document_img_col[3], - 0.0f, - icon_col, - false, - UI_NO_ICON_OVERLAY_TEXT); - } - else { - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); - immDrawPixelsTexTiled_scaling(&state, - float(xmin), - float(ymin), - imb->x, - imb->y, - GPU_RGBA8, - true, - imb->byte_buffer.data, - scale, - scale, - 1.0f, - 1.0f, - document_img_col); - } + if (is_special_file_image) { + /* Draw large folder or document icon. */ + const int icon_large = (file->typeflag & FILE_TYPE_DIR) ? ICON_FILE_FOLDER_LARGE : + ICON_FILE_LARGE; + uchar icon_col[4]; + rgba_float_to_uchar(icon_col, document_img_col); + float icon_x = float(xmin) + (file->typeflag & FILE_TYPE_DIR ? 0.0f : scaled_width * -0.142f); + float icon_y = float(ymin) + (file->typeflag & FILE_TYPE_DIR ? scaled_width * -0.11f : 0.0f); + UI_icon_draw_ex(icon_x, + icon_y, + icon_large, + icon_aspect / 4.0f / UI_SCALE_FAC, + document_img_col[3], + 0.0f, + icon_col, + false, + UI_NO_ICON_OVERLAY_TEXT); + } + else { + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_3D_IMAGE_COLOR); + immDrawPixelsTexTiled_scaling(&state, + float(xmin), + float(ymin), + imb->x, + imb->y, + GPU_RGBA8, + true, + imb->byte_buffer.data, + scale, + scale, + 1.0f, + 1.0f, + document_img_col); } if (file_type_icon && is_special_file_image) { @@ -691,17 +689,12 @@ static void file_draw_preview(const FileList *files, icon_color[2] = 255; } - if (is_loading) { - /* Contrast with background since we are not showing the large document image. */ - UI_GetThemeColor4ubv(TH_TEXT, icon_color); - } - icon_x = xmin + (file->typeflag & FILE_TYPE_DIR ? scaled_width * 0.31f : scaled_width * 0.178f); icon_y = ymin + (file->typeflag & FILE_TYPE_DIR ? scaled_width * 0.19f : scaled_width * 0.15f); UI_icon_draw_ex(icon_x, icon_y, - is_loading ? ICON_TEMP : file_type_icon, + file_type_icon, icon_aspect / UI_SCALE_FAC / (file->typeflag & FILE_TYPE_DIR ? 1.5f : 2.0f), icon_opacity, 0.0f, @@ -738,10 +731,40 @@ static void file_draw_preview(const FileList *files, } GPU_blend(GPU_BLEND_NONE); +} - if (r_scale) { - *r_scale = scale; - } +static void file_draw_loading_icon(const rcti *tile_draw_rect, + const float preview_icon_aspect, + const FileLayout *layout) +{ + /* Small icon in the middle of large image, scaled to fit container and UI scale */ + float icon_opacity = 0.4f; + + uchar icon_color[4] = {0, 0, 0, 255}; + /* Contrast with background since we are not showing the large document image. */ + UI_GetThemeColor4ubv(TH_TEXT, icon_color); + + const auto [scaled_width, scaled_height, scale] = preview_image_scaled_dimensions_get( + 200, 256, *layout, true); + + /* Additional offset to keep the scaled image centered. Difference between maximum + * width/height and the actual width/height, divided by two for centering. */ + const float ofs_x = (float(layout->prv_w) - float(scaled_width)) / 2.0f; + const float ofs_y = (float(layout->prv_h) - float(scaled_height)) / 2.0f; + const int xmin = tile_draw_rect->xmin + layout->prv_border_x + int(ofs_x + 0.5f); + const int ymin = tile_draw_rect->ymax - layout->prv_border_y - layout->prv_h + int(ofs_y + 0.5f); + + const float icon_x = xmin + scaled_width * 0.178f; + const float icon_y = ymin + scaled_width * 0.15f; + UI_icon_draw_ex(icon_x, + icon_y, + ICON_TEMP, + preview_icon_aspect / UI_SCALE_FAC / 2.0f, + icon_opacity, + 0.0f, + icon_color, + false, + UI_NO_ICON_OVERLAY_TEXT); } static void file_draw_indicator_icons(const FileList *files, @@ -1275,23 +1298,34 @@ void file_draw_list(const bContext *C, ARegion *region) is_special_file_image = true; } - float scale = 0; - file_draw_preview(files, - file, - &tile_draw_rect, - thumb_icon_aspect, - imb, - file_type_icon, - layout, - is_special_file_image, - is_hidden, - /* Returns the scale which is needed below. */ - &scale); + const bool is_loading = filelist_file_is_preview_pending(files, file); + if (is_loading) { + file_draw_loading_icon(&tile_draw_rect, thumb_icon_aspect, layout); + } + else { + file_draw_preview(file, + &tile_draw_rect, + thumb_icon_aspect, + imb, + file_type_icon, + layout, + is_special_file_image, + is_hidden); + } + file_draw_indicator_icons( files, file, &tile_draw_rect, thumb_icon_aspect, file_type_icon, is_special_file_image); + if (do_drag) { - file_add_preview_drag_but( - sfile, block, layout, file, path, &tile_draw_rect, imb, file_type_icon, scale); + file_add_preview_drag_but(sfile, + block, + layout, + file, + path, + &tile_draw_rect, + imb, + file_type_icon, + is_special_file_image); } } else {