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