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
8
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/* -------------------------------------------------------------------- */
54
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
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);
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
625
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)
@ BLF_WORD_WRAP
Definition BLF_api.hh:367
@ BLF_CLIPPING
Definition BLF_api.hh:362
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
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.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
#define C
Definition RandGen.cpp:29
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)]
#define U
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
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
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
#define SLIDE_PIXEL_DISTANCE
Definition pose_slide.cc:78
#define OVERSHOOT_RANGE_DELTA
Definition pose_slide.cc:79
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
int ymin
int xmin
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