Blender V4.3
ed_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
9#include <cmath>
10#include <cstdlib>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_listbase.h"
16#include "BLI_rect.h"
17#include "BLI_string.h"
18#include "BLI_utildefines.h"
19
20#include "BLT_translation.hh"
21
22#include "BKE_context.hh"
23#include "BKE_image.hh"
24
25#include "BLF_api.hh"
26
27#include "IMB_imbuf_types.hh"
28#include "IMB_metadata.hh"
29
30#include "ED_screen.hh"
31#include "ED_space_api.hh"
32#include "ED_util.hh"
33
34#include "GPU_immediate.hh"
35#include "GPU_matrix.hh"
36#include "GPU_state.hh"
37
38#include "UI_interface.hh"
39#include "UI_resources.hh"
40
41#include "WM_api.hh"
42#include "WM_types.hh"
43
44/* -------------------------------------------------------------------- */
55#define SLIDE_PIXEL_DISTANCE (300.0f * UI_SCALE_FAC)
56#define OVERSHOOT_RANGE_DELTA 0.2f
57#define SLIDER_UNIT_STRING_SIZE 64
58
59struct tSlider {
62
65
68
71
73 float factor;
74
76 float last_cursor[2];
77
79 float factor_bounds[2];
80
81 /* How the factor number is drawn. When drawing percent it is factor*100. */
83
84 /* Optional string that will display next to the slider to indicate which property is modified
85 * right now. */
86 std::string property_label;
87
88 /* What unit to add to the slider. */
90
96
100
104
107
110};
111
112static void draw_overshoot_triangle(const uint8_t color[4],
113 const bool facing_right,
114 const float x,
115 const float y)
116{
117 const uint shdr_pos_2d = GPU_vertformat_attr_add(
121 GPU_polygon_smooth(true);
122 immUniformColor3ubvAlpha(color, 225);
123 const float triangle_side_length = facing_right ? 6 * U.pixelsize : -6 * U.pixelsize;
124 const float triangle_offset = facing_right ? 2 * U.pixelsize : -2 * U.pixelsize;
125
127 immVertex2f(shdr_pos_2d, x + triangle_offset + triangle_side_length, y);
128 immVertex2f(shdr_pos_2d, x + triangle_offset, y + triangle_side_length / 2);
129 immVertex2f(shdr_pos_2d, x + triangle_offset, y - triangle_side_length / 2);
130 immEnd();
131
132 GPU_polygon_smooth(false);
135}
136
137static void draw_ticks(const float start_factor,
138 const float end_factor,
139 const float line_start[2],
140 const float base_tick_height,
141 const float line_width,
142 const uint8_t color_overshoot[4],
143 const uint8_t color_line[4])
144{
145 /* Use factor represented as 0-100 int to avoid floating point precision problems. */
146 const int tick_increment = 10;
147
148 /* Round initial_tick_factor up to the next tick_increment. */
149 int tick_percentage = ceil((start_factor * 100) / tick_increment) * tick_increment;
150
151 while (tick_percentage <= int(end_factor * 100)) {
152 float tick_height;
153 /* Different ticks have different heights. Multiples of 100% are the tallest, 50% is a bit
154 * smaller and the rest is the minimum size. */
155 if (tick_percentage % 100 == 0) {
156 tick_height = base_tick_height;
157 }
158 else if (tick_percentage % 50 == 0) {
159 tick_height = base_tick_height * 0.8;
160 }
161 else {
162 tick_height = base_tick_height * 0.5;
163 }
164
165 const float x = line_start[0] +
166 ((float(tick_percentage) / 100) - start_factor) * SLIDE_PIXEL_DISTANCE;
167 rctf tick_rect{};
168 tick_rect.xmin = x - (line_width / 2);
169 tick_rect.xmax = x + (line_width / 2);
170 tick_rect.ymin = line_start[1] - (tick_height / 2);
171 tick_rect.ymax = line_start[1] + (tick_height / 2);
172
173 if (tick_percentage < 0 || tick_percentage > 100) {
174 UI_draw_roundbox_3ub_alpha(&tick_rect, true, 1, color_overshoot, 255);
175 }
176 else {
177 UI_draw_roundbox_3ub_alpha(&tick_rect, true, 1, color_line, 255);
178 }
179 tick_percentage += tick_increment;
180 }
181}
182
183static void draw_main_line(const rctf *main_line_rect,
184 const float factor,
185 const bool overshoot,
186 const uint8_t color_overshoot[4],
187 const uint8_t color_line[4])
188{
189 if (overshoot) {
190 /* In overshoot mode, draw the 0-100% range differently to provide a visual reference. */
191 const float line_zero_percent = main_line_rect->xmin -
192 ((factor - 0.5f - OVERSHOOT_RANGE_DELTA) *
194
195 const float clamped_line_zero_percent = clamp_f(
196 line_zero_percent, main_line_rect->xmin, main_line_rect->xmax);
197 const float clamped_line_hundred_percent = clamp_f(
198 line_zero_percent + SLIDE_PIXEL_DISTANCE, main_line_rect->xmin, main_line_rect->xmax);
199
200 rctf left_overshoot_line_rect{};
201 left_overshoot_line_rect.xmin = main_line_rect->xmin;
202 left_overshoot_line_rect.xmax = clamped_line_zero_percent;
203 left_overshoot_line_rect.ymin = main_line_rect->ymin;
204 left_overshoot_line_rect.ymax = main_line_rect->ymax;
205
206 rctf right_overshoot_line_rect{};
207 right_overshoot_line_rect.xmin = clamped_line_hundred_percent;
208 right_overshoot_line_rect.xmax = main_line_rect->xmax;
209 right_overshoot_line_rect.ymin = main_line_rect->ymin;
210 right_overshoot_line_rect.ymax = main_line_rect->ymax;
211
212 UI_draw_roundbox_3ub_alpha(&left_overshoot_line_rect, true, 0, color_overshoot, 255);
213 UI_draw_roundbox_3ub_alpha(&right_overshoot_line_rect, true, 0, color_overshoot, 255);
214
215 rctf non_overshoot_line_rect{};
216 non_overshoot_line_rect.xmin = clamped_line_zero_percent;
217 non_overshoot_line_rect.xmax = clamped_line_hundred_percent;
218 non_overshoot_line_rect.ymin = main_line_rect->ymin;
219 non_overshoot_line_rect.ymax = main_line_rect->ymax;
220 UI_draw_roundbox_3ub_alpha(&non_overshoot_line_rect, true, 0, color_line, 255);
221 }
222 else {
223 UI_draw_roundbox_3ub_alpha(main_line_rect, true, 0, color_line, 255);
224 }
225}
226
227static void draw_backdrop(const int fontid,
228 const rctf *main_line_rect,
229 const uint8_t color_bg[4],
230 const short region_y_size,
231 const float base_tick_height,
232 const std::string &property_label)
233{
234 float percent_string_pixel_size[2];
235 const char *percentage_string_placeholder = "000%%";
237 percentage_string_placeholder,
238 sizeof(percentage_string_placeholder),
239 &percent_string_pixel_size[0],
240 &percent_string_pixel_size[1]);
241
242 float property_name_pixel_size[2];
244 property_label.c_str(),
245 property_label.size(),
246 &property_name_pixel_size[0],
247 &property_name_pixel_size[1]);
248 const float pad[2] = {(region_y_size - base_tick_height) / 2 + 12.0f * U.pixelsize,
249 2.0f * U.pixelsize};
250 rctf backdrop_rect{};
251 backdrop_rect.xmin = main_line_rect->xmin - property_name_pixel_size[0] - pad[0];
252 backdrop_rect.xmax = main_line_rect->xmax + percent_string_pixel_size[0] + pad[0];
253 backdrop_rect.ymin = pad[1];
254 backdrop_rect.ymax = region_y_size - pad[1];
255 UI_draw_roundbox_3ub_alpha(&backdrop_rect, true, 4.0f, color_bg, color_bg[3]);
256}
257
261static void slider_draw(const bContext * /*C*/, ARegion *region, void *arg)
262{
263 tSlider *slider = static_cast<tSlider *>(arg);
264
265 /* Only draw in region from which the Operator was started. */
266 if (region != slider->region_header) {
267 return;
268 }
269
270 uint8_t color_text[4];
271 uint8_t color_line[4];
272 uint8_t color_handle[4];
273 uint8_t color_overshoot[4];
274 uint8_t color_bg[4];
275
276 /* Get theme colors. */
280 UI_GetThemeColor4ubv(TH_HEADER_TEXT, color_overshoot);
282
283 color_overshoot[0] = color_overshoot[0] * 0.8;
284 color_overshoot[1] = color_overshoot[1] * 0.8;
285 color_overshoot[2] = color_overshoot[2] * 0.8;
286 color_bg[3] = 160;
287
288 /* Get the default font. */
289 const uiStyle *style = UI_style_get();
290 const uiFontStyle *fstyle = &style->widget;
291 const int fontid = fstyle->uifont_id;
292 BLF_color3ubv(fontid, color_text);
293 BLF_rotation(fontid, 0.0f);
294
295 const float line_width = 1.5 * U.pixelsize;
296 const float base_tick_height = 12.0 * U.pixelsize;
297 const float line_y = region->winy / 2;
298
299 rctf main_line_rect{};
300 main_line_rect.xmin = (region->winx / 2) - (SLIDE_PIXEL_DISTANCE / 2);
301 main_line_rect.xmax = (region->winx / 2) + (SLIDE_PIXEL_DISTANCE / 2);
302 main_line_rect.ymin = line_y - line_width / 2;
303 main_line_rect.ymax = line_y + line_width / 2;
304
305 float line_start_factor = 0;
306 int handle_pos_x;
307 if (slider->overshoot) {
308 main_line_rect.xmin = main_line_rect.xmin - SLIDE_PIXEL_DISTANCE * OVERSHOOT_RANGE_DELTA;
309 main_line_rect.xmax = main_line_rect.xmax + SLIDE_PIXEL_DISTANCE * OVERSHOOT_RANGE_DELTA;
310 line_start_factor = slider->factor - 0.5f - OVERSHOOT_RANGE_DELTA;
311 handle_pos_x = region->winx / 2;
312 }
313 else {
314 const float total_range = slider->factor_bounds[1] - slider->factor_bounds[0];
315 /* 0-1 value of the representing the position of the slider in the allowed range. */
316 const float range_factor = (slider->factor - slider->factor_bounds[0]) / total_range;
317 handle_pos_x = main_line_rect.xmin + SLIDE_PIXEL_DISTANCE * range_factor;
318 }
319
320 draw_backdrop(fontid,
321 &main_line_rect,
322 color_bg,
323 slider->region_header->winy,
324 base_tick_height,
325 slider->property_label);
326
327 draw_main_line(&main_line_rect, slider->factor, slider->overshoot, color_overshoot, color_line);
328
329 const float factor_range = slider->overshoot ? 1 + OVERSHOOT_RANGE_DELTA * 2 : 1;
330 const float line_start_position[2] = {main_line_rect.xmin, line_y};
331 draw_ticks(line_start_factor,
332 line_start_factor + factor_range,
333 line_start_position,
334 base_tick_height,
335 line_width,
336 color_overshoot,
337 color_line);
338
339 /* Draw triangles at the ends of the line in overshoot mode to indicate direction of 0-100%
340 * range. */
341 if (slider->overshoot) {
342 if (slider->factor > 1 + OVERSHOOT_RANGE_DELTA + 0.5) {
343 draw_overshoot_triangle(color_line, false, main_line_rect.xmin, line_y);
344 }
345 if (slider->factor < 0 - OVERSHOOT_RANGE_DELTA - 0.5) {
346 draw_overshoot_triangle(color_line, true, main_line_rect.xmax, line_y);
347 }
348 }
349
350 /* Draw handle indicating current factor. */
351 rctf handle_rect{};
352 handle_rect.xmin = handle_pos_x - (line_width);
353 handle_rect.xmax = handle_pos_x + (line_width);
354 handle_rect.ymin = line_y - (base_tick_height / 2);
355 handle_rect.ymax = line_y + (base_tick_height / 2);
356
357 UI_draw_roundbox_3ub_alpha(&handle_rect, true, 1, color_handle, 255);
358
359 char factor_string[256];
360 switch (slider->slider_mode) {
362 SNPRINTF(factor_string, "%.0f %s", slider->factor * 100, slider->unit_string);
363 break;
365 SNPRINTF(factor_string, "%.1f %s", slider->factor, slider->unit_string);
366 break;
367 }
368
369 /* Draw factor string. */
370 float factor_string_pixel_size[2];
372 factor_string,
373 sizeof(factor_string),
374 &factor_string_pixel_size[0],
375 &factor_string_pixel_size[1]);
376
377 const float text_padding = 12.0 * U.pixelsize;
378 const float factor_string_pos_x = main_line_rect.xmax + text_padding;
380 fontid, factor_string_pos_x, (region->winy / 2) - factor_string_pixel_size[1] / 2, 0.0f);
381 BLF_draw(fontid, factor_string, sizeof(factor_string));
382
383 if (!slider->property_label.empty()) {
384 float property_name_pixel_size[2];
386 slider->property_label.c_str(),
387 slider->property_label.length(),
388 &property_name_pixel_size[0],
389 &property_name_pixel_size[1]);
390 BLF_position(fontid,
391 main_line_rect.xmin - text_padding - property_name_pixel_size[0],
392 (region->winy / 2) - property_name_pixel_size[1] / 2,
393 0.0f);
394 BLF_draw(fontid, slider->property_label.c_str(), slider->property_label.length());
395 }
396}
397
398static void slider_update_factor(tSlider *slider, const wmEvent *event)
399{
400 /* Normalize so no matter the factor bounds, the mouse distance traveled from min to max is
401 * constant. */
402 const float slider_range = slider->factor_bounds[1] - slider->factor_bounds[0];
403 const float factor_delta = (event->xy[0] - slider->last_cursor[0]) /
404 (SLIDE_PIXEL_DISTANCE / slider_range);
405 /* Reduced factor delta in precision mode (shift held). */
406 slider->raw_factor += slider->precision ? (factor_delta / 8) : factor_delta;
407 slider->factor = slider->raw_factor;
408 copy_v2fl_v2i(slider->last_cursor, event->xy);
409
410 if (slider->increments) {
411 slider->factor = round(slider->factor * 10) / 10;
412 }
413
414 if (!slider->overshoot) {
415 slider->factor = clamp_f(slider->factor, slider->factor_bounds[0], slider->factor_bounds[1]);
416 }
417 else {
418 if (!slider->allow_overshoot_lower) {
419 slider->factor = max_ff(slider->factor, slider->factor_bounds[0]);
420 }
421 if (!slider->allow_overshoot_upper) {
422 slider->factor = min_ff(slider->factor, slider->factor_bounds[1]);
423 }
424 }
425}
426
428{
429 tSlider *slider = MEM_new<tSlider>(__func__);
430 slider->scene = CTX_data_scene(C);
431 slider->area = CTX_wm_area(C);
432 slider->region_header = CTX_wm_region(C);
433
434 /* Default is true, caller needs to manually set to false. */
435 slider->allow_overshoot_lower = true;
436 slider->allow_overshoot_upper = true;
437 slider->allow_increments = true;
438
439 slider->factor_bounds[0] = 0;
440 slider->factor_bounds[1] = 1;
441
442 slider->unit_string[0] = '%';
443
445
446 /* Set initial factor. */
447 slider->raw_factor = 0.5f;
448 slider->factor = 0.5;
449
450 /* Add draw callback. Always in header. */
451 if (slider->area) {
452 LISTBASE_FOREACH (ARegion *, region, &slider->area->regionbase) {
453 if (region->regiontype == RGN_TYPE_HEADER) {
454 slider->region_header = region;
456 region->type, slider_draw, slider, REGION_DRAW_POST_PIXEL);
457 }
458 }
459 }
460
461 /* Hide the area menu bar contents, as the slider will be drawn on top. */
462 ED_area_status_text(slider->area, "");
463
464 return slider;
465}
466
467void ED_slider_init(tSlider *slider, const wmEvent *event)
468{
469 copy_v2fl_v2i(slider->last_cursor, event->xy);
470}
471
472bool ED_slider_modal(tSlider *slider, const wmEvent *event)
473{
474 bool event_handled = true;
475 /* Handle key presses. */
476 switch (event->type) {
477 case EVT_EKEY:
478 if (slider->allow_overshoot_lower || slider->allow_overshoot_upper) {
479 slider->overshoot = event->val == KM_PRESS ? !slider->overshoot : slider->overshoot;
480 slider_update_factor(slider, event);
481 }
482 break;
483 case EVT_LEFTSHIFTKEY:
485 slider->precision = event->val == KM_PRESS;
486 break;
487 case EVT_LEFTCTRLKEY:
488 case EVT_RIGHTCTRLKEY:
489 slider->increments = slider->allow_increments && event->val == KM_PRESS;
490 break;
491 case MOUSEMOVE:;
492 /* Update factor. */
493 slider_update_factor(slider, event);
494 break;
495 default:
496 event_handled = false;
497 break;
498 }
499
501
502 return event_handled;
503}
504
506 char *status_string,
507 const size_t size_of_status_string)
508{
509 /* 50 characters is enough to fit the individual setting strings. Extend if message is longer. */
510 char overshoot_str[50];
511 char precision_str[50];
512 char increments_str[50];
513
514 if (slider->allow_overshoot_lower || slider->allow_overshoot_upper) {
515 if (slider->overshoot) {
516 STRNCPY(overshoot_str, IFACE_("[E] - Disable overshoot"));
517 }
518 else {
519 STRNCPY(overshoot_str, IFACE_("[E] - Enable overshoot"));
520 }
521 }
522 else {
523 STRNCPY(overshoot_str, IFACE_("Overshoot disabled"));
524 }
525
526 if (slider->precision) {
527 STRNCPY(precision_str, IFACE_("[Shift] - Precision active"));
528 }
529 else {
530 STRNCPY(precision_str, IFACE_("Shift - Hold for precision"));
531 }
532
533 if (slider->allow_increments) {
534 if (slider->increments) {
535 STRNCPY(increments_str, IFACE_(" | [Ctrl] - Increments active"));
536 }
537 else {
538 STRNCPY(increments_str, IFACE_(" | Ctrl - Hold for 10% increments"));
539 }
540 }
541 else {
542 increments_str[0] = '\0';
543 }
544
545 BLI_snprintf(status_string,
546 size_of_status_string,
547 "%s | %s%s",
548 overshoot_str,
549 precision_str,
550 increments_str);
551}
552
554{
555 /* Remove draw callback. */
556 if (slider->draw_handle) {
558 }
559 ED_area_status_text(slider->area, nullptr);
560 ED_workspace_status_text(C, nullptr);
561 MEM_delete(slider);
562}
563
564/* Setters & Getters */
565
566float ED_slider_factor_get(const tSlider *slider)
567{
568 return slider->factor;
569}
570
571void ED_slider_factor_set(tSlider *slider, const float factor)
572{
573 slider->raw_factor = factor;
574 slider->factor = factor;
575 if (!slider->overshoot) {
576 slider->factor = clamp_f(slider->factor, slider->factor_bounds[0], slider->factor_bounds[1]);
577 }
578}
579
580void ED_slider_allow_overshoot_set(tSlider *slider, const bool lower, const bool upper)
581{
582 slider->allow_overshoot_lower = lower;
583 slider->allow_overshoot_upper = upper;
584}
585
587{
588 return slider->allow_increments;
589}
590
591void ED_slider_allow_increments_set(tSlider *slider, const bool value)
592{
593 slider->allow_increments = value;
594}
595
597 float factor_bound_lower,
598 float factor_bound_upper)
599{
600 slider->factor_bounds[0] = factor_bound_lower;
601 slider->factor_bounds[1] = factor_bound_upper;
602}
603
605{
606 slider->slider_mode = mode;
607}
608
610{
611 return slider->slider_mode;
612}
613
614void ED_slider_unit_set(tSlider *slider, const char *unit)
615{
616 STRNCPY(slider->unit_string, unit);
617}
618
619void ED_slider_property_label_set(tSlider *slider, const char *property_label)
620{
621 slider->property_label.assign(property_label);
622}
623
626void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_info)
627{
628 wmWindow *win = CTX_wm_window(C);
629 const float *mval_src = (float *)arg_info;
630 const float mval_dst[2] = {
631 float(win->eventstate->xy[0] - region->winrct.xmin),
632 float(win->eventstate->xy[1] - region->winrct.ymin),
633 };
634
635 const uint shdr_pos = GPU_vertformat_attr_add(
637
638 GPU_line_width(1.0f);
639
641
642 float viewport_size[4];
643 GPU_viewport_size_get_f(viewport_size);
644 immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC);
645
646 immUniform1i("colors_len", 0); /* "simple" mode */
648 immUniform1f("dash_width", 6.0f);
649 immUniform1f("udash_factor", 0.5f);
650
652 immVertex2fv(shdr_pos, mval_src);
653 immVertex2fv(shdr_pos, mval_dst);
654 immEnd();
655
657}
658
659#define MAX_METADATA_STR 1024
660
661static const char *meta_data_list[] = {
662 "File",
663 "Strip",
664 "Date",
665 "RenderTime",
666 "Note",
667 "Marker",
668 "Time",
669 "Frame",
670 "Camera",
671 "Scene",
672};
673
674BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset)
675{
677 ibuf->metadata, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) &&
678 r_str[0]);
679}
680
682{
683 /* Metadata field stored by Blender for multi-layer EXR images. Is rather
684 * useless to be viewed all the time. Can still be seen in the Metadata
685 * panel. */
686 if (STREQ(field, "BlenderMultiChannel")) {
687 return false;
688 }
689 /* Is almost always has value "scanlineimage", also useless to be seen
690 * all the time. */
691 if (STREQ(field, "type")) {
692 return false;
693 }
694 return !BKE_stamp_is_known_field(field);
695}
696
703
704static void metadata_custom_draw_fields(const char *field, const char *value, void *ctx_v)
705{
706 if (!metadata_is_custom_drawable(field)) {
707 return;
708 }
710 char temp_str[MAX_METADATA_STR];
711 SNPRINTF(temp_str, "%s: %s", field, value);
712 BLF_position(ctx->fontid, ctx->xmin, ctx->ymin + ctx->current_y, 0.0f);
713 BLF_draw(ctx->fontid, temp_str, sizeof(temp_str));
714 ctx->current_y += ctx->vertical_offset;
715}
716
717static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const bool is_top)
718{
719 char temp_str[MAX_METADATA_STR];
720 int ofs_y = 0;
721 const float height = BLF_height_max(fontid);
722 const float margin = height / 8;
723 const float vertical_offset = (height + margin);
724
725 /* values taking margins into account */
726 const float descender = BLF_descender(fontid);
727 const float xmin = (rect->xmin + margin);
728 const float xmax = (rect->xmax - margin);
729 const float ymin = (rect->ymin + margin) - descender;
730 const float ymax = (rect->ymax - margin) - descender;
731
732 if (is_top) {
733 for (int i = 0; i < 4; i++) {
734 /* first line */
735 if (i == 0) {
736 bool do_newline = false;
737 int len = SNPRINTF_RLEN(temp_str, "%s: ", meta_data_list[0]);
738 if (metadata_is_valid(ibuf, temp_str, 0, len)) {
739 BLF_position(fontid, xmin, ymax - vertical_offset, 0.0f);
740 BLF_draw(fontid, temp_str, sizeof(temp_str));
741 do_newline = true;
742 }
743
744 len = SNPRINTF_RLEN(temp_str, "%s: ", meta_data_list[1]);
745 if (metadata_is_valid(ibuf, temp_str, 1, len)) {
746 int line_width = BLF_width(fontid, temp_str, sizeof(temp_str));
747 BLF_position(fontid, xmax - line_width, ymax - vertical_offset, 0.0f);
748 BLF_draw(fontid, temp_str, sizeof(temp_str));
749 do_newline = true;
750 }
751
752 if (do_newline) {
753 ofs_y += vertical_offset;
754 }
755 } /* Strip */
756 else if (ELEM(i, 1, 2)) {
757 int len = SNPRINTF_RLEN(temp_str, "%s: ", meta_data_list[i + 1]);
758 if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
759 BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
760 BLF_draw(fontid, temp_str, sizeof(temp_str));
761 ofs_y += vertical_offset;
762 }
763 } /* Note (wrapped) */
764 else if (i == 3) {
765 int len = SNPRINTF_RLEN(temp_str, "%s: ", meta_data_list[i + 1]);
766 if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
767 ResultBLF info;
768 BLF_enable(fontid, BLF_WORD_WRAP);
769 BLF_wordwrap(fontid, ibuf->x - (margin * 2));
770 BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
771 BLF_draw(fontid, temp_str, sizeof(temp_str), &info);
772 BLF_wordwrap(fontid, 0);
773 BLF_disable(fontid, BLF_WORD_WRAP);
774 ofs_y += vertical_offset * info.lines;
775 }
776 }
777 else {
778 int len = SNPRINTF_RLEN(temp_str, "%s: ", meta_data_list[i + 1]);
779 if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
780 int line_width = BLF_width(fontid, temp_str, sizeof(temp_str));
781 BLF_position(fontid, xmax - line_width, ymax - vertical_offset - ofs_y, 0.0f);
782 BLF_draw(fontid, temp_str, sizeof(temp_str));
783 ofs_y += vertical_offset;
784 }
785 }
786 }
787 }
788 else {
790 ctx.fontid = fontid;
791 ctx.xmin = xmin;
792 ctx.ymin = ymin;
793 ctx.current_y = ofs_y;
794 ctx.vertical_offset = vertical_offset;
796 int ofs_x = 0;
797 ofs_y = ctx.current_y;
798 for (int i = 5; i < 10; i++) {
799 int len = SNPRINTF_RLEN(temp_str, "%s: ", meta_data_list[i]);
800 if (metadata_is_valid(ibuf, temp_str, i, len)) {
801 BLF_position(fontid, xmin + ofs_x, ymin + ofs_y, 0.0f);
802 BLF_draw(fontid, temp_str, sizeof(temp_str));
803
804 ofs_x += BLF_width(fontid, temp_str, sizeof(temp_str)) + UI_UNIT_X;
805 }
806 }
807 }
808}
809
813
814static void metadata_custom_count_fields(const char *field, const char * /*value*/, void *ctx_v)
815{
816 if (!metadata_is_custom_drawable(field)) {
817 return;
818 }
820 ctx->count++;
821}
822
823static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
824{
825 const float height = BLF_height_max(fontid);
826 const float margin = (height / 8);
827 char str[MAX_METADATA_STR] = "";
828 short count = 0;
829
830 if (is_top) {
831 if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) {
832 count++;
833 }
834 for (int i = 2; i < 5; i++) {
835 if (metadata_is_valid(ibuf, str, i, 0)) {
836 if (i == 4) {
837 struct {
838 ResultBLF info;
839 rcti rect;
840 } wrap;
841
842 BLF_enable(fontid, BLF_WORD_WRAP);
843 BLF_wordwrap(fontid, ibuf->x - (margin * 2));
844 BLF_boundbox(fontid, str, sizeof(str), &wrap.rect, &wrap.info);
845 BLF_wordwrap(fontid, 0);
846 BLF_disable(fontid, BLF_WORD_WRAP);
847
848 count += wrap.info.lines;
849 }
850 else {
851 count++;
852 }
853 }
854 }
855 }
856 else {
857 for (int i = 5; i < 10; i++) {
858 if (metadata_is_valid(ibuf, str, i, 0)) {
859 count = 1;
860 break;
861 }
862 }
864 ctx.count = 0;
866 count += ctx.count;
867 }
868
869 if (count) {
870 return (height + margin) * count;
871 }
872
873 return 0;
874}
875
877 int x, int y, ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy)
878{
879 const uiStyle *style = UI_style_get_dpi();
880
881 if (!ibuf->metadata) {
882 return;
883 }
884
885 /* find window pixel coordinates of origin */
887
888 /* Offset and zoom using GPU viewport. */
890 GPU_matrix_scale_2f(zoomx, zoomy);
891
893
894 /* *** upper box*** */
895
896 /* get needed box height */
897 float box_y = metadata_box_height_get(ibuf, blf_mono_font, true);
898
899 if (box_y) {
900 /* set up rect */
901 rctf rect;
902 BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y);
903 /* draw top box */
909 immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
911
912 BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
914
916 metadata_draw_imbuf(ibuf, &rect, blf_mono_font, true);
917
920 }
921
922 /* *** lower box*** */
923
924 box_y = metadata_box_height_get(ibuf, blf_mono_font, false);
925
926 if (box_y) {
927 /* set up box rect */
928 rctf rect;
929 BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin);
930 /* draw top box */
936 immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
938
939 BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
941
943 metadata_draw_imbuf(ibuf, &rect, blf_mono_font, false);
944
947 }
948
950}
951
952#undef MAX_METADATA_STR
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
bool BKE_stamp_is_known_field(const char *field_name)
void BLF_size(int fontid, float size)
Definition blf.cc:426
int BLF_descender(int fontid) ATTR_WARN_UNUSED_RESULT
Definition blf.cc:850
void BLF_color3ubv(int fontid, const unsigned char rgb[3])
Definition blf.cc:459
void BLF_clipping(int fontid, int xmin, int ymin, int xmax, int ymax)
Definition blf.cc:881
void BLF_width_and_height(int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL()
Definition blf.cc:778
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:761
void BLF_disable(int fontid, int option)
Definition blf.cc:321
void BLF_rotation(int fontid, float angle)
Definition blf.cc:872
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:568
int blf_mono_font
Definition blf.cc:51
void BLF_enable(int fontid, int option)
Definition blf.cc:312
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition blf.cc:791
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT
Definition blf.cc:828
@ BLF_WORD_WRAP
Definition BLF_api.hh:367
@ BLF_CLIPPING
Definition BLF_api.hh:362
void BLF_wordwrap(int fontid, int wrap_width)
Definition blf.cc:893
void BLF_position(int fontid, float x, float y, float z)
Definition blf.cc:371
#define BLI_INLINE
#define LISTBASE_FOREACH(type, var, list)
MINLINE float max_ff(float a, float b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
MINLINE void copy_v2fl_v2i(float r[2], const int a[2])
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition rct.c:408
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define SNPRINTF_RLEN(dst, format,...)
Definition BLI_string.h:598
unsigned int uint
#define ELEM(...)
#define STREQ(a, b)
#define IFACE_(msgid)
@ RGN_TYPE_HEADER
#define UI_SCALE_FAC
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:803
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:966
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
#define REGION_DRAW_POST_PIXEL
SliderMode
Definition ED_util.hh:70
@ SLIDER_MODE_PERCENT
Definition ED_util.hh:70
@ SLIDER_MODE_FLOAT
Definition ED_util.hh:70
void immUniformThemeColorAlpha(int color_id, float a)
void immEnd()
void immUnbindProgram()
void immUniform2f(const char *name, float x, float y)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex2fv(uint attr_id, const float data[2])
void immUniform1i(const char *name, int x)
void immUniformThemeColor3(int color_id)
void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char a)
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat()
void immBegin(GPUPrimType, uint vertex_len)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
void GPU_matrix_scale_2f(float x, float y)
void GPU_matrix_push()
void GPU_matrix_pop()
void GPU_matrix_translate_2f(float x, float y)
@ GPU_PRIM_LINES
@ GPU_PRIM_TRIS
@ GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_line_width(float width)
Definition gpu_state.cc:161
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:262
void GPU_polygon_smooth(bool enable)
Definition gpu_state.cc:83
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Contains defines and structs used throughout the imbuf module.
bool IMB_metadata_get_field(const IDProperty *metadata, const char *key, char *value, size_t value_maxncpy)
Definition metadata.cc:42
void IMB_metadata_foreach(ImBuf *ibuf, IMBMetadataForeachCb callback, void *userdata)
Definition metadata.cc:88
Read Guarded memory(de)allocation.
void UI_draw_roundbox_3ub_alpha(const rctf *rect, bool filled, float rad, const unsigned char col[3], unsigned char alpha)
const uiStyle * UI_style_get_dpi()
const uiStyle * UI_style_get()
#define UI_UNIT_X
@ TH_HEADER
@ TH_METADATA_TEXT
@ TH_HEADER_TEXT
@ TH_VIEW_OVERLAY
@ TH_HEADER_TEXT_HI
@ TH_METADATA_BG
void UI_FontThemeColor(int fontid, int colorid)
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
@ KM_PRESS
Definition WM_types.hh:284
int pad[32 - sizeof(int)]
unsigned int U
Definition btGjkEpa3.h:78
int len
void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy)
Definition ed_draw.cc:876
#define MAX_METADATA_STR
Definition ed_draw.cc:659
void ED_slider_allow_overshoot_set(tSlider *slider, const bool lower, const bool upper)
Definition ed_draw.cc:580
static void draw_overshoot_triangle(const uint8_t color[4], const bool facing_right, const float x, const float y)
Definition ed_draw.cc:112
void ED_slider_init(tSlider *slider, const wmEvent *event)
Definition ed_draw.cc:467
static void draw_ticks(const float start_factor, const float end_factor, const float line_start[2], const float base_tick_height, const float line_width, const uint8_t color_overshoot[4], const uint8_t color_line[4])
Definition ed_draw.cc:137
static void metadata_custom_draw_fields(const char *field, const char *value, void *ctx_v)
Definition ed_draw.cc:704
#define SLIDER_UNIT_STRING_SIZE
Definition ed_draw.cc:57
static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
Definition ed_draw.cc:823
static void metadata_custom_count_fields(const char *field, const char *, void *ctx_v)
Definition ed_draw.cc:814
void ED_slider_factor_set(tSlider *slider, const float factor)
Definition ed_draw.cc:571
SliderMode ED_slider_mode_get(const tSlider *slider)
Definition ed_draw.cc:609
void ED_slider_unit_set(tSlider *slider, const char *unit)
Definition ed_draw.cc:614
void ED_slider_mode_set(tSlider *slider, SliderMode mode)
Definition ed_draw.cc:604
void ED_slider_allow_increments_set(tSlider *slider, const bool value)
Definition ed_draw.cc:591
#define SLIDE_PIXEL_DISTANCE
Definition ed_draw.cc:55
void ED_slider_property_label_set(tSlider *slider, const char *property_label)
Definition ed_draw.cc:619
void ED_slider_destroy(bContext *C, tSlider *slider)
Definition ed_draw.cc:553
static const char * meta_data_list[]
Definition ed_draw.cc:661
BLI_INLINE bool metadata_is_custom_drawable(const char *field)
Definition ed_draw.cc:681
static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const bool is_top)
Definition ed_draw.cc:717
static void draw_main_line(const rctf *main_line_rect, const float factor, const bool overshoot, const uint8_t color_overshoot[4], const uint8_t color_line[4])
Definition ed_draw.cc:183
BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset)
Definition ed_draw.cc:674
tSlider * ED_slider_create(bContext *C)
Definition ed_draw.cc:427
bool ED_slider_modal(tSlider *slider, const wmEvent *event)
Definition ed_draw.cc:472
#define OVERSHOOT_RANGE_DELTA
Definition ed_draw.cc:56
void ED_slider_factor_bounds_set(tSlider *slider, float factor_bound_lower, float factor_bound_upper)
Definition ed_draw.cc:596
bool ED_slider_allow_increments_get(const tSlider *slider)
Definition ed_draw.cc:586
static void slider_draw(const bContext *, ARegion *region, void *arg)
Definition ed_draw.cc:261
void ED_slider_status_string_get(const tSlider *slider, char *status_string, const size_t size_of_status_string)
Definition ed_draw.cc:505
void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_info)
Definition ed_draw.cc:626
static void draw_backdrop(const int fontid, const rctf *main_line_rect, const uint8_t color_bg[4], const short region_y_size, const float base_tick_height, const std::string &property_label)
Definition ed_draw.cc:227
float ED_slider_factor_get(const tSlider *slider)
Definition ed_draw.cc:566
static void slider_update_factor(tSlider *slider, const wmEvent *event)
Definition ed_draw.cc:398
draw_view in_light_buf[] float
#define str(s)
int count
format
ccl_device_inline float3 ceil(const float3 a)
float wrap(float value, float max, float min)
Definition node_math.h:71
unsigned char uint8_t
Definition stdint.h:78
struct ARegionType * type
IDProperty * metadata
int lines
Definition BLF_api.hh:406
ListBase regionbase
float xmax
float xmin
float ymax
float ymin
char unit_string[SLIDER_UNIT_STRING_SIZE]
Definition ed_draw.cc:89
float factor_bounds[2]
Definition ed_draw.cc:79
bool allow_overshoot_upper
Definition ed_draw.cc:95
bool overshoot
Definition ed_draw.cc:99
ARegion * region_header
Definition ed_draw.cc:64
bool allow_increments
Definition ed_draw.cc:103
bool precision
Definition ed_draw.cc:109
bool allow_overshoot_lower
Definition ed_draw.cc:94
float raw_factor
Definition ed_draw.cc:70
ScrArea * area
Definition ed_draw.cc:61
float last_cursor[2]
Definition ed_draw.cc:76
bool increments
Definition ed_draw.cc:106
std::string property_label
Definition ed_draw.cc:86
void * draw_handle
Definition ed_draw.cc:67
float factor
Definition ed_draw.cc:73
Scene * scene
Definition ed_draw.cc:60
SliderMode slider_mode
Definition ed_draw.cc:82
uiFontStyle widget
int xy[2]
Definition WM_types.hh:726
short type
Definition WM_types.hh:722
struct wmEvent * eventstate
@ EVT_EKEY
@ EVT_RIGHTCTRLKEY
@ EVT_LEFTCTRLKEY
@ MOUSEMOVE
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY