Blender V5.0
file_draw.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cerrno>
11#include <cstring>
12#include <string>
13
14#include <fmt/format.h>
15
16#include "MEM_guardedalloc.h"
17
19
20#include "BLI_fileops.h"
21#include "BLI_fileops_types.h"
22#include "BLI_listbase.h"
23#include "BLI_math_color.h"
24#include "BLI_math_vector.h"
25#include "BLI_path_utils.hh"
26#include "BLI_string.h"
27#include "BLI_string_utf8.h"
28#include "BLI_utildefines.h"
29
30#ifdef WIN32
31# include "BLI_winstuff.h"
32#endif
33
34#include "BIF_glutil.hh"
35
36#include "BKE_blendfile.hh"
37#include "BKE_context.hh"
38#include "BKE_report.hh"
39
40#include "BLO_readfile.hh"
41
42#include "BLT_translation.hh"
43
44#include "BLF_api.hh"
45
46#include "IMB_imbuf.hh"
47#include "IMB_imbuf_types.hh"
48#include "IMB_metadata.hh"
49#include "IMB_thumbs.hh"
50
51#include "DNA_userdef_types.h"
53
54#include "RNA_access.hh"
55#include "RNA_prototypes.hh"
56
57#include "ED_asset.hh"
58#include "ED_fileselect.hh"
59#include "ED_screen.hh"
60
61#include "UI_interface.hh"
62#include "UI_interface_icons.hh"
63#include "UI_resources.hh"
64#include "UI_view2d.hh"
65
66#include "WM_api.hh"
67#include "WM_types.hh"
68
69#include "GPU_immediate.hh"
70#include "GPU_immediate_util.hh"
71#include "GPU_state.hh"
72
73#include "filelist.hh"
74
75#include "file_intern.hh" /* own include */
76
78 const SpaceFile *sfile,
80 uiBlock *block)
81{
82 uiBut *but;
83
84 BLI_assert_msg(params != nullptr,
85 "File select parameters not set. The caller is expected to check this.");
86
88 &screen->id, &RNA_FileSelectParams, params);
89
90 /* callbacks for operator check functions */
91 UI_block_func_set(block, file_draw_check_cb, nullptr, nullptr);
92
93 but = uiDefButR(block,
95 -1,
96 "",
97 0,
98 0,
99 UI_UNIT_X * 10,
100 UI_UNIT_Y,
101 &params_rna_ptr,
102 "directory",
103 0,
104 0.0f,
105 float(FILE_MAX),
106 TIP_("File path"));
107
110
113
114 /* TODO: directory editing is non-functional while a library is loaded
115 * until this is properly supported just disable it. */
116 if (sfile && sfile->files && filelist_lib(sfile->files)) {
118 }
119
120 /* clear func */
121 UI_block_func_set(block, nullptr, nullptr, nullptr);
122}
123
128
130{
132 data->sfile = sfile;
133 data->file = file;
134 return data;
135}
136
138 uiTooltipData &tip,
139 uiBut * /*but*/,
140 void *argN)
141{
142 FileTooltipData *file_data = static_cast<FileTooltipData *>(argN);
143 const SpaceFile *sfile = file_data->sfile;
144 const FileList *files = sfile->files;
146 const FileDirEntry *file = file_data->file;
147
148 BLI_assert_msg(!file->asset, "Asset tooltip should never be overridden here.");
149
150 /* Check the FileDirEntry first to see if the preview is already loaded. */
152
153 /* Only free if it is loaded later. */
154 bool free_imbuf = (thumb == nullptr);
155
158
159 if (!(file->typeflag & FILE_TYPE_BLENDERLIB)) {
160
161 char full_path[FILE_MAX_LIBEXTRA];
162 filelist_file_get_full_path(files, file, full_path);
163
164 if (params->recursion_level > 0) {
165 char root[FILE_MAX];
166 BLI_path_split_dir_part(full_path, root, FILE_MAX);
168 }
169
170 if (file->redirection_path) {
172 fmt::format("{}: {}", N_("Link target"), file->redirection_path),
173 {},
176 }
177 if (file->attributes & FILE_ATTR_OFFLINE) {
179 tip, N_("This file is offline"), {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_ALERT);
180 }
181 if (file->attributes & FILE_ATTR_READONLY) {
183 tip, N_("This file is read-only"), {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_ALERT);
184 }
187 tip, N_("This is a restricted system file"), {}, UI_TIP_STYLE_NORMAL, UI_TIP_LC_ALERT);
188 }
189
191 char version_str[128] = {0};
192 if (!thumb) {
193 /* Load the thumbnail from cache if existing, but don't create if not. */
194 thumb = IMB_thumb_read(full_path, THB_LARGE);
195 }
196 if (thumb) {
197 /* Look for version in existing thumbnail if available. */
199 thumb->metadata, "Thumb::Blender::Version", version_str, sizeof(version_str));
200 }
201
202 if (!version_str[0] && !(file->attributes & FILE_ATTR_OFFLINE)) {
203 /* Load Blender version directly from the file. */
204 short version = BLO_version_from_file(full_path);
205 if (version != 0) {
206 SNPRINTF_UTF8(version_str, "%d.%01d", version / 100, version % 100);
207 }
208 }
209
210 if (version_str[0]) {
212 fmt::format("Blender {}", version_str),
213 {},
217 }
218 }
219 else if (file->typeflag & FILE_TYPE_IMAGE) {
220 if (!thumb) {
221 /* Load the thumbnail from cache if existing, create if not. */
222 thumb = IMB_thumb_manage(full_path, THB_LARGE, THB_SOURCE_IMAGE);
223 }
224 if (thumb) {
225 char value1[128];
226 char value2[128];
228 thumb->metadata, "Thumb::Image::Width", value1, sizeof(value1)) &&
230 thumb->metadata, "Thumb::Image::Height", value2, sizeof(value2)))
231 {
233 fmt::format("{} \u00D7 {}", value1, value2),
234 {},
238 }
239 }
240 }
241 else if (file->typeflag & FILE_TYPE_MOVIE) {
242 if (!thumb) {
243 /* This could possibly take a while. */
244 thumb = IMB_thumb_manage(full_path, THB_LARGE, THB_SOURCE_MOVIE);
245 }
246 if (thumb) {
247 char value1[128];
248 char value2[128];
249 char value3[128];
251 thumb->metadata, "Thumb::Video::Width", value1, sizeof(value1)) &&
253 thumb->metadata, "Thumb::Video::Height", value2, sizeof(value2)))
254 {
256 fmt::format("{} \u00D7 {}", value1, value2),
257 {},
260 }
262 thumb->metadata, "Thumb::Video::Frames", value1, sizeof(value1)) &&
263 IMB_metadata_get_field(thumb->metadata, "Thumb::Video::FPS", value2, sizeof(value2)) &&
265 thumb->metadata, "Thumb::Video::Duration", value3, sizeof(value3)))
266 {
268 tip,
269 fmt::format("{} {} @ {} {}", value1, N_("Frames"), value2, N_("FPS")),
270 {},
274 fmt::format("{} {}", value3, N_("seconds")),
275 {},
279 }
280 }
281 }
282 else if (file->typeflag & FILE_TYPE_FTFONT) {
283 float color[4];
284 bTheme *btheme = UI_GetTheme();
286 thumb = IMB_font_preview(full_path,
287 512 * UI_SCALE_FAC,
288 color,
289 TIP_("The five boxing wizards jump quickly! 0123456789"));
290 free_imbuf = true;
291 }
292
294 bool is_today, is_yesterday;
295 std::string day_string;
297 nullptr, file->time, false, time_str, date_str, &is_today, &is_yesterday);
298 if (is_today || is_yesterday) {
299 day_string = (is_today ? N_("Today") : N_("Yesterday")) + std::string(" ");
300 }
302 fmt::format("{}: {}{}{}",
303 N_("Modified"),
304 day_string,
305 (is_today || is_yesterday) ? "" : date_str,
306 (is_today || is_yesterday) ? time_str : ""),
307 {},
310
311 if (!(file->typeflag & FILE_TYPE_DIR) && file->size > 0) {
312 char size[16];
313 BLI_filelist_entry_size_to_string(nullptr, file->size, false, size);
314 if (file->size < 10000) {
316 BLI_str_format_uint64_grouped(size_full, file->size);
318 tip,
319 fmt::format("{}: {} ({} {})", N_("Size"), size, size_full, N_("bytes")),
320 {},
323 }
324 else {
326 fmt::format("{}: {}", N_("Size"), size),
327 {},
330 }
331 }
332 }
333
334 if (thumb && file->typeflag & FILE_TYPE_FTFONT) {
335 const float scale = (512.0f * UI_SCALE_FAC) / float(std::max(thumb->x, thumb->y));
336 uiTooltipImage image_data;
337 image_data.ibuf = thumb;
338 image_data.width = short(float(thumb->x) * scale);
339 image_data.height = short(float(thumb->y) * scale);
341 image_data.premultiplied = false;
342 image_data.text_color = true;
343 image_data.border = false;
345 UI_tooltip_image_field_add(tip, image_data);
346 }
347 else if (thumb && params->display != FILE_IMGDISPLAY) {
350
351 uiTooltipImage image_data;
352 float scale = (96.0f * UI_SCALE_FAC) / float(std::max(thumb->x, thumb->y));
353 image_data.ibuf = thumb;
354 image_data.width = short(float(thumb->x) * scale);
355 image_data.height = short(float(thumb->y) * scale);
356 image_data.border = true;
357 image_data.background = uiTooltipImageBackground::Checkerboard_Themed;
358 image_data.premultiplied = true;
359 UI_tooltip_image_field_add(tip, image_data);
360 }
361
362 if (thumb && free_imbuf) {
363 IMB_freeImBuf(thumb);
364 }
365}
366
368 uiTooltipData &tip,
369 uiBut * /*but*/,
370 void *argN)
371{
372 const auto *asset = static_cast<blender::asset_system::AssetRepresentation *>(argN);
374}
375
376static void draw_tile_background(const rcti *draw_rect, int colorid, int shade)
377{
378 float color[4];
379 rctf draw_rect_fl;
380 BLI_rctf_rcti_copy(&draw_rect_fl, draw_rect);
381
382 UI_GetThemeColorShade4fv(colorid, shade, color);
384 UI_draw_roundbox_aa(&draw_rect_fl, true, 5.0f, color);
385}
386
388 const SpaceFile *sfile,
389 const FileDirEntry *file,
390 const char *path,
391 const ImBuf *preview_image,
392 int icon,
393 float scale)
394{
395 ID *id;
396
397 if ((id = filelist_file_get_id(file))) {
398 UI_but_drag_set_id(but, id);
399 if (preview_image) {
400 UI_but_drag_attach_image(but, preview_image, scale);
401 }
402 }
403 else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS &&
404 (file->typeflag & FILE_TYPE_ASSET) != 0)
405 {
406 const int import_method = ED_fileselect_asset_import_method_get(sfile, file);
407 BLI_assert(import_method > -1);
408 if (import_method > -1) {
409 AssetImportSettings import_settings{};
410 import_settings.method = eAssetImportMethod(import_method);
411 import_settings.use_instance_collections =
412 (sfile->asset_params->import_flags &
413 (ELEM(import_method, ASSET_IMPORT_LINK, ASSET_IMPORT_PACK) ?
416
417 UI_but_drag_set_asset(but, file->asset, import_settings, icon, file->preview_icon_id);
418 }
419 }
420 else if (preview_image) {
421 UI_but_drag_set_image(but, path, icon, preview_image, scale);
422 }
423 else {
424 /* path is no more static, cannot give it directly to but... */
425 UI_but_drag_set_path(but, path);
426 }
427}
428
429static void file_but_tooltip_func_set(const SpaceFile *sfile, const FileDirEntry *file, uiBut *but)
430{
431 if (file->asset) {
433 }
434 else {
437 }
438}
439
440static uiBut *file_add_icon_but(const SpaceFile *sfile,
441 uiBlock *block,
442 const char * /*path*/,
443 const FileDirEntry *file,
444 const rcti *tile_draw_rect,
445 int icon,
446 int width,
447 int height,
448 int padx,
449 bool dimmed)
450{
451 uiBut *but;
452
453 const int x = tile_draw_rect->xmin + padx;
454 const int y = tile_draw_rect->ymin +
455 round_fl_to_int((BLI_rcti_size_y(tile_draw_rect) - height) / 2.0f);
456
457 if (icon < BIFICONID_LAST_STATIC) {
458 /* Small built-in icon. Draw centered in given width. */
459 but = uiDefIconBut(
460 block, ButType::Label, 0, icon, x, y, width, height, nullptr, 0.0f, 0.0f, std::nullopt);
461 /* Center the icon. */
463 }
464 else {
465 /* Larger preview icon. Fills available width/height. */
467 block, ButType::Label, 0, icon, x, y, width, height, nullptr, 0.0f, 0.0f, std::nullopt);
468 }
469 UI_but_label_alpha_factor_set(but, dimmed ? 0.3f : 1.0f);
470 file_but_tooltip_func_set(sfile, file, but);
471
472 return but;
473}
474
475static uiBut *file_add_overlay_icon_but(uiBlock *block, int pos_x, int pos_y, int icon)
476{
477 uiBut *but = uiDefIconBut(block,
479 0,
480 icon,
481 pos_x,
482 pos_y,
485 nullptr,
486 0.0f,
487 0.0f,
488 std::nullopt);
489 /* Otherwise a left hand padding will be added. */
492 const uchar light[4] = {255, 255, 255, 255};
493 UI_but_color_set(but, light);
494
495 return but;
496}
497
498static void file_draw_string(int sx,
499 int sy,
500 const char *string,
501 float width,
502 int height,
503 eFontStyle_Align align,
504 const uchar col[4])
505{
506 uiFontStyle fs;
507 rcti rect;
508 char filename[FILE_MAXFILE];
509
510 if (string[0] == '\0' || width < 1) {
511 return;
512 }
513
514 const uiStyle *style = UI_style_get();
515 fs = style->widget;
516
517 STRNCPY(filename, string);
518 UI_text_clip_middle_ex(&fs, filename, width, UI_ICON_SIZE, sizeof(filename), '\0');
519
520 /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict
521 * (for buttons it works) */
522 rect.xmin = sx;
523 rect.xmax = sx + round_fl_to_int(width);
524 rect.ymin = sy - height;
525 rect.ymax = sy;
526
527 uiFontStyleDraw_Params font_style_params{};
528 font_style_params.align = align;
529
530 UI_fontstyle_draw(&fs, &rect, filename, sizeof(filename), col, &font_style_params);
531}
532
537 const char *string,
538 eFontStyle_Align align,
539 const uchar col[4])
540{
541 if (string[0] == '\0' || BLI_rcti_size_x(rect) < 1) {
542 return;
543 }
544
545 const uiStyle *style = UI_style_get();
546 uiFontStyle fs = style->widget;
547
548 UI_fontstyle_draw_multiline_clipped(&fs, rect, string, col, align);
549}
550
556static void file_draw_string_multiline(int sx,
557 int sy,
558 const char *string,
559 int wrap_width,
560 int line_height,
561 const uchar text_col[4],
562 int *r_sx,
563 int *r_sy)
564{
565 rcti rect;
566
567 if (string[0] == '\0' || wrap_width < 1) {
568 return;
569 }
570
571 const uiStyle *style = UI_style_get();
572 int font_id = style->widget.uifont_id;
573 int len = strlen(string);
574
575 rcti textbox;
576 BLF_wordwrap(font_id, wrap_width);
577 BLF_enable(font_id, BLF_WORD_WRAP);
578 BLF_boundbox(font_id, string, len, &textbox);
579 BLF_disable(font_id, BLF_WORD_WRAP);
580
581 /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict
582 * (for buttons it works) */
583 rect.xmin = sx;
584 rect.xmax = sx + wrap_width;
585 /* Need to increase the clipping rect by one more line, since the #UI_fontstyle_draw_ex() will
586 * actually start drawing at (ymax - line-height). */
587 rect.ymin = sy - BLI_rcti_size_y(&textbox) - line_height;
588 rect.ymax = sy;
589
590 uiFontStyleDraw_Params font_style_params{};
591 font_style_params.align = UI_STYLE_TEXT_LEFT;
592 font_style_params.word_wrap = true;
593
596 &style->widget, &rect, string, len, text_col, &font_style_params, nullptr, nullptr, &result);
597 if (r_sx) {
598 *r_sx = result.width;
599 }
600 if (r_sy) {
601 *r_sy = rect.ymin + line_height;
602 }
603}
604
606{
607 SpaceFile *sfile = CTX_wm_space_file(C);
608 View2D *v2d = &region->v2d;
609
610 ED_fileselect_init_layout(sfile, region);
611 UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
612}
613
614static std::tuple<int, int, float> preview_image_scaled_dimensions_get(const int image_width,
615 const int image_height,
616 const FileLayout &layout)
617{
618 const float ui_imbx = image_width * UI_SCALE_FAC;
619 const float ui_imby = image_height * UI_SCALE_FAC;
620
621 float scale;
622 float scaledx, scaledy;
623 if (((ui_imbx > layout.prv_w) || (ui_imby > layout.prv_h)) ||
624 ((ui_imbx < layout.prv_w) || (ui_imby < layout.prv_h)))
625 {
627 scaledx = float(layout.prv_w);
628 scaledy = (float(image_height) / float(image_width)) * layout.prv_w;
629 scale = scaledx / image_width;
630 }
631 else {
632 scaledy = float(layout.prv_h);
633 scaledx = (float(image_width) / float(image_height)) * layout.prv_h;
634 scale = scaledy / image_height;
635 }
636 }
637 else {
638 scaledx = ui_imbx;
639 scaledy = ui_imby;
640 scale = UI_SCALE_FAC;
641 }
642
643 return std::make_tuple(int(scaledx), int(scaledy), scale);
644}
645
646static void file_add_preview_drag_but(const SpaceFile *sfile,
647 uiBlock *block,
648 FileLayout *layout,
649 const FileDirEntry *file,
650 const char *path,
651 const rcti *tile_draw_rect,
652 const ImBuf *preview_image,
653 const int file_type_icon)
654{
655 /* Invisible button for dragging. */
656 rcti drag_rect = *tile_draw_rect;
657 /* A bit smaller than the full tile, to increase the gap between items that users can drag from
658 * for box select. */
659 BLI_rcti_pad(&drag_rect, -layout->tile_border_x, -layout->tile_border_y);
660
661 uiBut *but = uiDefBut(block,
663 0,
664 "",
665 drag_rect.xmin,
666 drag_rect.ymin,
667 BLI_rcti_size_x(&drag_rect),
668 BLI_rcti_size_y(&drag_rect),
669 nullptr,
670 0.0,
671 0.0,
672 std::nullopt);
673
674 const ImBuf *drag_image = preview_image ? preview_image :
675 /* Larger directory or document icon. */
677 const float scale = (PREVIEW_DRAG_DRAW_SIZE * UI_SCALE_FAC) /
678 std::max(drag_image->x, drag_image->y);
679 file_but_enable_drag(but, sfile, file, path, drag_image, file_type_icon, scale);
680 file_but_tooltip_func_set(sfile, file, but);
681}
682
683static void file_draw_preview(const FileDirEntry *file,
684 const rcti *tile_draw_rect,
685 const ImBuf *imb,
686 FileLayout *layout,
687 const bool dimmed)
688{
689 BLI_assert(imb != nullptr);
690
691 const auto [scaled_width, scaled_height, scale] = preview_image_scaled_dimensions_get(
692 imb->x, imb->y, *layout);
693
694 /* Additional offset to keep the scaled image centered. Difference between maximum
695 * width/height and the actual width/height, divided by two for centering. */
696 const float ofs_x = (float(layout->prv_w) - float(scaled_width)) / 2.0f;
697 const float ofs_y = (float(layout->prv_h) - float(scaled_height)) / 2.0f;
698 const int xmin = tile_draw_rect->xmin + layout->prv_border_x + int(ofs_x + 0.5f);
699 const int ymin = tile_draw_rect->ymax - layout->prv_border_y - layout->prv_h + int(ofs_y + 0.5f);
700
702
703 float document_img_col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
704 if (file->typeflag & FILE_TYPE_FTFONT) {
705 UI_GetThemeColor4fv(TH_TEXT, document_img_col);
706 }
707 if (dimmed) {
708 document_img_col[3] *= 0.3f;
709 }
710
712 /* Draw checker pattern behind image previews in case they have transparency. */
714 float(xmin), float(ymin), float(xmin + scaled_width), float(ymin + scaled_height));
715 }
716
717 if (file->typeflag & FILE_TYPE_BLENDERLIB) {
718 /* Datablock preview images use premultiplied alpha. */
720 }
721
724 float(xmin),
725 float(ymin),
726 imb->x,
727 imb->y,
728 blender::gpu::TextureFormat::UNORM_8_8_8_8,
729 true,
730 imb->byte_buffer.data,
731 scale,
732 scale,
733 1.0f,
734 1.0f,
735 document_img_col);
736
737 const bool show_outline = (file->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_OBJECT_IO |
739 /* Contrasting outline around some preview types. */
740 if (show_outline) {
742
744 uint pos = GPU_vertformat_attr_add(format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
746 float border_color[4] = {1.0f, 1.0f, 1.0f, 0.15f};
747 float bgcolor[4];
749 if (srgb_to_grayscale(bgcolor) > 0.5f) {
750 border_color[0] = 0.0f;
751 border_color[1] = 0.0f;
752 border_color[2] = 0.0f;
753 }
754 immUniformColor4fv(border_color);
756 float(xmin),
757 float(ymin),
758 float(xmin + scaled_width + 1),
759 float(ymin + scaled_height + 1));
761 }
762
764}
765
766static void file_draw_special_image(const FileDirEntry *file,
767 const rcti *tile_draw_rect,
768 const int file_type_icon,
769 const float icon_aspect,
770 const FileLayout *layout,
771 const bool dimmed)
772{
773 float document_img_col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
774 if (file->typeflag & FILE_TYPE_DIR) {
775 UI_GetThemeColor4fv(TH_ICON_FOLDER, document_img_col);
776 }
777 else {
778 UI_GetThemeColor4fv(TH_TEXT, document_img_col);
779 }
780
781 if (dimmed) {
782 document_img_col[3] *= 0.3f;
783 }
784
786
787 const int cent_x = tile_draw_rect->xmin + layout->prv_border_x + (layout->prv_w / 2.0f) + 0.5f;
788 const int cent_y = tile_draw_rect->ymax - layout->prv_border_y - (layout->prv_h / 2.0f) + 0.5f;
789 const float aspect = icon_aspect / UI_SCALE_FAC;
790
791 {
792 /* Draw large folder or document icon. */
793 const int icon_large = (file->typeflag & FILE_TYPE_DIR) ? ICON_FILE_FOLDER_LARGE :
794 ICON_FILE_LARGE;
795
796 uchar icon_col[4];
797 rgba_float_to_uchar(icon_col, document_img_col);
798
799 const float scale = 4.0f;
800 const float ofs_y = (file->typeflag & FILE_TYPE_DIR ? -0.02f : 0.0f) * layout->prv_h;
801
802 UI_icon_draw_ex(cent_x - (ICON_DEFAULT_WIDTH * scale / aspect / 2.0f),
803 cent_y - (ICON_DEFAULT_HEIGHT * scale / aspect / 2.0f) + ofs_y,
804 icon_large,
805 icon_aspect / UI_SCALE_FAC / scale,
806 document_img_col[3],
807 0.0f,
808 icon_col,
809 false,
811 }
812
813 if (file_type_icon) {
814 /* Small icon in the middle of large image, scaled to fit container and UI scale */
815 float icon_opacity = 0.4f;
816 uchar icon_color[4] = {0, 0, 0, 255};
817 if (srgb_to_grayscale(document_img_col) < 0.5f) {
818 icon_color[0] = 255;
819 icon_color[1] = 255;
820 icon_color[2] = 255;
821 }
822
823 const float scale = file->typeflag & FILE_TYPE_DIR ? 1.5f : 2.0f;
824 const float ofs_y = (file->typeflag & FILE_TYPE_DIR ? -0.035f : -0.135f) * layout->prv_h;
825
826 UI_icon_draw_ex(cent_x - (ICON_DEFAULT_WIDTH * scale / aspect / 2.0f),
827 cent_y - (ICON_DEFAULT_HEIGHT * scale / aspect / 2.0f) + ofs_y,
828 file_type_icon,
829 icon_aspect / UI_SCALE_FAC / scale,
830 icon_opacity,
831 0.0f,
832 icon_color,
833 false,
835 }
836
838}
839
840static void file_draw_loading_icon(const rcti *tile_draw_rect,
841 const float preview_icon_aspect,
842 const FileLayout *layout)
843{
844 uchar icon_color[4] = {0, 0, 0, 255};
845 /* Contrast with background since we are not showing the large document image. */
846 UI_GetThemeColor4ubv(TH_TEXT, icon_color);
847
848 const int cent_x = tile_draw_rect->xmin + layout->prv_border_x + (layout->prv_w / 2.0f) + 0.5f;
849 const int cent_y = tile_draw_rect->ymax - layout->prv_border_y - (layout->prv_h / 2.0f) + 0.5f;
850 const float aspect = preview_icon_aspect / UI_SCALE_FAC;
851
852 UI_icon_draw_ex(cent_x - (ICON_DEFAULT_WIDTH / aspect / 2.0f),
853 cent_y - (ICON_DEFAULT_HEIGHT / aspect / 2.0f),
854 ICON_PREVIEW_LOADING,
855 aspect,
856 1.0f,
857 0.0f,
858 icon_color,
859 false,
861}
862
863static void file_draw_indicator_icons(const FileList *files,
864 const FileDirEntry *file,
865 const FileLayout *layout,
866 const rcti *tile_draw_rect,
867 const float preview_icon_aspect,
868 const int file_type_icon,
869 const bool has_special_file_image)
870{
871 const bool is_offline = (file->attributes & FILE_ATTR_OFFLINE);
872 const bool is_link = (file->attributes & FILE_ATTR_ANY_LINK);
873 const bool is_loading = filelist_file_is_preview_pending(files, file);
874
875 /* Don't draw these icons if the preview image is small. They are just indicators and shouldn't
876 * cover the preview. */
877 if (preview_icon_aspect < 2.0f) {
878 const float icon_x = float(tile_draw_rect->xmin) + (3.0f * UI_SCALE_FAC);
879 const float icon_y = float(tile_draw_rect->ymax) - layout->prv_border_y - layout->prv_h;
880 const uchar light[4] = {255, 255, 255, 255};
881 if (is_offline) {
882 /* Icon at bottom to indicate the file is offline. */
883 UI_icon_draw_ex(icon_x,
884 icon_y,
885 ICON_INTERNET,
886 1.0f / UI_SCALE_FAC,
887 0.6f,
888 0.0f,
889 light,
890 true,
892 }
893 else if (is_link) {
894 /* Icon at bottom to indicate it is a shortcut, link, or alias. */
895 UI_icon_draw_ex(icon_x,
896 icon_y,
897 ICON_FILE_ALIAS,
898 1.0f / UI_SCALE_FAC,
899 0.6f,
900 0.0f,
901 nullptr,
902 false,
904 }
905 else if (file_type_icon) {
906 /* Smaller, fainter type icon at bottom-left.
907 *
908 * Always draw while loading, the preview shows a loading icon and doesn't indicate the type
909 * yet then. After loading, the special file image may already draw the type icon in
910 * #file_draw_preview(), don't draw it again here. Also don't draw it for font files, they
911 * render a font preview already, the type indicator would be redundant.
912 */
913 if (is_loading || !(has_special_file_image || (file->typeflag & FILE_TYPE_FTFONT))) {
914 UI_icon_draw_ex(icon_x,
915 icon_y,
916 file_type_icon,
917 1.0f / UI_SCALE_FAC,
918 0.6f,
919 0.0f,
920 light,
921 true,
923 }
924 }
925 }
926
927 const bool is_current_main_data = filelist_file_get_id(file) != nullptr;
928 if (is_current_main_data) {
929 /* Smaller, fainter icon at the top-right indicating that the file represents data from the
930 * current file (from current #Main in fact). */
931 float icon_x, icon_y;
932 const uchar light[4] = {255, 255, 255, 255};
933 icon_x = float(tile_draw_rect->xmax) - (16.0f * UI_SCALE_FAC);
934 icon_y = float(tile_draw_rect->ymax) - (20.0f * UI_SCALE_FAC);
935 UI_icon_draw_ex(icon_x,
936 icon_y,
937 ICON_CURRENT_FILE,
938 1.0f / UI_SCALE_FAC,
939 0.6f,
940 0.0f,
941 light,
942 true,
944 }
945}
946
947static void renamebutton_cb(bContext *C, void * /*arg1*/, char *oldname)
948{
949 char newname[FILE_MAX + 12];
950 char orgname[FILE_MAX + 12];
951 char filename[FILE_MAX + 12];
953 wmWindow *win = CTX_wm_window(C);
955 ARegion *region = CTX_wm_region(C);
957
958 BLI_path_join(orgname, sizeof(orgname), params->dir, oldname);
959 STRNCPY(filename, params->renamefile);
961 BLI_path_join(newname, sizeof(newname), params->dir, filename);
962
963 if (!STREQ(orgname, newname)) {
964 errno = 0;
965 if ((BLI_rename(orgname, newname) != 0) || !BLI_exists(newname)) {
967 RPT_ERROR, "Could not rename: %s", errno ? strerror(errno) : "unknown error");
968 WM_report_banner_show(wm, win);
969 /* Renaming failed, reset the name for further renaming handling. */
970 STRNCPY(params->renamefile, oldname);
971 }
972 else {
973 /* If rename is successful, set renamefile to newly renamed entry.
974 * This is used later to select and scroll to the file.
975 */
976 STRNCPY(params->renamefile, filename);
977 }
978
979 /* Ensure we select and scroll to the renamed file.
980 * This is done even if the rename fails as we want to make sure that the file we tried to
981 * rename is still selected and in view. (it can move if something added files/folders to the
982 * directory while we were renaming.
983 */
985 /* to make sure we show what is on disk */
986 ED_fileselect_clear(wm, sfile);
987 ED_region_tag_redraw(region);
988 }
989}
990
991static void draw_background(FileLayout *layout, View2D *v2d)
992{
993 const int item_height = layout->tile_h + (2 * layout->tile_border_y);
994 int i;
995 int sy;
996
998 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1000 float col_alternating[4];
1001 UI_GetThemeColor4fv(TH_ROW_ALTERNATE, col_alternating);
1003
1004 /* alternating flat shade background */
1005 for (i = 2; (i <= layout->rows + 1); i += 2) {
1006 sy = int(v2d->cur.ymax) - layout->offset_top - i * item_height - layout->list_padding_top;
1007
1008 /* Offset pattern slightly to add scroll effect. */
1009 sy += round_fl_to_int(item_height * (v2d->tot.ymax - v2d->cur.ymax) / item_height);
1010
1011 immRectf(pos,
1012 v2d->cur.xmin,
1013 float(sy),
1014 v2d->cur.xmax,
1015 float(sy + layout->tile_h + 2 * layout->tile_border_y));
1016 }
1017
1019}
1020
1021static void draw_dividers(FileLayout *layout, View2D *v2d)
1022{
1023 /* vertical column dividers */
1024
1025 const int step = (layout->tile_w + 2 * layout->tile_border_x);
1026
1027 uint vertex_len = 0;
1028 int sx = int(v2d->tot.xmin);
1029 while (sx < v2d->cur.xmax) {
1030 sx += step;
1031 vertex_len += 4; /* vertex_count = 2 points per line * 2 lines per divider */
1032 }
1033
1034 if (vertex_len > 0) {
1035 float v1[2], v2[2];
1036 float col_hi[3], col_lo[3];
1037
1038 UI_GetThemeColorShade3fv(TH_BACK, 30, col_hi);
1039 UI_GetThemeColorShade3fv(TH_BACK, -30, col_lo);
1040
1041 v1[1] = v2d->cur.ymax - layout->tile_border_y;
1042 v2[1] = v2d->cur.ymin;
1043
1045 uint pos = GPU_vertformat_attr_add(format, "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1047 format, "color", blender::gpu::VertAttrType::SFLOAT_32_32_32);
1048
1050 immBegin(GPU_PRIM_LINES, vertex_len);
1051
1052 sx = int(v2d->tot.xmin);
1053 while (sx < v2d->cur.xmax) {
1054 sx += step;
1055
1056 v1[0] = v2[0] = sx;
1057 immAttrSkip(color);
1058 immVertex2fv(pos, v1);
1059 immAttr3fv(color, col_lo);
1061
1062 v1[0] = v2[0] = sx + 1;
1063 immAttrSkip(color);
1064 immVertex2fv(pos, v1);
1065 immAttr3fv(color, col_hi);
1067 }
1068
1069 immEnd();
1071 }
1072}
1073
1074static void draw_columnheader_background(const FileLayout *layout, const View2D *v2d)
1075{
1077 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1078
1081
1082 immRectf(pos,
1083 v2d->cur.xmin,
1084 v2d->cur.ymax - layout->attribute_column_header_h,
1085 v2d->cur.xmax,
1086 v2d->cur.ymax);
1087
1089}
1090
1092 FileLayout *layout,
1093 const View2D *v2d,
1094 const uchar text_col[4])
1095{
1096 const float divider_pad = 0.2 * layout->attribute_column_header_h;
1097 int sx = v2d->cur.xmin, sy = v2d->cur.ymax;
1098
1099 for (int column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX; column_type++) {
1101 {
1102 continue;
1103 }
1104 const FileAttributeColumn *column = &layout->attribute_columns[column_type];
1105
1106 /* Active sort type triangle */
1107 if (params->sort == column->sort_type) {
1108 float tri_color[4];
1109
1110 rgba_uchar_to_float(tri_color, text_col);
1111 UI_draw_icon_tri(sx + column->width - (0.3f * U.widget_unit) -
1113 sy + (0.1f * U.widget_unit) - (layout->attribute_column_header_h / 2),
1114 (params->flag & FILE_SORT_INVERT) ? 't' : 'v',
1115 tri_color);
1116 }
1117
1119 sy - layout->tile_border_y,
1120 IFACE_(column->name),
1121 column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
1122 layout->attribute_column_header_h - layout->tile_border_y,
1124 text_col);
1125
1126 /* Separator line */
1127 if (column_type != COLUMN_NAME) {
1129 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1130
1134 immVertex2f(pos, sx - 1, sy - divider_pad);
1135 immVertex2f(pos, sx - 1, sy - layout->attribute_column_header_h + divider_pad);
1136 immEnd();
1138 }
1139
1140 sx += column->width;
1141 }
1142
1143 /* Vertical separator lines line */
1144 {
1146 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1150 immVertex2f(pos, v2d->cur.xmin, sy);
1151 immVertex2f(pos, v2d->cur.xmax, sy);
1152 immVertex2f(pos, v2d->cur.xmin, sy - layout->attribute_column_header_h);
1153 immVertex2f(pos, v2d->cur.xmax, sy - layout->attribute_column_header_h);
1154 immEnd();
1156 }
1157}
1158
1164 /* Generated string will be cached in the file, so non-const. */
1165 FileDirEntry *file,
1166 const bool compact,
1167 const bool update_stat_strings)
1168{
1169 switch (column) {
1170 case COLUMN_DATETIME:
1171 if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
1172 if (file->draw_data.datetime_str[0] == '\0' || update_stat_strings) {
1174 bool is_today, is_yesterday;
1175
1177 nullptr, file->time, compact, time, date, &is_today, &is_yesterday);
1178
1179 if (!compact && (is_today || is_yesterday)) {
1180 STRNCPY_UTF8(date, is_today ? IFACE_("Today") : IFACE_("Yesterday"));
1181 }
1182 SNPRINTF_UTF8(file->draw_data.datetime_str, compact ? "%s" : "%s %s", date, time);
1183 }
1184
1185 return file->draw_data.datetime_str;
1186 }
1187 break;
1188 case COLUMN_SIZE:
1191 {
1192 if (file->draw_data.size_str[0] == '\0' || update_stat_strings) {
1194 nullptr, file->size, compact, file->draw_data.size_str);
1195 }
1196
1197 return file->draw_data.size_str;
1198 }
1199 break;
1200 default:
1201 break;
1202 }
1203
1204 return nullptr;
1205}
1206
1208 const FileLayout *layout,
1209 FileDirEntry *file,
1210 const rcti *tile_draw_rect,
1211 const uchar text_col[4])
1212{
1213 const bool compact = FILE_LAYOUT_COMPACT(layout);
1214 const bool update_stat_strings = layout->width != layout->curr_size;
1215 int sx = tile_draw_rect->xmin - layout->tile_border_x;
1216
1217 for (int column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX; column_type++) {
1218 const FileAttributeColumn *column = &layout->attribute_columns[column_type];
1219
1220 /* Name column is not a detail column (should already be drawn), always skip here. */
1221 if (column_type == COLUMN_NAME) {
1222 sx += column->width;
1223 continue;
1224 }
1226 {
1227 continue;
1228 }
1229
1231 FileAttributeColumnType(column_type), file, compact, update_stat_strings);
1232
1233 if (str) {
1235 tile_draw_rect->ymax,
1236 IFACE_(str),
1237 column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
1238 layout->tile_h,
1240 text_col);
1241 }
1242
1243 sx += column->width;
1244 }
1245}
1246
1247static rcti tile_draw_rect_get(const View2D *v2d, const FileLayout *layout, const int file_idx)
1248{
1249 int tile_pos_x, tile_pos_y;
1250 ED_fileselect_layout_tilepos(layout, file_idx, &tile_pos_x, &tile_pos_y);
1251 tile_pos_x += int(v2d->tot.xmin);
1252 tile_pos_y = int(v2d->tot.ymax - tile_pos_y);
1253
1254 rcti rect;
1255 rect.xmin = tile_pos_x;
1256 rect.xmax = rect.xmin + layout->tile_w;
1257 rect.ymax = tile_pos_y;
1258 rect.ymin = rect.ymax - layout->tile_h;
1259
1260 return rect;
1261}
1262
1267 const eFileDisplayType display_type,
1268 const FileLayout *layout,
1269 const int file_idx,
1270 const int icon_ofs_x)
1271{
1272 rcti tile_rect = tile_draw_rect_get(v2d, layout, file_idx);
1273
1274 rcti rect = tile_rect;
1275 if (display_type == FILE_IMGDISPLAY) {
1276 rect.ymin += round_fl_to_int(layout->prv_border_y * 0.5f);
1277 rect.ymax = rect.ymin + layout->text_line_height * layout->text_lines_count;
1278 }
1279 else {
1280 rect.xmin += icon_ofs_x + 1;
1281 rect.xmax = tile_rect.xmin + round_fl_to_int(layout->attribute_columns[COLUMN_NAME].width) -
1282 layout->tile_border_x;
1283 }
1284
1285 return rect;
1286}
1287
1288void file_draw_list(const bContext *C, ARegion *region)
1289{
1291 wmWindow *win = CTX_wm_window(C);
1292 SpaceFile *sfile = CTX_wm_space_file(C);
1294 FileLayout *layout = ED_fileselect_get_layout(sfile, region);
1295 View2D *v2d = &region->v2d;
1296 FileList *files = sfile->files;
1297 FileDirEntry *file;
1298 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
1299 int numfiles;
1300 int numfiles_layout;
1301 int offset;
1302 int i;
1303 eFontStyle_Align align;
1304 bool do_drag;
1305 uchar text_col[4];
1306 const bool draw_columnheader = (params->display == FILE_VERTICALDISPLAY);
1307 const float thumb_icon_aspect = std::min(64.0f / float(params->thumbnail_size), 4.0f);
1308
1309 numfiles = filelist_files_ensure(files);
1310
1311 if (params->display != FILE_IMGDISPLAY) {
1312 draw_background(layout, v2d);
1313 draw_dividers(layout, v2d);
1314 }
1315
1317 layout, int(region->v2d.cur.xmin), int(-region->v2d.cur.ymax) + layout->offset_top);
1318 offset = std::max(offset, 0);
1319
1320 numfiles_layout = ED_fileselect_layout_numfiles(layout, region);
1321
1322 /* adjust, so the next row is already drawn when scrolling */
1323 if (layout->flag & FILE_LAYOUT_HOR) {
1324 numfiles_layout += layout->rows;
1325 }
1326 else {
1327 numfiles_layout += layout->flow_columns;
1328 }
1329
1330 filelist_file_cache_slidingwindow_set(files, numfiles_layout);
1331
1333
1334 if (numfiles > 0) {
1335 const bool success = filelist_file_cache_block(
1336 files, min_ii(offset + (numfiles_layout / 2), numfiles - 1));
1337 BLI_assert(success);
1338 UNUSED_VARS_NDEBUG(success);
1339
1341
1342 /* Handle preview timer here,
1343 * since it's filelist_file_cache_block() and filelist_cache_previews_update()
1344 * which controls previews task. */
1345 {
1346 const bool previews_running = filelist_cache_previews_running(files) &&
1348 // printf("%s: preview task: %d\n", __func__, previews_running);
1349 if (previews_running && !sfile->previews_timer) {
1351 wm, win, NC_SPACE | ND_SPACE_FILE_PREVIEW, 0.01);
1352 }
1353 if (!previews_running && sfile->previews_timer) {
1354 /* Preview is not running, no need to keep generating update events! */
1355 // printf("%s: Inactive preview task, sleeping!\n", __func__);
1357 sfile->previews_timer = nullptr;
1358 }
1359 }
1360 }
1361
1363
1364 UI_GetThemeColor4ubv(TH_TEXT, text_col);
1365
1366 for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
1367 eDirEntry_SelectFlag file_selflag;
1368 const int padx = 0.1f * UI_UNIT_X;
1369 int icon_ofs = 0;
1370
1371 const rcti tile_draw_rect = tile_draw_rect_get(v2d, layout, i);
1372
1373 file = filelist_file(files, i);
1374 file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL);
1375
1376 char path[FILE_MAX_LIBEXTRA];
1377 filelist_file_get_full_path(files, file, path);
1378
1379 if (!(file_selflag & FILE_SEL_EDITING)) {
1380 if ((params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ||
1381 (file_selflag & FILE_SEL_SELECTED))
1382 {
1383 int colorid = (file_selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
1384 int shade = (params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ? 35 :
1385 0;
1386 BLI_assert(i == 0 || !FILENAME_IS_CURRPAR(file->relpath));
1387
1388 draw_tile_background(&tile_draw_rect, colorid, shade);
1389 }
1390 }
1392
1393 /* don't drag parent or refresh items */
1394 do_drag = !FILENAME_IS_CURRPAR(file->relpath);
1395 const bool is_hidden = (file->attributes & FILE_ATTR_HIDDEN);
1396
1397 if (FILE_IMGDISPLAY == params->display) {
1398 const int file_type_icon = filelist_geticon_file_type(files, i, false);
1399 const ImBuf *preview_imb = filelist_get_preview_image(files, i);
1400
1401 bool has_special_file_image = false;
1402
1403 const bool is_loading = filelist_file_is_preview_pending(files, file);
1404 if (is_loading) {
1405 file_draw_loading_icon(&tile_draw_rect, thumb_icon_aspect, layout);
1406 }
1407 else if (preview_imb) {
1408 file_draw_preview(file, &tile_draw_rect, preview_imb, layout, is_hidden);
1409 }
1410 else {
1411 /* Larger folder or document icon, with file/folder type icon in the middle (if any). */
1413 file, &tile_draw_rect, file_type_icon, thumb_icon_aspect, layout, is_hidden);
1414 has_special_file_image = true;
1415 }
1416
1418 file,
1419 layout,
1420 &tile_draw_rect,
1421 thumb_icon_aspect,
1422 file_type_icon,
1423 has_special_file_image);
1424
1425 if (do_drag) {
1427 sfile, block, layout, file, path, &tile_draw_rect, preview_imb, file_type_icon);
1428 }
1429 }
1430 else {
1431 const bool filelist_loading = !filelist_is_ready(files);
1432 const BIFIconID icon = [&]() {
1433 if (file->asset) {
1434 file->asset->ensure_previewable();
1435
1436 if (filelist_loading) {
1437 return BIFIconID(ICON_PREVIEW_LOADING);
1438 }
1440 }
1441 return filelist_geticon_file_type(files, i, true);
1442 }();
1443
1444 icon_ofs += layout->prv_w + 2 * padx;
1445
1446 /* Add dummy draggable button covering the icon and the label. */
1447 if (do_drag) {
1448 const uiStyle *style = UI_style_get();
1449 const int str_width = UI_fontstyle_string_width(&style->widget, file->name);
1450 const int drag_width = std::min(
1451 str_width + icon_ofs,
1453 if (drag_width > 0) {
1454 /* Uses full row height (tile height plus 2 * tile border padding) so there's no space
1455 * between rows. */
1456 uiBut *drag_but = uiDefBut(block,
1458 0,
1459 "",
1460 tile_draw_rect.xmin,
1461 tile_draw_rect.ymin - layout->tile_border_y,
1462 drag_width,
1463 layout->tile_h + layout->tile_border_y * 2,
1464 nullptr,
1465 0,
1466 0,
1467 std::nullopt);
1469 file_but_enable_drag(drag_but, sfile, file, path, nullptr, icon, UI_SCALE_FAC);
1470 file_but_tooltip_func_set(sfile, file, drag_but);
1471 }
1472 }
1473
1474 /* Add this after the fake draggable button, so the icon button tooltip is displayed. */
1475 uiBut *icon_but = file_add_icon_but(sfile,
1476 block,
1477 path,
1478 file,
1479 &tile_draw_rect,
1480 icon,
1481 layout->prv_w,
1482 layout->prv_h,
1483 padx,
1484 is_hidden);
1485 if (do_drag) {
1486 /* For some reason the dragging is unreliable for the icon button if we don't explicitly
1487 * enable dragging, even though the dummy drag button above covers the same area. */
1488 file_but_enable_drag(icon_but, sfile, file, path, nullptr, icon, UI_SCALE_FAC);
1489 }
1490
1491 if (layout->prv_w >= round_fl_to_int(ICON_DEFAULT_WIDTH_SCALE * 2) &&
1492 (filelist_loading || icon >= BIFICONID_LAST_STATIC))
1493 {
1494 const BIFIconID type_icon = filelist_geticon_file_type(files, i, true);
1496 tile_draw_rect.xmin + padx - 2,
1497 tile_draw_rect.ymin - 2 * UI_SCALE_FAC,
1498 type_icon);
1499 }
1500 }
1501
1502 const rcti text_rect = text_draw_rect_get(
1503 v2d, eFileDisplayType(params->display), layout, i, icon_ofs);
1504
1505 if (file_selflag & FILE_SEL_EDITING) {
1506 const int but_height =
1507 (params->display == FILE_IMGDISPLAY) ?
1508 layout->text_line_height * 1.4f :
1509 /* Just a little smaller than the tile height, clamped to #UI_UNIT_Y as maximum. */
1510 std::min(short(BLI_rcti_size_y(&text_rect) - 1.0f * UI_SCALE_FAC), UI_UNIT_Y);
1511 uiBut *but = uiDefBut(block,
1513 1,
1514 "",
1515 text_rect.xmin,
1516 /* First line only, when name is displayed in multiple lines. */
1517 text_rect.ymax - but_height,
1518 BLI_rcti_size_x(&text_rect),
1519 but_height,
1520 params->renamefile,
1521 1.0f,
1522 float(sizeof(params->renamefile)),
1523 "");
1525 UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* Allow non UTF8 names. */
1527 if (false == UI_but_active_only(C, region, block, but)) {
1528 /* Note that this is the only place where we can also handle a cancelled renaming. */
1529
1530 file_params_rename_end(wm, win, sfile, file);
1531
1532 /* After the rename button is removed, we need to make sure the view is redrawn once more,
1533 * in case selection changed. Usually UI code would trigger that redraw, but the rename
1534 * operator may have been called from a different region.
1535 * Tagging regions for redrawing while drawing is rightfully prevented. However, this
1536 * active button removing basically introduces handling logic to drawing code. So a
1537 * notifier should be an acceptable workaround. */
1539
1540 file_selflag = filelist_entry_select_get(sfile->files, file, CHECK_ALL);
1541 }
1542 }
1543
1544 /* file_selflag might have been modified by branch above. */
1545 if ((file_selflag & FILE_SEL_EDITING) == 0) {
1546 if (layout->text_lines_count == 1) {
1547 file_draw_string(text_rect.xmin,
1548 text_rect.ymax,
1549 file->name,
1550 BLI_rcti_size_x(&text_rect),
1551 BLI_rcti_size_y(&text_rect),
1552 align,
1553 text_col);
1554 }
1555 else {
1556 file_draw_string_mulitline_clipped(&text_rect, file->name, align, text_col);
1557 }
1558 }
1559
1560 if (params->display != FILE_IMGDISPLAY) {
1561 draw_details_columns(params, layout, file, &tile_draw_rect, text_col);
1562 }
1563 }
1564
1565 if (numfiles < 1) {
1566 const rcti tile_draw_rect = tile_draw_rect_get(v2d, layout, 0);
1567 const uiStyle *style = UI_style_get();
1568
1569 const bool is_filtered = params->filter_search[0] != '\0';
1570
1571 uchar text_col_mod[4];
1572 copy_v4_v4_uchar(text_col_mod, text_col);
1573 if (!is_filtered) {
1574 text_col_mod[3] /= 2;
1575 }
1576
1577 const char *message = [&]() {
1578 if (!filelist_is_ready(files)) {
1579 return IFACE_("Loading...");
1580 }
1581 if (is_filtered) {
1582 return IFACE_("No results match the search filter");
1583 }
1584 return IFACE_("No items");
1585 }();
1586
1588 tile_draw_rect.xmin + UI_UNIT_X,
1589 tile_draw_rect.ymax - UI_UNIT_Y,
1590 message,
1591 text_col_mod);
1592 }
1593
1595
1596 UI_block_end(C, block);
1597 UI_block_draw(C, block);
1598
1599 /* Draw last, on top of file list. */
1600 if (draw_columnheader) {
1601 draw_columnheader_background(layout, v2d);
1602 draw_columnheader_columns(params, layout, v2d, text_col);
1603 }
1604
1605 if (numfiles != -1) {
1606 /* Only save current size if there is something to show. */
1607 layout->curr_size = layout->width;
1608 }
1609}
1610
1612 const SpaceFile *sfile,
1613 ARegion *region,
1614 FileAssetSelectParams *asset_params)
1615{
1616 char library_ui_path[FILE_MAX_LIBEXTRA];
1617 file_path_to_ui_path(asset_params->base_params.dir, library_ui_path, sizeof(library_ui_path));
1618
1619 uchar text_col[4];
1620 UI_GetThemeColor4ubv(TH_TEXT, text_col);
1621
1622 const View2D *v2d = &region->v2d;
1623 const int pad = sfile->layout->tile_border_x;
1624 const int width = BLI_rctf_size_x(&v2d->tot) - (2 * pad);
1625 const int line_height = sfile->layout->text_line_height;
1626 int sx = v2d->tot.xmin + pad;
1627 /* For some reason no padding needed. */
1628 int sy = v2d->tot.ymax;
1629
1630 {
1631 const char *message = RPT_("Path to asset library does not exist:");
1632 file_draw_string_multiline(sx, sy, message, width, line_height, text_col, nullptr, &sy);
1633
1634 sy -= line_height;
1635 file_draw_string(sx, sy, library_ui_path, width, line_height, UI_STYLE_TEXT_LEFT, text_col);
1636 }
1637
1638 /* Separate a bit further. */
1639 sy -= line_height * 2.2f;
1640
1641 {
1642 UI_icon_draw(sx, sy - UI_UNIT_Y, ICON_INFO);
1643
1644 const char *suggestion = RPT_(
1645 "Asset Libraries are local directories that can contain .blend files with assets inside.\n"
1646 "Manage Asset Libraries from the File Paths section in Preferences");
1648 sx + UI_UNIT_X, sy, suggestion, width - UI_UNIT_X, line_height, text_col, nullptr, &sy);
1649
1650 uiBlock *block = UI_block_begin(C, region, __func__, blender::ui::EmbossType::Emboss);
1651 wmOperatorType *ot = WM_operatortype_find("SCREEN_OT_userpref_show", false);
1652 uiBut *but = uiDefIconTextButO_ptr(block,
1654 ot,
1656 ICON_PREFERENCES,
1657 WM_operatortype_name(ot, nullptr),
1658 sx + UI_UNIT_X,
1659 sy - line_height - UI_UNIT_Y * 1.2f,
1660 UI_UNIT_X * 8,
1661 UI_UNIT_Y,
1662 std::nullopt);
1663 PointerRNA *but_opptr = UI_but_operator_ptr_ensure(but);
1664 RNA_enum_set(but_opptr, "section", USER_SECTION_FILE_PATHS);
1665
1666 UI_block_end(C, block);
1667 UI_block_draw(C, block);
1668 }
1669}
1670
1672 const SpaceFile *sfile,
1673 ARegion *region,
1674 const char *blendfile_path,
1675 ReportList *reports)
1676{
1677 uchar text_col[4];
1678 UI_GetThemeColor4ubv(TH_TEXT, text_col);
1679
1680 const View2D *v2d = &region->v2d;
1681 const int pad = sfile->layout->tile_border_x;
1682 const int width = BLI_rctf_size_x(&v2d->tot) - (2 * pad);
1683 const int line_height = sfile->layout->text_line_height;
1684 int sx = v2d->tot.xmin + pad;
1685 /* For some reason no padding needed. */
1686 int sy = v2d->tot.ymax;
1687
1688 {
1689 const char *message = RPT_("Unreadable Blender library file:");
1690 file_draw_string_multiline(sx, sy, message, width, line_height, text_col, nullptr, &sy);
1691
1692 sy -= line_height;
1693 file_draw_string(sx, sy, blendfile_path, width, line_height, UI_STYLE_TEXT_LEFT, text_col);
1694 }
1695
1696 /* Separate a bit further. */
1697 sy -= line_height * 2.2f;
1698
1699 LISTBASE_FOREACH (Report *, report, &reports->list) {
1700 const short report_type = report->type;
1701 if (report_type <= RPT_INFO) {
1702 continue;
1703 }
1704
1705 int icon = ICON_INFO;
1706 if (report_type > RPT_WARNING) {
1707 icon = ICON_ERROR;
1708 }
1709 UI_icon_draw(sx, sy - UI_UNIT_Y, icon);
1710
1712 sy,
1713 RPT_(report->message),
1714 width - UI_UNIT_X,
1715 line_height,
1716 text_col,
1717 nullptr,
1718 &sy);
1719 sy -= line_height;
1720 }
1721}
1722
1723bool file_draw_hint_if_invalid(const bContext *C, const SpaceFile *sfile, ARegion *region)
1724{
1725 char blendfile_path[FILE_MAX_LIBEXTRA];
1726 const bool is_asset_browser = ED_fileselect_is_asset_browser(sfile);
1727 const bool is_library_browser = !is_asset_browser &&
1728 filelist_islibrary(sfile->files, blendfile_path, nullptr);
1729
1730 if (is_asset_browser) {
1732
1733 /* Check if the asset library exists. */
1734 if (!((asset_params->asset_library_ref.type == ASSET_LIBRARY_LOCAL) ||
1735 filelist_is_dir(sfile->files, asset_params->base_params.dir)))
1736 {
1737 file_draw_invalid_asset_library_hint(C, sfile, region, asset_params);
1738 return true;
1739 }
1740 }
1741
1742 /* Check if the blendfile library is valid (has entries). */
1743 if (is_library_browser) {
1744 if (!filelist_is_ready(sfile->files)) {
1745 return false;
1746 }
1747
1748 const int numfiles = filelist_files_num_entries(sfile->files);
1749 if (numfiles > 0) {
1750 return false;
1751 }
1752
1753 /* This could all be part of the file-list loading:
1754 * - When loading fails this could be saved in the file-list, e.g. when
1755 * `BLO_blendhandle_from_file()` returns null in `filelist_readjob_list_lib()`, a
1756 * `FL_HAS_INVALID_LIBRARY` file-list flag could be set.
1757 * - Reports from it could also be stored in `FileList` rather than being ignored
1758 * (`RPT_STORE` must be set!).
1759 * - Then we could just check for `is_library_browser` and the `FL_HAS_INVALID_LIBRARY` flag
1760 * here, and draw the hint with the reports in the file-list. (We would not draw a hint for
1761 * recursive loading, even if the file-list has the "has invalid library" flag set, which
1762 * seems like the wanted behavior.)
1763 * - The call to BKE_blendfile_is_readable() would not be needed then.
1764 */
1765 if (!sfile->runtime->is_blendfile_status_set) {
1768 blendfile_path, &sfile->runtime->is_blendfile_readable_reports);
1769 sfile->runtime->is_blendfile_status_set = true;
1770 }
1771 if (!sfile->runtime->is_blendfile_readable) {
1773 C, sfile, region, blendfile_path, &sfile->runtime->is_blendfile_readable_reports);
1774 return true;
1775 }
1776 }
1777
1778 return false;
1779}
Main runtime representation of an asset.
void immDrawPixelsTexTiled_scaling(IMMDrawPixelsTexState *state, float x, float y, int img_w, int img_h, blender::gpu::TextureFormat gpu_format, bool use_filter, const void *rect, float scaleX, float scaleY, float xzoom, float yzoom, const float color[4])
Definition glutil.cc:309
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
Definition glutil.cc:37
bool BKE_blendfile_is_readable(const char *path, ReportList *reports)
Definition blendfile.cc:155
SpaceFile * CTX_wm_space_file(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
SpaceLink * CTX_wm_space_data(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_reports_clear(ReportList *reports)
Definition report.cc:109
void BLF_enable(int fontid, FontFlags flag)
Definition blf.cc:320
void BLF_batch_draw_begin()
Definition blf.cc:534
void BLF_boundbox(int fontid, const char *str, size_t str_len, rcti *r_box, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:772
void BLF_batch_draw_end()
Definition blf.cc:547
void BLF_wordwrap(int fontid, int wrap_width, BLFWrapMode mode=BLFWrapMode::Minimal)
Definition blf.cc:924
void BLF_disable(int fontid, FontFlags flag)
Definition blf.cc:329
@ BLF_WORD_WRAP
Definition BLF_enums.hh:39
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:360
#define FILE_ATTR_ANY_LINK
void BLI_filelist_entry_size_to_string(const struct stat *st, uint64_t st_size_fallback, bool compact, char r_size[FILELIST_DIRENTRY_SIZE_LEN])
int BLI_rename(const char *from, const char *to) ATTR_NONNULL()
Definition fileops_c.cc:461
void BLI_filelist_entry_datetime_to_string(const struct stat *st, int64_t ts, bool compact, char r_time[FILELIST_DIRENTRY_TIME_LEN], char r_date[FILELIST_DIRENTRY_DATE_LEN], bool *r_is_today, bool *r_is_yesterday)
@ FILE_ATTR_HIDDEN
@ FILE_ATTR_READONLY
@ FILE_ATTR_RESTRICTED
@ FILE_ATTR_SYSTEM
@ FILE_ATTR_OFFLINE
Some types for dealing with directories.
#define FILELIST_DIRENTRY_DATE_LEN
#define FILELIST_DIRENTRY_TIME_LEN
#define LISTBASE_FOREACH(type, var, list)
MINLINE int round_fl_to_int(float a)
MINLINE int min_ii(int a, int b)
MINLINE void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
MINLINE void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
MINLINE float srgb_to_grayscale(const float rgb[3])
static constexpr int image_width
static constexpr int image_height
MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4])
#define FILE_MAXFILE
#define FILE_MAX
#define BLI_path_join(...)
#define FILENAME_IS_CURRPAR(_n)
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
bool BLI_path_make_safe_filename(char *filename) ATTR_NONNULL(1)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
void BLI_rcti_pad(struct rcti *rect, int pad_x, int pad_y)
Definition rct.cc:629
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:202
#define BLI_STR_FORMAT_UINT64_GROUPED_SIZE
Definition BLI_string.h:22
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
size_t BLI_str_format_uint64_grouped(char dst[BLI_STR_FORMAT_UINT64_GROUPED_SIZE], uint64_t num) ATTR_NONNULL(1)
Definition string.cc:1183
#define SNPRINTF_UTF8(dst, format,...)
#define STRNCPY_UTF8(dst, src)
unsigned char uchar
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
#define STREQ(a, b)
Compatibility-like things for windows.
external readfile function prototypes.
short BLO_version_from_file(const char *filepath)
Definition readfile.cc:1483
#define RPT_(msgid)
#define TIP_(msgid)
#define IFACE_(msgid)
eAssetImportMethod
@ ASSET_IMPORT_PACK
@ ASSET_IMPORT_LINK
@ ASSET_LIBRARY_LOCAL
@ FILE_TYPE_BLENDER
@ FILE_TYPE_ASSET
@ FILE_TYPE_BLENDER_BACKUP
@ FILE_TYPE_MOVIE
@ FILE_TYPE_OBJECT_IO
@ FILE_TYPE_FTFONT
@ FILE_TYPE_BLENDERLIB
@ FILE_TYPE_IMAGE
@ FILE_TYPE_DIR
@ FILE_BROWSE_MODE_ASSETS
eDirEntry_SelectFlag
@ FILE_SEL_EDITING
@ FILE_SEL_HIGHLIGHTED
@ FILE_SEL_SELECTED
eFileDisplayType
@ FILE_VERTICALDISPLAY
@ FILE_IMGDISPLAY
@ FILE_SORT_INVERT
@ FILE_ASSET_IMPORT_INSTANCE_COLLECTIONS_ON_LINK
@ FILE_ASSET_IMPORT_INSTANCE_COLLECTIONS_ON_APPEND
#define FILE_MAX_LIBEXTRA
#define UI_SCALE_FAC
#define UI_ICON_SIZE
@ USER_SECTION_FILE_PATHS
int BIFIconID
Definition ED_asset.hh:28
#define FILE_LAYOUT_HOR
int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *region)
Definition filesel.cc:735
FileSelectParams * ED_fileselect_get_active_params(const SpaceFile *sfile)
Definition filesel.cc:379
int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
Definition filesel.cc:821
FileLayout * ED_fileselect_get_layout(SpaceFile *sfile, ARegion *region)
Definition filesel.cc:1141
bool ED_fileselect_is_asset_browser(const SpaceFile *sfile)
Definition filesel.cc:467
FileAssetSelectParams * ED_fileselect_get_asset_params(const SpaceFile *sfile)
Definition filesel.cc:402
FileAttributeColumnType
@ COLUMN_DATETIME
@ ATTRIBUTE_COLUMN_MAX
@ COLUMN_NAME
@ COLUMN_SIZE
void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region)
Definition filesel.cc:1030
void ED_fileselect_clear(wmWindowManager *wm, SpaceFile *sfile)
Definition filesel.cc:1291
void ED_fileselect_layout_tilepos(const FileLayout *layout, int tile, int *x, int *y)
Definition filesel.cc:873
int ED_fileselect_asset_import_method_get(const SpaceFile *sfile, const FileDirEntry *file)
Definition filesel.cc:512
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:618
void immEnd()
void immUnbindProgram()
void immBindBuiltinProgram(GPUBuiltinShader shader_id)
void immAttrSkip(uint attr_id)
void immVertex2f(uint attr_id, float x, float y)
void immUniformThemeColorShade(int color_id, int offset)
void immVertex2fv(uint attr_id, const float data[2])
GPUVertFormat * immVertexFormat()
void immUniformColor4fv(const float rgba[4])
void immUniformThemeColorBlend(int color_id1, int color_id2, float fac)
void immAttr3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2, bool clear_alpha=false)
@ GPU_PRIM_LINES
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_3D_FLAT_COLOR
@ GPU_SHADER_3D_IMAGE_COLOR
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
@ GPU_BLEND_ALPHA_PREMULT
Definition GPU_state.hh:88
void GPU_blend(GPUBlend blend)
Definition gpu_state.cc:42
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
void IMB_freeImBuf(ImBuf *ibuf)
bool IMB_metadata_get_field(const IDProperty *metadata, const char *key, char *value, size_t value_maxncpy)
Definition metadata.cc:41
ImBuf * IMB_thumb_read(const char *file_or_lib_path, ThumbSize size)
Definition thumbs.cc:504
@ THB_LARGE
Definition IMB_thumbs.hh:23
@ THB_SOURCE_IMAGE
Definition IMB_thumbs.hh:28
@ THB_SOURCE_MOVIE
Definition IMB_thumbs.hh:29
ImBuf * IMB_thumb_manage(const char *file_or_lib_path, ThumbSize size, ThumbSource source)
Definition thumbs.cc:538
ImBuf * IMB_font_preview(const char *filepath, unsigned int width, const float color[4], const char *sample_text=nullptr)
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
void UI_but_flag_disable(uiBut *but, int flag)
#define UI_UNIT_Y
void UI_but_drag_attach_image(uiBut *but, const ImBuf *imb, float scale)
uiBut * uiDefButR(uiBlock *block, ButType type, int retval, std::optional< blender::StringRef > str, int x, int y, short width, short height, PointerRNA *ptr, blender::StringRefNull propname, int index, float min, float max, std::optional< blender::StringRef > tip)
void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const char *str, const uchar col[4])
void UI_but_func_tooltip_custom_set(uiBut *but, uiButToolTipCustomFunc func, void *arg, uiFreeArgFunc free_arg)
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, blender::ui::EmbossType emboss)
void UI_draw_icon_tri(float x, float y, char dir, const float[4])
void UI_tooltip_image_field_add(uiTooltipData &data, const uiTooltipImage &image_data)
void UI_but_color_set(uiBut *but, const uchar color[4])
@ UI_BUT_UNDO
@ UI_BUT_DISABLED
@ UI_BUT_NO_UTF8
uiBut * uiDefIconBut(uiBlock *block, uiButTypeWithPointerType but_and_ptr_type, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_tooltip_text_field_add(uiTooltipData &data, std::string text, std::string suffix, const uiTooltipStyle style, const uiTooltipColorID color_id, const bool is_pad=false)
bool UI_but_is_utf8(const uiBut *but)
void UI_but_drag_set_image(uiBut *but, const char *path, int icon, const ImBuf *imb, float scale)
void UI_draw_roundbox_corner_set(int type)
@ UI_BUT_DRAG_FULL_BUT
void UI_fontstyle_draw_ex(const uiFontStyle *fs, const rcti *rect, const char *str, size_t str_len, const uchar col[4], const uiFontStyleDraw_Params *fs_params, int *r_xofs, int *r_yofs, ResultBLF *r_info)
eFontStyle_Align
@ UI_STYLE_TEXT_LEFT
@ UI_STYLE_TEXT_CENTER
const uiStyle * UI_style_get()
void UI_but_dragflag_enable(uiBut *but, int flag)
void UI_but_drag_set_path(uiBut *but, const char *path)
PointerRNA * UI_but_operator_ptr_ensure(uiBut *but)
@ UI_TIP_STYLE_NORMAL
@ UI_TIP_STYLE_SPACER
@ UI_TIP_STYLE_HEADER
void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2)
float UI_text_clip_middle_ex(const uiFontStyle *fstyle, char *str, float okwidth, float minwidth, size_t max_len, char rpart_sep, bool clip_right_if_tight=true)
void UI_but_func_rename_set(uiBut *but, uiButHandleRenameFunc func, void *arg1)
void UI_but_drawflag_disable(uiBut *but, int flag)
void UI_block_draw(const bContext *C, uiBlock *block)
@ UI_CNR_ALL
@ UI_CNR_NONE
void UI_but_drag_set_asset(uiBut *but, const blender::asset_system::AssetRepresentation *asset, const AssetImportSettings &import_settings, int icon, int preview_icon)
int UI_fontstyle_string_width(const uiFontStyle *fs, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
void UI_fontstyle_draw_multiline_clipped(const uiFontStyle *fs, const rcti *rect, const char *str, const uchar col[4], eFontStyle_Align align)
bool UI_but_active_only(const bContext *C, ARegion *region, uiBlock *block, uiBut *but)
uiBut * uiDefIconTextButO_ptr(uiBlock *block, ButType type, wmOperatorType *ot, blender::wm::OpCallContext opcontext, int icon, blender::StringRef str, int x, int y, short width, short height, std::optional< blender::StringRef > tip)
void UI_fontstyle_draw(const uiFontStyle *fs, const rcti *rect, const char *str, size_t str_len, const uchar col[4], const uiFontStyleDraw_Params *fs_params)
void UI_but_label_alpha_factor_set(uiBut *but, float alpha_factor)
@ UI_TIP_LC_ALERT
@ UI_TIP_LC_MAIN
@ UI_TIP_LC_NORMAL
void UI_but_func_complete_set(uiBut *but, uiButCompleteFunc func, void *arg)
#define UI_UNIT_X
void UI_but_drag_set_id(uiBut *but, ID *id)
@ UI_BUT_ICON_LEFT
void UI_draw_roundbox_aa(const rctf *rect, bool filled, float rad, const float color[4])
void UI_but_funcN_set(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2, uiButArgNFree func_argN_free_fn=MEM_freeN, uiButArgNCopy func_argN_copy_fn=MEM_dupallocN)
void UI_block_end(const bContext *C, uiBlock *block)
uiBut * uiDefBut(uiBlock *block, uiButTypeWithPointerType but_and_ptr_type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
uiBut * uiDefIconPreviewBut(uiBlock *block, ButType type, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_but_flag_enable(uiBut *but, int flag)
bool UI_but_flag_is_set(uiBut *but, int flag)
#define ICON_DEFAULT_HEIGHT
void UI_icon_draw(float x, float y, int icon_id)
#define ICON_DEFAULT_WIDTH_SCALE
#define UI_NO_ICON_OVERLAY_TEXT
#define PREVIEW_DRAG_DRAW_SIZE
#define ICON_DEFAULT_HEIGHT_SCALE
void UI_icon_draw_ex(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const uchar mono_color[4], bool mono_border, const IconTextOverlay *text_overlay, const bool inverted=false)
#define ICON_DEFAULT_WIDTH
@ TH_ROW_ALTERNATE
@ TH_ICON_FOLDER
@ TH_BACK
@ TH_HILITE
@ TH_TEXT
void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3])
void UI_GetThemeColor4fv(int colorid, float col[4])
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
@ BIFICONID_LAST_STATIC
bTheme * UI_GetTheme()
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
Definition view2d.cc:1036
#define ND_SPACE_FILE_PREVIEW
Definition WM_types.hh:540
#define ND_SPACE_FILE_PARAMS
Definition WM_types.hh:523
#define NC_SPACE
Definition WM_types.hh:392
int pad[32 - sizeof(int)]
#define U
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
nullptr float
#define str(s)
static void file_draw_indicator_icons(const FileList *files, const FileDirEntry *file, const FileLayout *layout, const rcti *tile_draw_rect, const float preview_icon_aspect, const int file_type_icon, const bool has_special_file_image)
Definition file_draw.cc:863
static void draw_dividers(FileLayout *layout, View2D *v2d)
static void draw_details_columns(const FileSelectParams *params, const FileLayout *layout, FileDirEntry *file, const rcti *tile_draw_rect, const uchar text_col[4])
static void file_but_tooltip_func_set(const SpaceFile *sfile, const FileDirEntry *file, uiBut *but)
Definition file_draw.cc:429
void file_calc_previews(const bContext *C, ARegion *region)
Definition file_draw.cc:605
static void file_draw_invalid_asset_library_hint(const bContext *C, const SpaceFile *sfile, ARegion *region, FileAssetSelectParams *asset_params)
static void draw_tile_background(const rcti *draw_rect, int colorid, int shade)
Definition file_draw.cc:376
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 file_type_icon)
Definition file_draw.cc:646
static void draw_columnheader_columns(const FileSelectParams *params, FileLayout *layout, const View2D *v2d, const uchar text_col[4])
static FileTooltipData * file_tooltip_data_create(const SpaceFile *sfile, const FileDirEntry *file)
Definition file_draw.cc:129
static void file_draw_string_multiline(int sx, int sy, const char *string, int wrap_width, int line_height, const uchar text_col[4], int *r_sx, int *r_sy)
Definition file_draw.cc:556
bool file_draw_hint_if_invalid(const bContext *C, const SpaceFile *sfile, ARegion *region)
static void file_draw_special_image(const FileDirEntry *file, const rcti *tile_draw_rect, const int file_type_icon, const float icon_aspect, const FileLayout *layout, const bool dimmed)
Definition file_draw.cc:766
static void file_draw_tooltip_custom_func(bContext &, uiTooltipData &tip, uiBut *, void *argN)
Definition file_draw.cc:137
static uiBut * file_add_icon_but(const SpaceFile *sfile, uiBlock *block, const char *, const FileDirEntry *file, const rcti *tile_draw_rect, int icon, int width, int height, int padx, bool dimmed)
Definition file_draw.cc:440
static void file_draw_asset_tooltip_custom_func(bContext &, uiTooltipData &tip, uiBut *, void *argN)
Definition file_draw.cc:367
static void file_draw_string_mulitline_clipped(const rcti *rect, const char *string, eFontStyle_Align align, const uchar col[4])
Definition file_draw.cc:536
static uiBut * file_add_overlay_icon_but(uiBlock *block, int pos_x, int pos_y, int icon)
Definition file_draw.cc:475
static void file_draw_preview(const FileDirEntry *file, const rcti *tile_draw_rect, const ImBuf *imb, FileLayout *layout, const bool dimmed)
Definition file_draw.cc:683
static void draw_columnheader_background(const FileLayout *layout, const View2D *v2d)
static void renamebutton_cb(bContext *C, void *, char *oldname)
Definition file_draw.cc:947
static rcti tile_draw_rect_get(const View2D *v2d, const FileLayout *layout, const int file_idx)
void ED_file_path_button(bScreen *screen, const SpaceFile *sfile, FileSelectParams *params, uiBlock *block)
Definition file_draw.cc:77
static rcti text_draw_rect_get(const View2D *v2d, const eFileDisplayType display_type, const FileLayout *layout, const int file_idx, const int icon_ofs_x)
static void draw_background(FileLayout *layout, View2D *v2d)
Definition file_draw.cc:991
static const char * filelist_get_details_column_string(FileAttributeColumnType column, FileDirEntry *file, const bool compact, const bool update_stat_strings)
static std::tuple< int, int, float > preview_image_scaled_dimensions_get(const int image_width, const int image_height, const FileLayout &layout)
Definition file_draw.cc:614
static void file_draw_string(int sx, int sy, const char *string, float width, int height, eFontStyle_Align align, const uchar col[4])
Definition file_draw.cc:498
void file_draw_list(const bContext *C, ARegion *region)
static void file_draw_invalid_library_hint(const bContext *, const SpaceFile *sfile, ARegion *region, const char *blendfile_path, ReportList *reports)
static void file_draw_loading_icon(const rcti *tile_draw_rect, const float preview_icon_aspect, const FileLayout *layout)
Definition file_draw.cc:840
static void file_but_enable_drag(uiBut *but, const SpaceFile *sfile, const FileDirEntry *file, const char *path, const ImBuf *preview_image, int icon, float scale)
Definition file_draw.cc:387
void file_path_to_ui_path(const char *path, char *r_path, int r_path_maxncpy)
Definition file_utils.cc:34
bool file_attribute_column_type_enabled(const FileSelectParams *params, FileAttributeColumnType column, const FileLayout *layout)
Definition filesel.cc:899
void file_params_rename_end(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile, const FileDirEntry *rename_file)
Definition filesel.cc:1360
void file_params_invoke_rename_postscroll(wmWindowManager *wm, wmWindow *win, SpaceFile *sfile)
Definition filesel.cc:1347
int autocomplete_directory(bContext *C, char *str, void *arg_v)
Definition filesel.cc:1222
#define FILE_LAYOUT_COMPACT(_layout)
void file_directory_enter_handle(bContext *C, void *arg_unused, void *arg_but)
Definition file_ops.cc:2921
#define ATTRIBUTE_COLUMN_PADDING
void file_draw_check_cb(bContext *C, void *arg1, void *arg2)
Definition file_ops.cc:1778
int filelist_geticon_file_type(FileList *filelist, int index, bool is_main)
Definition filelist.cc:390
bool filelist_file_cache_block(FileList *filelist, int index)
Definition filelist.cc:1440
int filelist_files_num_entries(FileList *filelist)
Definition filelist.cc:1045
void filelist_file_get_full_path(const FileList *filelist, const FileDirEntry *file, char r_filepath[1282])
bool filelist_islibrary(FileList *filelist, char *dir, char **r_group)
Definition filelist.cc:2043
BlendHandle * filelist_lib(FileList *filelist)
Definition filelist.cc:1040
ImBuf * filelist_get_preview_image(FileList *filelist, int index)
Definition filelist.cc:230
bool filelist_file_is_preview_pending(const FileList *filelist, const FileDirEntry *file)
Definition filelist.cc:215
bool filelist_cache_previews_running(FileList *filelist)
Definition filelist.cc:1739
bool filelist_cache_previews_done(FileList *filelist)
Definition filelist.cc:1746
ImBuf * filelist_geticon_special_file_image_ex(const FileDirEntry *file)
Definition filelist.cc:251
ID * filelist_file_get_id(const FileDirEntry *file)
Definition filelist.cc:1345
bool filelist_cache_previews_update(FileList *filelist)
Definition filelist.cc:1681
void filelist_file_cache_slidingwindow_set(FileList *filelist, size_t window_size)
Definition filelist.cc:1378
@ CHECK_ALL
Definition filelist.hh:44
ImBuf * filelist_file_get_preview_image(const FileDirEntry *file)
Definition filelist.cc:237
bool filelist_is_dir(const FileList *filelist, const char *path)
Definition filelist.cc:1100
int filelist_files_ensure(FileList *filelist)
Definition filelist.cc:1168
FileDirEntry * filelist_file(FileList *filelist, int index)
Definition filelist.cc:1285
bool filelist_is_ready(const FileList *filelist)
Definition filelist.cc:1153
eDirEntry_SelectFlag filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileCheckType check)
Definition filelist.cc:1989
uint pos
uint col
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong state[N]
void asset_tooltip(const asset_system::AssetRepresentation &asset, uiTooltipData &tip, const bool include_name)
BIFIconID asset_preview_or_icon(const asset_system::AssetRepresentation &asset)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
eAssetImportMethod method
AssetLibraryReference asset_library_ref
FileSelectParams base_params
char datetime_str[16+8]
struct FileDirEntry::@257003076343006177237046347027064317037127117226 draw_data
AssetRepresentationHandle * asset
char * redirection_path
const char * name
FileAttributeColumn attribute_columns[ATTRIBUTE_COLUMN_MAX]
int attribute_column_header_h
const FileDirEntry * file
Definition file_draw.cc:126
const SpaceFile * sfile
Definition file_draw.cc:125
Definition DNA_ID.h:414
ImBufByteBuffer byte_buffer
IDProperty * metadata
ListBase list
Definition BKE_report.hh:75
ReportList is_blendfile_readable_reports
struct FileLayout * layout
struct FileList * files
struct wmTimer * previews_timer
FileAssetSelectParams * asset_params
SpaceFile_Runtime * runtime
uiWidgetColors wcol_tooltip
ThemeUI tui
float xmax
float xmin
float ymax
float ymin
int ymin
int ymax
int xmin
int xmax
uiFontStyle widget
uiTooltipImageBackground background
unsigned char text[4]
i
Definition text_draw.cc:230
uint len
#define N_(msgid)
void WM_event_add_notifier_ex(wmWindowManager *wm, const wmWindow *win, uint type, void *reference)
void WM_global_reportf(eReportType type, const char *format,...)
void WM_report_banner_show(wmWindowManager *wm, wmWindow *win)
wmOperatorType * ot
Definition wm_files.cc:4237
std::string WM_operatortype_name(wmOperatorType *ot, PointerRNA *properties)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
wmTimer * WM_event_timer_add_notifier(wmWindowManager *wm, wmWindow *win, const uint type, const double time_step)
void WM_event_timer_remove_notifier(wmWindowManager *wm, wmWindow *win, wmTimer *timer)