Blender  V3.3
interface_region_tooltip.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. All rights reserved. */
3 
10 /* TODO(campbell):
11  * We may want to have a higher level API that initializes a timer,
12  * checks for mouse motion and clears the tool-tip afterwards.
13  * We never want multiple tool-tips at once
14  * so this could be handled on the window / window-manager level.
15  *
16  * For now it's not a priority, so leave as-is.
17  */
18 
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "MEM_guardedalloc.h"
24 
25 #include "DNA_brush_types.h"
26 #include "DNA_userdef_types.h"
27 
28 #include "BLI_listbase.h"
29 #include "BLI_math.h"
30 #include "BLI_rect.h"
31 #include "BLI_string.h"
32 #include "BLI_utildefines.h"
33 
34 #include "BKE_context.h"
35 #include "BKE_paint.h"
36 #include "BKE_screen.h"
37 
38 #include "WM_api.h"
39 #include "WM_types.h"
40 
41 #include "RNA_access.h"
42 #include "RNA_path.h"
43 
44 #include "UI_interface.h"
45 
46 #include "BLF_api.h"
47 #include "BLT_translation.h"
48 
49 #ifdef WITH_PYTHON
50 # include "BPY_extern_run.h"
51 #endif
52 
53 #include "ED_screen.h"
54 
55 #include "interface_intern.h"
57 
58 #define UI_TIP_PAD_FAC 1.3f
59 #define UI_TIP_PADDING (int)(UI_TIP_PAD_FAC * UI_UNIT_Y)
60 #define UI_TIP_MAXWIDTH 600
61 
62 #define UI_TIP_STR_MAX 1024
63 
64 typedef struct uiTooltipFormat {
65  enum {
69  } style : 3;
70  enum {
71  UI_TIP_LC_MAIN = 0, /* primary text */
72  UI_TIP_LC_VALUE, /* the value of buttons (also shortcuts) */
73  UI_TIP_LC_ACTIVE, /* titles of active enum values */
74  UI_TIP_LC_NORMAL, /* regular text */
75  UI_TIP_LC_PYTHON, /* Python snippet */
76  UI_TIP_LC_ALERT, /* description of why operator can't run */
77  } color_id : 4;
78  int is_pad : 1;
80 
81 typedef struct uiTooltipField {
82  char *text;
83  char *text_suffix;
84  struct {
85  uint x_pos; /* x cursor position at the end of the last line */
86  uint lines; /* number of lines, 1 or more with word-wrap */
87  } geom;
89 
91 
92 typedef struct uiTooltipData {
98  int toth, lineh;
100 
101 #define UI_TIP_LC_MAX 6
102 
103 BLI_STATIC_ASSERT(UI_TIP_LC_MAX == UI_TIP_LC_ALERT + 1, "invalid lc-max");
104 BLI_STATIC_ASSERT(sizeof(uiTooltipFormat) <= sizeof(int), "oversize");
105 
107 {
108  data->fields_len += 1;
109  data->fields = MEM_recallocN(data->fields, sizeof(*data->fields) * data->fields_len);
110  return &data->fields[data->fields_len - 1];
111 }
112 
114 {
116  field->format = *format;
117  return field;
118 }
119 
120 /* -------------------------------------------------------------------- */
124 static void rgb_tint(float col[3], float h, float h_strength, float v, float v_strength)
125 {
126  float col_hsv_from[3];
127  float col_hsv_to[3];
128 
129  rgb_to_hsv_v(col, col_hsv_from);
130 
131  col_hsv_to[0] = h;
132  col_hsv_to[1] = h_strength;
133  col_hsv_to[2] = (col_hsv_from[2] * (1.0f - v_strength)) + (v * v_strength);
134 
135  hsv_to_rgb_v(col_hsv_to, col);
136 }
137 
138 static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *region)
139 {
140  const float pad_px = UI_TIP_PADDING;
141  uiTooltipData *data = region->regiondata;
142  const uiWidgetColors *theme = ui_tooltip_get_theme();
143  rcti bbox = data->bbox;
144  float tip_colors[UI_TIP_LC_MAX][3];
145  uchar drawcol[4] = {0, 0, 0, 255}; /* to store color in while drawing (alpha is always 255) */
146 
147  float *main_color = tip_colors[UI_TIP_LC_MAIN]; /* the color from the theme */
148  float *value_color = tip_colors[UI_TIP_LC_VALUE];
149  float *active_color = tip_colors[UI_TIP_LC_ACTIVE];
150  float *normal_color = tip_colors[UI_TIP_LC_NORMAL];
151  float *python_color = tip_colors[UI_TIP_LC_PYTHON];
152  float *alert_color = tip_colors[UI_TIP_LC_ALERT];
153 
154  float background_color[3];
155 
157 
158  /* draw background */
160 
161  /* set background_color */
162  rgb_uchar_to_float(background_color, theme->inner);
163 
164  /* calculate normal_color */
165  rgb_uchar_to_float(main_color, theme->text);
166  copy_v3_v3(active_color, main_color);
167  copy_v3_v3(normal_color, main_color);
168  copy_v3_v3(python_color, main_color);
169  copy_v3_v3(alert_color, main_color);
170  copy_v3_v3(value_color, main_color);
171 
172  /* find the brightness difference between background and text colors */
173 
174  const float tone_bg = rgb_to_grayscale(background_color);
175  /* tone_fg = rgb_to_grayscale(main_color); */
176 
177  /* mix the colors */
178  rgb_tint(value_color, 0.0f, 0.0f, tone_bg, 0.2f); /* Light gray. */
179  rgb_tint(active_color, 0.6f, 0.2f, tone_bg, 0.2f); /* Light blue. */
180  rgb_tint(normal_color, 0.0f, 0.0f, tone_bg, 0.4f); /* Gray. */
181  rgb_tint(python_color, 0.0f, 0.0f, tone_bg, 0.5f); /* Dark gray. */
182  rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* Red. */
183 
184  /* draw text */
185  BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
186  BLF_wordwrap(blf_mono_font, data->wrap_width);
187 
188  bbox.xmin += 0.5f * pad_px; /* add padding to the text */
189  bbox.ymax -= 0.25f * pad_px;
190 
191  for (int i = 0; i < data->fields_len; i++) {
192  const uiTooltipField *field = &data->fields[i];
193  const uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] : NULL;
194 
195  bbox.ymin = bbox.ymax - (data->lineh * field->geom.lines);
196  if (field->format.style == UI_TIP_STYLE_HEADER) {
197  const struct uiFontStyleDraw_Params fs_params = {
199  .word_wrap = true,
200  };
201  /* draw header and active data (is done here to be able to change color) */
202  rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_MAIN]);
203  UI_fontstyle_set(&data->fstyle);
204  UI_fontstyle_draw(&data->fstyle, &bbox, field->text, UI_TIP_STR_MAX, drawcol, &fs_params);
205 
206  /* offset to the end of the last line */
207  if (field->text_suffix) {
208  const float xofs = field->geom.x_pos;
209  const float yofs = data->lineh * (field->geom.lines - 1);
210  bbox.xmin += xofs;
211  bbox.ymax -= yofs;
212 
213  rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]);
215  &data->fstyle, &bbox, field->text_suffix, UI_TIP_STR_MAX, drawcol, &fs_params);
216 
217  /* undo offset */
218  bbox.xmin -= xofs;
219  bbox.ymax += yofs;
220  }
221  }
222  else if (field->format.style == UI_TIP_STYLE_MONO) {
223  const struct uiFontStyleDraw_Params fs_params = {
225  .word_wrap = true,
226  };
227  uiFontStyle fstyle_mono = data->fstyle;
228  fstyle_mono.uifont_id = blf_mono_font;
229 
230  UI_fontstyle_set(&fstyle_mono);
231  /* XXX, needed because we don't have mono in 'U.uifonts' */
232  BLF_size(fstyle_mono.uifont_id, fstyle_mono.points * U.pixelsize, U.dpi);
233  rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
234  UI_fontstyle_draw(&fstyle_mono, &bbox, field->text, UI_TIP_STR_MAX, drawcol, &fs_params);
235  }
236  else {
237  BLI_assert(field->format.style == UI_TIP_STYLE_NORMAL);
238  const struct uiFontStyleDraw_Params fs_params = {
240  .word_wrap = true,
241  };
242 
243  /* draw remaining data */
244  rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
245  UI_fontstyle_set(&data->fstyle);
246  UI_fontstyle_draw(&data->fstyle, &bbox, field->text, UI_TIP_STR_MAX, drawcol, &fs_params);
247  }
248 
249  bbox.ymax -= data->lineh * field->geom.lines;
250 
251  if (field_next && field_next->format.is_pad) {
252  bbox.ymax -= data->lineh * (UI_TIP_PAD_FAC - 1);
253  }
254  }
255 
256  BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
258 }
259 
260 static void ui_tooltip_region_free_cb(ARegion *region)
261 {
262  uiTooltipData *data = region->regiondata;
263 
264  for (int i = 0; i < data->fields_len; i++) {
265  const uiTooltipField *field = &data->fields[i];
266  MEM_freeN(field->text);
267  if (field->text_suffix) {
268  MEM_freeN(field->text_suffix);
269  }
270  }
271  MEM_freeN(data->fields);
272  MEM_freeN(data);
273  region->regiondata = NULL;
274 }
275 
278 /* -------------------------------------------------------------------- */
283 {
284  char *str = WM_operator_pystring_ex(C, NULL, false, false, ot, opptr);
285 
286  /* Avoid overly verbose tips (eg, arrays of 20 layers), exact limit is arbitrary. */
288 
289  return str;
290 }
291 
294 /* -------------------------------------------------------------------- */
298 #ifdef WITH_PYTHON
299 
300 static bool ui_tooltip_data_append_from_keymap(bContext *C, uiTooltipData *data, wmKeyMap *keymap)
301 {
302  const int fields_len_init = data->fields_len;
303  char buf[512];
304 
305  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
306  wmOperatorType *ot = WM_operatortype_find(kmi->idname, true);
307  if (ot != NULL) {
308  /* Tip */
309  {
311  &(uiTooltipFormat){
312  .style = UI_TIP_STYLE_NORMAL,
313  .color_id = UI_TIP_LC_MAIN,
314  .is_pad = true,
315  });
316  field->text = BLI_strdup(ot->description ? ot->description : ot->name);
317  }
318  /* Shortcut */
319  {
321  &(uiTooltipFormat){
322  .style = UI_TIP_STYLE_NORMAL,
323  .color_id = UI_TIP_LC_NORMAL,
324  });
325  bool found = false;
326  if (WM_keymap_item_to_string(kmi, false, buf, sizeof(buf))) {
327  found = true;
328  }
329  field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None");
330  }
331 
332  /* Python */
333  if (U.flag & USER_TOOLTIPS_PYTHON) {
335  &(uiTooltipFormat){
336  .style = UI_TIP_STYLE_NORMAL,
337  .color_id = UI_TIP_LC_PYTHON,
338  });
339  char *str = ui_tooltip_text_python_from_op(C, ot, kmi->ptr);
340  field->text = BLI_sprintfN(TIP_("Python: %s"), str);
341  MEM_freeN(str);
342  }
343  }
344  }
345 
346  return (fields_len_init != data->fields_len);
347 }
348 
349 #endif /* WITH_PYTHON */
350 
355 {
356  if (but->optype == NULL) {
357  return NULL;
358  }
359 
360  if (!STREQ(but->optype->idname, "WM_OT_tool_set_by_id")) {
361  return NULL;
362  }
363 
364  /* Needed to get the space-data's type (below). */
365  if (CTX_wm_space_data(C) == NULL) {
366  return NULL;
367  }
368 
369  char tool_id[MAX_NAME];
370  RNA_string_get(but->opptr, "name", tool_id);
371  BLI_assert(tool_id[0] != '\0');
372 
373  /* When false, we're in a different space type to the tool being set.
374  * Needed for setting the fallback tool from the properties space.
375  *
376  * If we drop the hard coded 3D-view in properties hack, we can remove this check. */
377  bool has_valid_context = true;
378  const char *has_valid_context_error = IFACE_("Unsupported context");
379  {
381  if (area == NULL) {
382  has_valid_context = false;
383  }
384  else {
385  PropertyRNA *prop = RNA_struct_find_property(but->opptr, "space_type");
386  if (RNA_property_is_set(but->opptr, prop)) {
387  const int space_type_prop = RNA_property_enum_get(but->opptr, prop);
388  if (space_type_prop != area->spacetype) {
389  has_valid_context = false;
390  }
391  }
392  }
393  }
394 
395  /* We have a tool, now extract the info. */
396  uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
397 
398 #ifdef WITH_PYTHON
399  /* it turns out to be most simple to do this via Python since C
400  * doesn't have access to information about non-active tools.
401  */
402 
403  /* Title (when icon-only). */
404  if (but->drawstr[0] == '\0') {
405  const char *expr_imports[] = {"bpy", "bl_ui", NULL};
406  char expr[256];
407  SNPRINTF(expr,
408  "bl_ui.space_toolsystem_common.item_from_id("
409  "bpy.context, "
410  "bpy.context.space_data.type, "
411  "'%s').label",
412  tool_id);
413  char *expr_result = NULL;
414  bool is_error = false;
415 
416  if (has_valid_context == false) {
417  expr_result = BLI_strdup(has_valid_context_error);
418  }
419  else if (BPY_run_string_as_string(C, expr_imports, expr, NULL, &expr_result)) {
420  if (STREQ(expr_result, "")) {
421  MEM_freeN(expr_result);
422  expr_result = NULL;
423  }
424  }
425  else {
426  /* NOTE: this is an exceptional case, we could even remove it
427  * however there have been reports of tooltips failing, so keep it for now. */
428  expr_result = BLI_strdup(IFACE_("Internal error!"));
429  is_error = true;
430  }
431 
432  if (expr_result != NULL) {
433  /* NOTE: This is a very weak hack to get a valid translation most of the time...
434  * Proper way to do would be to get i18n context from the item, somehow. */
435  const char *label_str = CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, expr_result);
436  if (label_str == expr_result) {
437  label_str = IFACE_(expr_result);
438  }
439 
440  if (label_str != expr_result) {
441  MEM_freeN(expr_result);
442  expr_result = BLI_strdup(label_str);
443  }
444 
446  &(uiTooltipFormat){
447  .style = UI_TIP_STYLE_NORMAL,
448  .color_id = UI_TIP_LC_MAIN,
449  .is_pad = true,
450  });
451  field->text = expr_result;
452 
453  if (UNLIKELY(is_error)) {
454  field->format.color_id = UI_TIP_LC_ALERT;
455  }
456  }
457  }
458 
459  /* Tip. */
460  if (is_label == false) {
461  const char *expr_imports[] = {"bpy", "bl_ui", NULL};
462  char expr[256];
463  SNPRINTF(expr,
464  "bl_ui.space_toolsystem_common.description_from_id("
465  "bpy.context, "
466  "bpy.context.space_data.type, "
467  "'%s') + '.'",
468  tool_id);
469 
470  char *expr_result = NULL;
471  bool is_error = false;
472 
473  if (has_valid_context == false) {
474  expr_result = BLI_strdup(has_valid_context_error);
475  }
476  else if (BPY_run_string_as_string(C, expr_imports, expr, NULL, &expr_result)) {
477  if (STREQ(expr_result, ".")) {
478  MEM_freeN(expr_result);
479  expr_result = NULL;
480  }
481  }
482  else {
483  /* NOTE: this is an exceptional case, we could even remove it
484  * however there have been reports of tooltips failing, so keep it for now. */
485  expr_result = BLI_strdup(TIP_("Internal error!"));
486  is_error = true;
487  }
488 
489  if (expr_result != NULL) {
491  &(uiTooltipFormat){
492  .style = UI_TIP_STYLE_NORMAL,
493  .color_id = UI_TIP_LC_MAIN,
494  .is_pad = true,
495  });
496  field->text = expr_result;
497 
498  if (UNLIKELY(is_error)) {
499  field->format.color_id = UI_TIP_LC_ALERT;
500  }
501  }
502  }
503 
504  /* Shortcut. */
505  const bool show_shortcut = is_label == false &&
506  ((but->block->flag & UI_BLOCK_SHOW_SHORTCUT_ALWAYS) == 0);
507 
508  if (show_shortcut) {
509  /* There are different kinds of shortcuts:
510  *
511  * - Direct access to the tool (as if the toolbar button is pressed).
512  * - The key is bound to a brush type (not the exact brush name).
513  * - The key is assigned to the operator itself
514  * (bypassing the tool, executing the operator).
515  *
516  * Either way case it's useful to show the shortcut.
517  */
518  char *shortcut = NULL;
519 
520  {
521  uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, NULL};
522  UI_but_string_info_get(C, but, &op_keymap, NULL);
523  shortcut = op_keymap.strinfo;
524  }
525 
526  if (shortcut == NULL) {
528  const char *tool_attr = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
529  if (tool_attr != NULL) {
530  const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode);
531  const char *tool_id_lstrip = strrchr(tool_id, '.');
532  const int tool_id_offset = tool_id_lstrip ? ((tool_id_lstrip - tool_id) + 1) : 0;
533  const int i = RNA_enum_from_name(items, tool_id + tool_id_offset);
534 
535  if (i != -1) {
536  wmOperatorType *ot = WM_operatortype_find("paint.brush_select", true);
537  PointerRNA op_props;
539  RNA_enum_set(&op_props, tool_attr, items[i].value);
540 
541  /* Check for direct access to the tool. */
542  char shortcut_brush[128] = "";
544  ot->idname,
546  op_props.data,
547  true,
548  shortcut_brush,
549  ARRAY_SIZE(shortcut_brush))) {
550  shortcut = BLI_strdup(shortcut_brush);
551  }
552  WM_operator_properties_free(&op_props);
553  }
554  }
555  }
556 
557  if (shortcut == NULL) {
558  /* Check for direct access to the tool. */
559  char shortcut_toolbar[128] = "";
561  "WM_OT_toolbar",
563  NULL,
564  true,
565  shortcut_toolbar,
566  ARRAY_SIZE(shortcut_toolbar))) {
567  /* Generate keymap in order to inspect it.
568  * NOTE: we could make a utility to avoid the keymap generation part of this. */
569  const char *expr_imports[] = {
570  "bpy", "bl_keymap_utils", "bl_keymap_utils.keymap_from_toolbar", NULL};
571  const char *expr =
572  ("getattr("
573  "bl_keymap_utils.keymap_from_toolbar.generate("
574  "bpy.context, "
575  "bpy.context.space_data.type), "
576  "'as_pointer', lambda: 0)()");
577 
578  intptr_t expr_result = 0;
579 
580  if (has_valid_context == false) {
581  shortcut = BLI_strdup(has_valid_context_error);
582  }
583  else if (BPY_run_string_as_intptr(C, expr_imports, expr, NULL, &expr_result)) {
584  if (expr_result != 0) {
585  wmKeyMap *keymap = (wmKeyMap *)expr_result;
586  LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
587  if (STREQ(kmi->idname, but->optype->idname)) {
588  char tool_id_test[MAX_NAME];
589  RNA_string_get(kmi->ptr, "name", tool_id_test);
590  if (STREQ(tool_id, tool_id_test)) {
591  char buf[128];
592  WM_keymap_item_to_string(kmi, false, buf, sizeof(buf));
593  shortcut = BLI_sprintfN("%s, %s", shortcut_toolbar, buf);
594  break;
595  }
596  }
597  }
598  }
599  }
600  else {
601  BLI_assert(0);
602  }
603  }
604  }
605 
606  if (shortcut != NULL) {
608  &(uiTooltipFormat){
609  .style = UI_TIP_STYLE_NORMAL,
610  .color_id = UI_TIP_LC_VALUE,
611  .is_pad = true,
612  });
613  field->text = BLI_sprintfN(TIP_("Shortcut: %s"), shortcut);
614  MEM_freeN(shortcut);
615  }
616  }
617 
618  if (show_shortcut) {
619  /* Shortcut for Cycling
620  *
621  * As a second option, we may have a shortcut to cycle this tool group.
622  *
623  * Since some keymaps may use this for the primary means of binding keys,
624  * it's useful to show these too.
625  * Without this there is no way to know how to use a key to set the tool.
626  *
627  * This is a little involved since the shortcut may be bound to another tool in this group,
628  * instead of the current tool on display. */
629 
630  char *expr_result = NULL;
631  size_t expr_result_len;
632 
633  {
634  const char *expr_imports[] = {"bpy", "bl_ui", NULL};
635  char expr[256];
636  SNPRINTF(expr,
637  "'\\x00'.join("
638  "item.idname for item in bl_ui.space_toolsystem_common.item_group_from_id("
639  "bpy.context, "
640  "bpy.context.space_data.type, '%s', coerce=True) "
641  "if item is not None)",
642  tool_id);
643 
644  if (has_valid_context == false) {
645  /* pass */
646  }
648  C, expr_imports, expr, NULL, &expr_result, &expr_result_len)) {
649  /* pass. */
650  }
651  }
652 
653  if (expr_result != NULL) {
654  PointerRNA op_props;
655  WM_operator_properties_create_ptr(&op_props, but->optype);
656  RNA_boolean_set(&op_props, "cycle", true);
657 
658  char shortcut[128] = "";
659 
660  const char *item_end = expr_result + expr_result_len;
661  const char *item_step = expr_result;
662 
663  while (item_step < item_end) {
664  RNA_string_set(&op_props, "name", item_step);
666  but->optype->idname,
668  op_props.data,
669  true,
670  shortcut,
671  ARRAY_SIZE(shortcut))) {
672  break;
673  }
674  item_step += strlen(item_step) + 1;
675  }
676 
677  WM_operator_properties_free(&op_props);
678  MEM_freeN(expr_result);
679 
680  if (shortcut[0] != '\0') {
682  &(uiTooltipFormat){
683  .style = UI_TIP_STYLE_NORMAL,
684  .color_id = UI_TIP_LC_VALUE,
685  .is_pad = true,
686  });
687  field->text = BLI_sprintfN(TIP_("Shortcut Cycle: %s"), shortcut);
688  }
689  }
690  }
691 
692  /* Python */
693  if ((is_label == false) && (U.flag & USER_TOOLTIPS_PYTHON)) {
695  &(uiTooltipFormat){
696  .style = UI_TIP_STYLE_NORMAL,
697  .color_id = UI_TIP_LC_PYTHON,
698  .is_pad = true,
699  });
700  char *str = ui_tooltip_text_python_from_op(C, but->optype, but->opptr);
701  field->text = BLI_sprintfN(TIP_("Python: %s"), str);
702  MEM_freeN(str);
703  }
704 
705  /* Keymap */
706 
707  /* This is too handy not to expose somehow, let's be sneaky for now. */
708  if ((is_label == false) && CTX_wm_window(C)->eventstate->modifier & KM_SHIFT) {
709  const char *expr_imports[] = {"bpy", "bl_ui", NULL};
710  char expr[256];
711  SNPRINTF(expr,
712  "getattr("
713  "bl_ui.space_toolsystem_common.keymap_from_id("
714  "bpy.context, "
715  "bpy.context.space_data.type, "
716  "'%s'), "
717  "'as_pointer', lambda: 0)()",
718  tool_id);
719 
720  intptr_t expr_result = 0;
721 
722  if (has_valid_context == false) {
723  /* pass */
724  }
725  else if (BPY_run_string_as_intptr(C, expr_imports, expr, NULL, &expr_result)) {
726  if (expr_result != 0) {
727  {
729  &(uiTooltipFormat){
730  .style = UI_TIP_STYLE_NORMAL,
731  .color_id = UI_TIP_LC_NORMAL,
732  .is_pad = true,
733  });
734  field->text = BLI_strdup("Tool Keymap:");
735  }
736  wmKeyMap *keymap = (wmKeyMap *)expr_result;
737  ui_tooltip_data_append_from_keymap(C, data, keymap);
738  }
739  }
740  else {
741  BLI_assert(0);
742  }
743  }
744 #else
745  UNUSED_VARS(is_label, has_valid_context, has_valid_context_error);
746 #endif /* WITH_PYTHON */
747 
748  if (data->fields_len == 0) {
749  MEM_freeN(data);
750  return NULL;
751  }
752  return data;
753 }
754 
756  uiBut *but,
757  uiButExtraOpIcon *extra_icon)
758 {
759  uiStringInfo but_label = {BUT_GET_LABEL, NULL};
760  uiStringInfo but_tip = {BUT_GET_TIP, NULL};
761  uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
762  uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
763  uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, NULL};
764  uiStringInfo prop_keymap = {BUT_GET_PROP_KEYMAP, NULL};
767 
768  char buf[512];
769 
770  wmOperatorType *optype = extra_icon ? UI_but_extra_operator_icon_optype_get(extra_icon) :
771  but->optype;
772  PropertyRNA *rnaprop = extra_icon ? NULL : but->rnaprop;
773 
774  /* create tooltip data */
775  uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
776 
777  if (extra_icon) {
778  UI_but_extra_icon_string_info_get(C, extra_icon, &but_label, &but_tip, &op_keymap, NULL);
779  }
780  else {
782  but,
783  &but_label,
784  &but_tip,
785  &enum_label,
786  &enum_tip,
787  &op_keymap,
788  &prop_keymap,
789  &rna_struct,
790  &rna_prop,
791  NULL);
792  }
793 
794  /* Tip Label (only for buttons not already showing the label).
795  * Check prefix instead of comparing because the button may include the shortcut.
796  * Buttons with dynamic tooltips also don't get their default label here since they
797  * can already provide more accurate and specific tooltip content. */
798  if (but_label.strinfo && !STRPREFIX(but->drawstr, but_label.strinfo) && !but->tip_func) {
800  &(uiTooltipFormat){
801  .style = UI_TIP_STYLE_HEADER,
802  .color_id = UI_TIP_LC_NORMAL,
803  });
804  field->text = BLI_strdup(but_label.strinfo);
805  }
806 
807  /* Tip */
808  if (but_tip.strinfo) {
809  {
811  &(uiTooltipFormat){
812  .style = UI_TIP_STYLE_HEADER,
813  .color_id = UI_TIP_LC_NORMAL,
814  });
815  if (enum_label.strinfo) {
816  field->text = BLI_sprintfN("%s: ", but_tip.strinfo);
817  field->text_suffix = BLI_strdup(enum_label.strinfo);
818  }
819  else {
820  field->text = BLI_sprintfN("%s.", but_tip.strinfo);
821  }
822  }
823 
824  /* special case enum rna buttons */
825  if ((but->type & UI_BTYPE_ROW) && rnaprop && RNA_property_flag(rnaprop) & PROP_ENUM_FLAG) {
827  &(uiTooltipFormat){
828  .style = UI_TIP_STYLE_NORMAL,
829  .color_id = UI_TIP_LC_NORMAL,
830  });
831  field->text = BLI_strdup(TIP_("(Shift-Click/Drag to select multiple)"));
832  }
833  }
834  /* Enum field label & tip */
835  if (enum_tip.strinfo) {
837  &(uiTooltipFormat){
838  .style = UI_TIP_STYLE_NORMAL,
839  .color_id = UI_TIP_LC_VALUE,
840  .is_pad = true,
841  });
842  field->text = BLI_strdup(enum_tip.strinfo);
843  }
844 
845  /* Op shortcut */
846  if (op_keymap.strinfo) {
848  &(uiTooltipFormat){
849  .style = UI_TIP_STYLE_NORMAL,
850  .color_id = UI_TIP_LC_VALUE,
851  .is_pad = true,
852  });
853  field->text = BLI_sprintfN(TIP_("Shortcut: %s"), op_keymap.strinfo);
854  }
855 
856  /* Property context-toggle shortcut */
857  if (prop_keymap.strinfo) {
859  &(uiTooltipFormat){
860  .style = UI_TIP_STYLE_NORMAL,
861  .color_id = UI_TIP_LC_VALUE,
862  .is_pad = true,
863  });
864  field->text = BLI_sprintfN(TIP_("Shortcut: %s"), prop_keymap.strinfo);
865  }
866 
868  /* better not show the value of a password */
869  if ((rnaprop && (RNA_property_subtype(rnaprop) == PROP_PASSWORD)) == 0) {
870  /* full string */
871  ui_but_string_get(but, buf, sizeof(buf));
872  if (buf[0]) {
874  &(uiTooltipFormat){
875  .style = UI_TIP_STYLE_NORMAL,
876  .color_id = UI_TIP_LC_VALUE,
877  .is_pad = true,
878  });
879  field->text = BLI_sprintfN(TIP_("Value: %s"), buf);
880  }
881  }
882  }
883 
884  if (rnaprop) {
885  const int unit_type = UI_but_unit_type_get(but);
886 
887  if (unit_type == PROP_UNIT_ROTATION) {
888  if (RNA_property_type(rnaprop) == PROP_FLOAT) {
889  float value = RNA_property_array_check(rnaprop) ?
890  RNA_property_float_get_index(&but->rnapoin, rnaprop, but->rnaindex) :
891  RNA_property_float_get(&but->rnapoin, rnaprop);
892 
894  &(uiTooltipFormat){
895  .style = UI_TIP_STYLE_NORMAL,
896  .color_id = UI_TIP_LC_VALUE,
897  });
898  field->text = BLI_sprintfN(TIP_("Radians: %f"), value);
899  }
900  }
901 
902  if (but->flag & UI_BUT_DRIVEN) {
903  if (ui_but_anim_expression_get(but, buf, sizeof(buf))) {
905  &(uiTooltipFormat){
906  .style = UI_TIP_STYLE_NORMAL,
907  .color_id = UI_TIP_LC_NORMAL,
908  });
909  field->text = BLI_sprintfN(TIP_("Expression: %s"), buf);
910  }
911  }
912 
913  if (but->rnapoin.owner_id) {
914  const ID *id = but->rnapoin.owner_id;
915  if (ID_IS_LINKED(id)) {
917  &(uiTooltipFormat){
918  .style = UI_TIP_STYLE_NORMAL,
919  .color_id = UI_TIP_LC_NORMAL,
920  });
921  field->text = BLI_sprintfN(TIP_("Library: %s"), id->lib->filepath);
922  }
923  }
924  }
925  else if (optype) {
926  PointerRNA *opptr = extra_icon ? UI_but_extra_operator_icon_opptr_get(extra_icon) :
927  /* allocated when needed, the button owns it */
929 
930  /* so the context is passed to fieldf functions (some py fieldf functions use it) */
931  WM_operator_properties_sanitize(opptr, false);
932 
933  char *str = ui_tooltip_text_python_from_op(C, optype, opptr);
934 
935  /* operator info */
936  if (U.flag & USER_TOOLTIPS_PYTHON) {
938  &(uiTooltipFormat){
939  .style = UI_TIP_STYLE_MONO,
940  .color_id = UI_TIP_LC_PYTHON,
941  .is_pad = true,
942  });
943  field->text = BLI_sprintfN(TIP_("Python: %s"), str);
944  }
945 
946  MEM_freeN(str);
947  }
948 
949  /* button is disabled, we may be able to tell user why */
950  if ((but->flag & UI_BUT_DISABLED) || extra_icon) {
951  const char *disabled_msg = NULL;
952  bool disabled_msg_free = false;
953 
954  /* if operator poll check failed, it can give pretty precise info why */
955  if (optype) {
956  const wmOperatorCallContext opcontext = extra_icon ? extra_icon->optype_params->opcontext :
957  but->opcontext;
960  C, but, &(wmOperatorCallParams){.optype = optype, .opcontext = opcontext});
961  disabled_msg = CTX_wm_operator_poll_msg_get(C, &disabled_msg_free);
962  }
963  /* alternatively, buttons can store some reasoning too */
964  else if (!extra_icon && but->disabled_info) {
965  disabled_msg = TIP_(but->disabled_info);
966  }
967 
968  if (disabled_msg && disabled_msg[0]) {
970  &(uiTooltipFormat){
971  .style = UI_TIP_STYLE_NORMAL,
972  .color_id = UI_TIP_LC_ALERT,
973  });
974  field->text = BLI_sprintfN(TIP_("Disabled: %s"), disabled_msg);
975  }
976  if (disabled_msg_free) {
977  MEM_freeN((void *)disabled_msg);
978  }
979  }
980 
981  if ((U.flag & USER_TOOLTIPS_PYTHON) && !optype && rna_struct.strinfo) {
982  {
984  &(uiTooltipFormat){
985  .style = UI_TIP_STYLE_MONO,
986  .color_id = UI_TIP_LC_PYTHON,
987  .is_pad = true,
988  });
989  if (rna_prop.strinfo) {
990  /* Struct and prop */
991  field->text = BLI_sprintfN(TIP_("Python: %s.%s"), rna_struct.strinfo, rna_prop.strinfo);
992  }
993  else {
994  /* Only struct (e.g. menus) */
995  field->text = BLI_sprintfN(TIP_("Python: %s"), rna_struct.strinfo);
996  }
997  }
998 
999  if (but->rnapoin.owner_id) {
1001  &(uiTooltipFormat){
1002  .style = UI_TIP_STYLE_MONO,
1003  .color_id = UI_TIP_LC_PYTHON,
1004  });
1005 
1006  /* this could get its own 'BUT_GET_...' type */
1007 
1008  /* never fails */
1009  /* Move ownership (no need for re-allocation). */
1010  if (rnaprop) {
1012  CTX_data_main(C), &but->rnapoin, rnaprop, but->rnaindex, true);
1013  }
1014  else {
1016  }
1017  }
1018  }
1019 
1020  /* Free strinfo's... */
1021  if (but_label.strinfo) {
1022  MEM_freeN(but_label.strinfo);
1023  }
1024  if (but_tip.strinfo) {
1025  MEM_freeN(but_tip.strinfo);
1026  }
1027  if (enum_label.strinfo) {
1028  MEM_freeN(enum_label.strinfo);
1029  }
1030  if (enum_tip.strinfo) {
1031  MEM_freeN(enum_tip.strinfo);
1032  }
1033  if (op_keymap.strinfo) {
1034  MEM_freeN(op_keymap.strinfo);
1035  }
1036  if (prop_keymap.strinfo) {
1037  MEM_freeN(prop_keymap.strinfo);
1038  }
1039  if (rna_struct.strinfo) {
1040  MEM_freeN(rna_struct.strinfo);
1041  }
1042  if (rna_prop.strinfo) {
1043  MEM_freeN(rna_prop.strinfo);
1044  }
1045 
1046  if (data->fields_len == 0) {
1047  MEM_freeN(data);
1048  return NULL;
1049  }
1050  return data;
1051 }
1052 
1054 {
1055  uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
1056 
1057  /* TODO(campbell): a way for gizmos to have their own descriptions (low priority). */
1058 
1059  /* Operator Actions */
1060  {
1061  const bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part;
1062  const struct {
1063  int part;
1064  const char *prefix;
1065  } gzop_actions[] = {
1066  {
1067  .part = gz->highlight_part,
1068  .prefix = use_drag ? CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Click") : NULL,
1069  },
1070  {
1071  .part = use_drag ? gz->drag_part : -1,
1072  .prefix = use_drag ? CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Drag") : NULL,
1073  },
1074  };
1075 
1076  for (int i = 0; i < ARRAY_SIZE(gzop_actions); i++) {
1077  wmGizmoOpElem *gzop = (gzop_actions[i].part != -1) ?
1078  WM_gizmo_operator_get(gz, gzop_actions[i].part) :
1079  NULL;
1080  if (gzop != NULL) {
1081  /* Description */
1082  char *info = WM_operatortype_description_or_name(C, gzop->type, &gzop->ptr);
1083 
1084  if (info != NULL) {
1085  char *text = info;
1086 
1087  if (gzop_actions[i].prefix != NULL) {
1088  text = BLI_sprintfN("%s: %s", gzop_actions[i].prefix, info);
1089  MEM_freeN(info);
1090  }
1091 
1092  if (text != NULL) {
1094  &(uiTooltipFormat){
1095  .style = UI_TIP_STYLE_HEADER,
1096  .color_id = UI_TIP_LC_VALUE,
1097  .is_pad = true,
1098  });
1099  field->text = text;
1100  }
1101  }
1102 
1103  /* Shortcut */
1104  {
1105  IDProperty *prop = gzop->ptr.data;
1106  char buf[128];
1108  C, gzop->type->idname, WM_OP_INVOKE_DEFAULT, prop, true, buf, ARRAY_SIZE(buf))) {
1110  &(uiTooltipFormat){
1111  .style = UI_TIP_STYLE_NORMAL,
1112  .color_id = UI_TIP_LC_VALUE,
1113  .is_pad = true,
1114  });
1115  field->text = BLI_sprintfN(TIP_("Shortcut: %s"), buf);
1116  }
1117  }
1118  }
1119  }
1120  }
1121 
1122  /* Property Actions */
1123  if (gz->type->target_property_defs_len) {
1124  wmGizmoProperty *gz_prop_array = WM_gizmo_target_property_array(gz);
1125  for (int i = 0; i < gz->type->target_property_defs_len; i++) {
1126  /* TODO(campbell): function callback descriptions. */
1127  wmGizmoProperty *gz_prop = &gz_prop_array[i];
1128  if (gz_prop->prop != NULL) {
1129  const char *info = RNA_property_ui_description(gz_prop->prop);
1130  if (info && info[0]) {
1132  &(uiTooltipFormat){
1133  .style = UI_TIP_STYLE_NORMAL,
1134  .color_id = UI_TIP_LC_VALUE,
1135  .is_pad = true,
1136  });
1137  field->text = BLI_strdup(info);
1138  }
1139  }
1140  }
1141  }
1142 
1143  if (data->fields_len == 0) {
1144  MEM_freeN(data);
1145  return NULL;
1146  }
1147  return data;
1148 }
1149 
1152  const float init_position[2],
1153  const rcti *init_rect_overlap,
1154  const float aspect)
1155 {
1156  const float pad_px = UI_TIP_PADDING;
1157  wmWindow *win = CTX_wm_window(C);
1158  const int winx = WM_window_pixels_x(win);
1159  const int winy = WM_window_pixels_y(win);
1160  const uiStyle *style = UI_style_get();
1161  rcti rect_i;
1162  int font_flag = 0;
1163 
1164  /* create area region */
1166 
1167  static ARegionType type;
1168  memset(&type, 0, sizeof(ARegionType));
1171  type.regionid = RGN_TYPE_TEMPORARY;
1172  region->type = &type;
1173 
1174  /* set font, get bb */
1175  data->fstyle = style->widget; /* copy struct */
1176  ui_fontscale(&data->fstyle.points, aspect);
1177 
1178  UI_fontstyle_set(&data->fstyle);
1179 
1180  data->wrap_width = min_ii(UI_TIP_MAXWIDTH * U.pixelsize / aspect, winx - (UI_TIP_PADDING * 2));
1181 
1182  font_flag |= BLF_WORD_WRAP;
1183  BLF_enable(data->fstyle.uifont_id, font_flag);
1184  BLF_enable(blf_mono_font, font_flag);
1185  BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
1186  BLF_wordwrap(blf_mono_font, data->wrap_width);
1187 
1188  /* these defines tweaked depending on font */
1189 #define TIP_BORDER_X (16.0f / aspect)
1190 #define TIP_BORDER_Y (6.0f / aspect)
1191 
1192  int h = BLF_height_max(data->fstyle.uifont_id);
1193 
1194  int i, fonth, fontw;
1195  for (i = 0, fontw = 0, fonth = 0; i < data->fields_len; i++) {
1196  uiTooltipField *field = &data->fields[i];
1197  uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] : NULL;
1198 
1199  struct ResultBLF info;
1200  int w, x_pos = 0;
1201  int font_id;
1202 
1203  if (field->format.style == UI_TIP_STYLE_MONO) {
1204  BLF_size(blf_mono_font, data->fstyle.points * U.pixelsize, U.dpi);
1205  font_id = blf_mono_font;
1206  }
1207  else {
1208  BLI_assert(ELEM(field->format.style, UI_TIP_STYLE_NORMAL, UI_TIP_STYLE_HEADER));
1209  font_id = data->fstyle.uifont_id;
1210  }
1211  w = BLF_width_ex(font_id, field->text, UI_TIP_STR_MAX, &info);
1212 
1213  /* check for suffix (enum label) */
1214  if (field->text_suffix && field->text_suffix[0]) {
1215  x_pos = info.width;
1216  w = max_ii(w, x_pos + BLF_width(font_id, field->text_suffix, UI_TIP_STR_MAX));
1217  }
1218  fontw = max_ii(fontw, w);
1219 
1220  fonth += h * info.lines;
1221  if (field_next && field_next->format.is_pad) {
1222  fonth += h * (UI_TIP_PAD_FAC - 1);
1223  }
1224 
1225  field->geom.lines = info.lines;
1226  field->geom.x_pos = x_pos;
1227  }
1228 
1229  // fontw *= aspect;
1230 
1231  BLF_disable(data->fstyle.uifont_id, font_flag);
1232  BLF_disable(blf_mono_font, font_flag);
1233 
1234  region->regiondata = data;
1235 
1236  data->toth = fonth;
1237  data->lineh = h;
1238 
1239  /* Compute position. */
1240  {
1241  rctf rect_fl;
1242  rect_fl.xmin = init_position[0] - TIP_BORDER_X;
1243  rect_fl.xmax = rect_fl.xmin + fontw + pad_px;
1244  rect_fl.ymax = init_position[1] - TIP_BORDER_Y;
1245  rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y;
1246  BLI_rcti_rctf_copy(&rect_i, &rect_fl);
1247  }
1248 
1249 #undef TIP_BORDER_X
1250 #undef TIP_BORDER_Y
1251 
1252  // #define USE_ALIGN_Y_CENTER
1253 
1254  /* Clamp to window bounds. */
1255  {
1256  /* Ensure at least 5 px above screen bounds
1257  * UI_UNIT_Y is just a guess to be above the menu item */
1258  if (init_rect_overlap != NULL) {
1259  const int pad = max_ff(1.0f, U.pixelsize) * 5;
1260  const rcti init_rect = {
1261  .xmin = init_rect_overlap->xmin - pad,
1262  .xmax = init_rect_overlap->xmax + pad,
1263  .ymin = init_rect_overlap->ymin - pad,
1264  .ymax = init_rect_overlap->ymax + pad,
1265  };
1266  const rcti rect_clamp = {
1267  .xmin = 0,
1268  .xmax = winx,
1269  .ymin = 0,
1270  .ymax = winy,
1271  };
1272  /* try right. */
1273  const int size_x = BLI_rcti_size_x(&rect_i);
1274  const int size_y = BLI_rcti_size_y(&rect_i);
1275  const int cent_overlap_x = BLI_rcti_cent_x(&init_rect);
1276 #ifdef USE_ALIGN_Y_CENTER
1277  const int cent_overlap_y = BLI_rcti_cent_y(&init_rect);
1278 #endif
1279  struct {
1280  rcti xpos;
1281  rcti xneg;
1282  rcti ypos;
1283  rcti yneg;
1284  } rect;
1285 
1286  { /* xpos */
1287  rcti r = rect_i;
1288  r.xmin = init_rect.xmax;
1289  r.xmax = r.xmin + size_x;
1290 #ifdef USE_ALIGN_Y_CENTER
1291  r.ymin = cent_overlap_y - (size_y / 2);
1292  r.ymax = r.ymin + size_y;
1293 #else
1294  r.ymin = init_rect.ymax - BLI_rcti_size_y(&rect_i);
1295  r.ymax = init_rect.ymax;
1296  r.ymin -= UI_POPUP_MARGIN;
1297  r.ymax -= UI_POPUP_MARGIN;
1298 #endif
1299  rect.xpos = r;
1300  }
1301  { /* xneg */
1302  rcti r = rect_i;
1303  r.xmin = init_rect.xmin - size_x;
1304  r.xmax = r.xmin + size_x;
1305 #ifdef USE_ALIGN_Y_CENTER
1306  r.ymin = cent_overlap_y - (size_y / 2);
1307  r.ymax = r.ymin + size_y;
1308 #else
1309  r.ymin = init_rect.ymax - BLI_rcti_size_y(&rect_i);
1310  r.ymax = init_rect.ymax;
1311  r.ymin -= UI_POPUP_MARGIN;
1312  r.ymax -= UI_POPUP_MARGIN;
1313 #endif
1314  rect.xneg = r;
1315  }
1316  { /* ypos */
1317  rcti r = rect_i;
1318  r.xmin = cent_overlap_x - (size_x / 2);
1319  r.xmax = r.xmin + size_x;
1320  r.ymin = init_rect.ymax;
1321  r.ymax = r.ymin + size_y;
1322  rect.ypos = r;
1323  }
1324  { /* yneg */
1325  rcti r = rect_i;
1326  r.xmin = cent_overlap_x - (size_x / 2);
1327  r.xmax = r.xmin + size_x;
1328  r.ymin = init_rect.ymin - size_y;
1329  r.ymax = r.ymin + size_y;
1330  rect.yneg = r;
1331  }
1332 
1333  bool found = false;
1334  for (int j = 0; j < 4; j++) {
1335  const rcti *r = (&rect.xpos) + j;
1336  if (BLI_rcti_inside_rcti(&rect_clamp, r)) {
1337  rect_i = *r;
1338  found = true;
1339  break;
1340  }
1341  }
1342  if (!found) {
1343  /* Fallback, we could pick the best fallback, for now just use xpos. */
1344  int offset_dummy[2];
1345  rect_i = rect.xpos;
1346  BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
1347  }
1348  }
1349  else {
1350  const int pad = max_ff(1.0f, U.pixelsize) * 5;
1351  const rcti rect_clamp = {
1352  .xmin = pad,
1353  .xmax = winx - pad,
1354  .ymin = pad + (UI_UNIT_Y * 2),
1355  .ymax = winy - pad,
1356  };
1357  int offset_dummy[2];
1358  BLI_rcti_clamp(&rect_i, &rect_clamp, offset_dummy);
1359  }
1360  }
1361 
1362 #undef USE_ALIGN_Y_CENTER
1363 
1364  /* add padding */
1365  BLI_rcti_resize(&rect_i, BLI_rcti_size_x(&rect_i) + pad_px, BLI_rcti_size_y(&rect_i) + pad_px);
1366 
1367  /* widget rect, in region coords */
1368  {
1369  /* Compensate for margin offset, visually this corrects the position. */
1370  const int margin = UI_POPUP_MARGIN;
1371  if (init_rect_overlap != NULL) {
1372  BLI_rcti_translate(&rect_i, margin, margin / 2);
1373  }
1374 
1375  data->bbox.xmin = margin;
1376  data->bbox.xmax = BLI_rcti_size_x(&rect_i) - margin;
1377  data->bbox.ymin = margin;
1378  data->bbox.ymax = BLI_rcti_size_y(&rect_i);
1379 
1380  /* region bigger for shadow */
1381  region->winrct.xmin = rect_i.xmin - margin;
1382  region->winrct.xmax = rect_i.xmax + margin;
1383  region->winrct.ymin = rect_i.ymin - margin;
1384  region->winrct.ymax = rect_i.ymax + margin;
1385  }
1386 
1387  /* adds subwindow */
1388  ED_region_floating_init(region);
1389 
1390  /* notify change and redraw */
1391  ED_region_tag_redraw(region);
1392 
1393  return region;
1394 }
1395 
1398 /* -------------------------------------------------------------------- */
1403  bContext *C, ARegion *butregion, uiBut *but, uiButExtraOpIcon *extra_icon, bool is_label)
1404 {
1405  wmWindow *win = CTX_wm_window(C);
1406  /* aspect values that shrink text are likely unreadable */
1407  const float aspect = min_ff(1.0f, but->block->aspect);
1408  float init_position[2];
1409 
1410  if (but->drawflag & UI_BUT_NO_TOOLTIP) {
1411  return NULL;
1412  }
1413  uiTooltipData *data = NULL;
1414 
1415  if (data == NULL) {
1416  data = ui_tooltip_data_from_tool(C, but, is_label);
1417  }
1418 
1419  if (data == NULL) {
1420  data = ui_tooltip_data_from_button_or_extra_icon(C, but, extra_icon);
1421  }
1422 
1423  if (data == NULL) {
1425  }
1426 
1427  if (data == NULL) {
1428  return NULL;
1429  }
1430 
1431  const bool is_no_overlap = UI_but_has_tooltip_label(but) || UI_but_is_tool(but);
1432  rcti init_rect;
1433  if (is_no_overlap) {
1434  rctf overlap_rect_fl;
1435  init_position[0] = BLI_rctf_cent_x(&but->rect);
1436  init_position[1] = BLI_rctf_cent_y(&but->rect);
1437  if (butregion) {
1438  ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
1439  ui_block_to_window_rctf(butregion, but->block, &overlap_rect_fl, &but->rect);
1440  }
1441  else {
1442  overlap_rect_fl = but->rect;
1443  }
1444  BLI_rcti_rctf_copy_round(&init_rect, &overlap_rect_fl);
1445  }
1446  else {
1447  init_position[0] = BLI_rctf_cent_x(&but->rect);
1448  init_position[1] = but->rect.ymin;
1449  if (butregion) {
1450  ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
1451  init_position[0] = win->eventstate->xy[0];
1452  }
1453  init_position[1] -= (UI_POPUP_MARGIN / 2);
1454  }
1455 
1457  C, data, init_position, is_no_overlap ? &init_rect : NULL, aspect);
1458 
1459  return region;
1460 }
1461 
1462 ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label)
1463 {
1464  return UI_tooltip_create_from_button_or_extra_icon(C, butregion, but, NULL, is_label);
1465 }
1466 
1468 {
1469  wmWindow *win = CTX_wm_window(C);
1470  const float aspect = 1.0f;
1471  float init_position[2] = {win->eventstate->xy[0], win->eventstate->xy[1]};
1472 
1474  if (data == NULL) {
1475  return NULL;
1476  }
1477 
1478  /* TODO(harley):
1479  * Julian preferred that the gizmo callback return the 3D bounding box
1480  * which we then project to 2D here. Would make a nice improvement.
1481  */
1482  if (gz->type->screen_bounds_get) {
1483  rcti bounds;
1484  if (gz->type->screen_bounds_get(C, gz, &bounds)) {
1485  init_position[0] = bounds.xmin;
1486  init_position[1] = bounds.ymin;
1487  }
1488  }
1489 
1490  return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect);
1491 }
1492 
1494  const uiSearchItemTooltipData *item_tooltip_data)
1495 {
1496  uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
1497 
1498  if (item_tooltip_data->description[0]) {
1500  &(uiTooltipFormat){
1501  .style = UI_TIP_STYLE_HEADER,
1502  .color_id = UI_TIP_LC_NORMAL,
1503  .is_pad = true,
1504  });
1505  field->text = BLI_strdup(item_tooltip_data->description);
1506  }
1507 
1508  if (item_tooltip_data->name && item_tooltip_data->name[0]) {
1510  &(uiTooltipFormat){
1511  .style = UI_TIP_STYLE_NORMAL,
1512  .color_id = UI_TIP_LC_VALUE,
1513  .is_pad = true,
1514  });
1515  field->text = BLI_strdup(item_tooltip_data->name);
1516  }
1517  if (item_tooltip_data->hint[0]) {
1519  &(uiTooltipFormat){
1520  .style = UI_TIP_STYLE_NORMAL,
1521  .color_id = UI_TIP_LC_NORMAL,
1522  .is_pad = true,
1523  });
1524  field->text = BLI_strdup(item_tooltip_data->hint);
1525  }
1526 
1527  if (data->fields_len == 0) {
1528  MEM_freeN(data);
1529  return NULL;
1530  }
1531  return data;
1532 }
1533 
1535  bContext *C,
1536  const ARegion *searchbox_region,
1537  const rcti *item_rect,
1538  const uiSearchItemTooltipData *item_tooltip_data)
1539 {
1541  if (data == NULL) {
1542  return NULL;
1543  }
1544 
1545  const float aspect = 1.0f;
1546  const wmWindow *win = CTX_wm_window(C);
1547  float init_position[2];
1548  init_position[0] = win->eventstate->xy[0];
1549  init_position[1] = item_rect->ymin + searchbox_region->winrct.ymin - (UI_POPUP_MARGIN / 2);
1550 
1551  return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect);
1552 }
1553 
1554 void UI_tooltip_free(bContext *C, bScreen *screen, ARegion *region)
1555 {
1556  ui_region_temp_remove(C, screen, region);
1557 }
1558 
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:733
const char * CTX_wm_operator_poll_msg_get(struct bContext *C, bool *r_free)
Definition: context.c:1057
struct SpaceLink * CTX_wm_space_data(const bContext *C)
Definition: context.c:743
void CTX_wm_operator_poll_msg_clear(struct bContext *C)
Definition: context.c:1030
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
ePaintMode BKE_paintmode_get_active_from_context(const struct bContext *C)
const struct EnumPropertyItem * BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode)
Definition: paint.c:382
ePaintMode
Definition: BKE_paint.h:67
const char * BKE_paint_get_tool_prop_id_from_paintmode(ePaintMode mode)
Definition: paint.c:412
@ BLF_WORD_WRAP
Definition: BLF_api.h:340
void BLF_disable(int fontid, int option)
Definition: blf.c:279
float BLF_width(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: blf.c:688
int blf_mono_font
Definition: blf.c:48
float BLF_width_ex(int fontid, const char *str, size_t str_len, struct ResultBLF *r_info) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
Definition: blf.c:675
void BLF_enable(int fontid, int option)
Definition: blf.c:270
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT
Definition: blf.c:722
void BLF_size(int fontid, float size, int dpi)
Definition: blf.c:363
void BLF_wordwrap(int fontid, int wrap_width)
Definition: blf.c:787
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition: math_color.c:49
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:232
MINLINE float rgb_to_grayscale(const float rgb[3])
void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
Definition: math_color.c:376
void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
Definition: math_color.c:391
MINLINE void copy_v3_v3(float r[3], const float a[3])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
Definition: BLI_rect.h:181
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
Definition: BLI_rect.h:177
void BLI_rcti_rctf_copy_round(struct rcti *dst, const struct rctf *src)
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition: rct.c:559
void BLI_rcti_resize(struct rcti *rect, int x, int y)
Definition: rct.c:599
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition: BLI_rect.h:173
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src)
bool BLI_rcti_inside_rcti(const rcti *rct_a, const rcti *rct_b)
Definition: rct.c:197
bool BLI_rcti_clamp(struct rcti *rect, const struct rcti *rect_bounds, int r_xy[2])
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition: BLI_rect.h:169
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:485
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define STRPREFIX(a, b)
#define ARRAY_SIZE(arr)
#define UNUSED_VARS(...)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define TIP_(msgid)
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
#define CTX_TIP_(context, msgid)
bool bool bool BPY_run_string_as_string_and_size(struct bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, char **r_value, size_t *r_value_size) ATTR_NONNULL(1
bool bool BPY_run_string_as_intptr(struct bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, intptr_t *r_value) ATTR_NONNULL(1
bool bool bool bool BPY_run_string_as_string(struct bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, char **r_value) ATTR_NONNULL(1
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define MAX_NAME
Definition: DNA_defs.h:48
@ RGN_TYPE_TEMPORARY
@ USER_TOOLTIPS_PYTHON
void ED_region_floating_init(struct ARegion *region)
Definition: area.c:2057
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define MEM_recallocN(vmemh, len)
@ PROP_FLOAT
Definition: RNA_types.h:61
@ PROP_UNIT_ROTATION
Definition: RNA_types.h:75
@ PROP_ENUM_FLAG
Definition: RNA_types.h:266
@ PROP_PASSWORD
Definition: RNA_types.h:136
#define C
Definition: RandGen.cpp:25
@ UI_BUT_NO_TOOLTIP
Definition: UI_interface.h:263
#define UI_UNIT_Y
@ UI_BUT_DISABLED
Definition: UI_interface.h:196
@ UI_BUT_DRIVEN
Definition: UI_interface.h:200
void UI_fontstyle_set(const struct uiFontStyle *fs)
struct PointerRNA * UI_but_operator_ptr_get(uiBut *but)
Definition: interface.cc:5908
struct PointerRNA * UI_but_extra_operator_icon_opptr_get(struct uiButExtraOpIcon *extra_icon)
Definition: interface.cc:1701
int UI_but_unit_type_get(const uiBut *but)
Definition: interface.cc:5939
const struct uiStyle * UI_style_get(void)
@ UI_STYLE_TEXT_LEFT
void UI_fontstyle_draw(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, size_t str_len, const uchar col[4], const struct uiFontStyleDraw_Params *fs_params)
@ BUT_GET_LABEL
@ BUT_GET_PROP_KEYMAP
@ BUT_GET_TIP
@ BUT_GET_RNAENUM_TIP
@ BUT_GET_RNASTRUCT_IDENTIFIER
@ BUT_GET_RNAENUM_LABEL
@ BUT_GET_RNAPROP_IDENTIFIER
@ BUT_GET_OP_KEYMAP
void UI_but_extra_icon_string_info_get(struct bContext *C, uiButExtraOpIcon *extra_icon,...) ATTR_SENTINEL(0)
Definition: interface.cc:6733
@ UI_BTYPE_TEXT
Definition: UI_interface.h:332
@ UI_BTYPE_ROW
Definition: UI_interface.h:331
@ UI_BTYPE_SEARCH_MENU
Definition: UI_interface.h:372
bool UI_but_is_tool(const uiBut *but)
void UI_but_string_info_get(struct bContext *C, uiBut *but,...) ATTR_SENTINEL(0)
Definition: interface.cc:6494
bool UI_but_has_tooltip_label(const uiBut *but)
struct wmOperatorType * UI_but_extra_operator_icon_optype_get(struct uiButExtraOpIcon *extra_icon)
Definition: interface.cc:1696
@ UI_BLOCK_SHOW_SHORTCUT_ALWAYS
Definition: UI_interface.h:160
wmOperatorCallContext
Definition: WM_types.h:199
@ WM_OP_INVOKE_REGION_WIN
Definition: WM_types.h:202
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:201
@ KM_SHIFT
Definition: WM_types.h:238
int pad[32 - sizeof(int)]
ATTR_WARN_UNUSED_RESULT const BMVert * v
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
#define str(s)
uint col
void ui_block_to_window_rctf(const ARegion *region, uiBlock *block, rctf *rct_dst, const rctf *rct_src)
Definition: interface.cc:170
bool ui_but_context_poll_operator_ex(bContext *C, const uiBut *but, const wmOperatorCallParams *optype_params)
Definition: interface.cc:1862
void ui_but_string_get(uiBut *but, char *str, const size_t maxlen)
Definition: interface.cc:2911
void ui_fontscale(float *points, float aspect)
Definition: interface.cc:2014
void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y)
Definition: interface.cc:142
bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
#define UI_POPUP_MARGIN
const struct uiWidgetColors * ui_tooltip_get_theme(void)
void ui_draw_tooltip_background(const struct uiStyle *style, uiBlock *block, rcti *rect)
#define UI_TIP_PADDING
#define TIP_BORDER_Y
#define UI_TIP_MAXWIDTH
static void rgb_tint(float col[3], float h, float h_strength, float v, float v_strength)
ARegion * UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz)
ARegion * UI_tooltip_create_from_search_item_generic(bContext *C, const ARegion *searchbox_region, const rcti *item_rect, const uiSearchItemTooltipData *item_tooltip_data)
static uiTooltipData * ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is_label)
void UI_tooltip_free(bContext *C, bScreen *screen, ARegion *region)
static uiTooltipData * ui_tooltip_data_from_button_or_extra_icon(bContext *C, uiBut *but, uiButExtraOpIcon *extra_icon)
#define UI_TIP_LC_MAX
static uiTooltipField * text_field_add_only(uiTooltipData *data)
#define UI_TIP_STR_MAX
#define TIP_BORDER_X
ARegion * UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but, bool is_label)
struct uiTooltipField uiTooltipField
static uiTooltipData * ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz)
static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *region)
static uiTooltipField * text_field_add(uiTooltipData *data, const uiTooltipFormat *format)
struct uiTooltipData uiTooltipData
struct uiTooltipFormat uiTooltipFormat
static uiTooltipData * ui_tooltip_data_from_search_item_tooltip_data(const uiSearchItemTooltipData *item_tooltip_data)
BLI_STATIC_ASSERT(UI_TIP_LC_MAX==UI_TIP_LC_ALERT+1, "invalid lc-max")
#define UI_TIP_PAD_FAC
ARegion * UI_tooltip_create_from_button_or_extra_icon(bContext *C, ARegion *butregion, uiBut *but, uiButExtraOpIcon *extra_icon, bool is_label)
static void ui_tooltip_region_free_cb(ARegion *region)
static ARegion * ui_tooltip_create_with_data(bContext *C, uiTooltipData *data, const float init_position[2], const rcti *init_rect_overlap, const float aspect)
static char * ui_tooltip_text_python_from_op(bContext *C, wmOperatorType *ot, PointerRNA *opptr)
void ui_region_temp_remove(bContext *C, bScreen *screen, ARegion *region)
ARegion * ui_region_temp_add(bScreen *screen)
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static void area(int d1, int d2, int e1, int e2, float weights[2])
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2767
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1080
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:5155
int RNA_enum_from_name(const EnumPropertyItem *item, const char *name)
Definition: rna_access.c:1725
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2954
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:4874
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
int RNA_property_flag(PropertyRNA *prop)
Definition: rna_access.c:1055
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1015
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
const char * RNA_property_ui_description(const PropertyRNA *prop)
Definition: rna_access.c:1885
char * RNA_path_full_struct_py(Main *bmain, const PointerRNA *ptr)
Definition: rna_path.cc:1217
char * RNA_path_full_property_py_ex(Main *bmain, const PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback)
Definition: rna_path.cc:1245
_W64 int intptr_t
Definition: stdint.h:118
void * regiondata
struct ARegionType * type
Definition: DNA_ID.h:368
struct Library * lib
Definition: DNA_ID.h:372
char filepath[1024]
Definition: DNA_ID.h:461
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
struct wmOperatorCallParams * optype_params
wmOperatorCallContext opcontext
eButType type
const char * disabled_info
uiBlock * block
uiButToolTipFunc tip_func
struct PointerRNA * opptr
struct wmOperatorType * optype
char drawstr[UI_MAX_DRAW_STR]
struct PropertyRNA * rnaprop
struct PointerRNA rnapoin
eFontStyle_Align align
char hint[UI_MAX_DRAW_STR]
char description[UI_MAX_DRAW_STR]
uiFontStyle widget
uiTooltipField * fields
struct uiTooltipField::@432 geom
uiTooltipFormat format
enum uiTooltipFormat::@431 color_id
enum uiTooltipFormat::@430 style
unsigned char inner[4]
unsigned char text[4]
int xy[2]
Definition: WM_types.h:682
PointerRNA ptr
struct wmOperatorType * type
PropertyRNA * prop
wmGizmoFnScreenBoundsGet screen_bounds_get
int target_property_defs_len
int highlight_part
const struct wmGizmoType * type
wmOperatorCallContext opcontext
Definition: WM_types.h:1010
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
const char * description
Definition: WM_types.h:893
struct wmEvent * eventstate
wmOperatorType * ot
Definition: wm_files.c:3479
struct wmGizmoOpElem * WM_gizmo_operator_get(wmGizmo *gz, int part_index)
Definition: wm_gizmo.c:195
wmGizmoProperty * WM_gizmo_target_property_array(wmGizmo *gz)
int WM_keymap_item_to_string(const wmKeyMapItem *kmi, const bool compact, char *result, const int result_len)
Definition: wm_keymap.c:1213
char * WM_key_event_operator_string(const bContext *C, const char *opname, wmOperatorCallContext opcontext, IDProperty *properties, const bool is_strict, char *result, const int result_len)
Definition: wm_keymap.c:1636
char * WM_operatortype_description_or_name(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *properties)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
bool WM_operator_pystring_abbreviate(char *str, int str_len_max)
Definition: wm_operators.c:272
char * WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, const bool macro_args, wmOperatorType *ot, PointerRNA *opptr)
Definition: wm_operators.c:192
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:661
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:783
void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
Definition: wm_operators.c:701
void wmOrtho2_region_pixelspace(const ARegion *region)
Definition: wm_subwindow.c:103
int WM_window_pixels_y(const wmWindow *win)
Definition: wm_window.c:2082
int WM_window_pixels_x(const wmWindow *win)
Definition: wm_window.c:2076