Blender  V3.3
view3d_gizmo_ruler.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BLI_listbase.h"
8 #include "BLI_math.h"
9 #include "BLI_rect.h"
10 #include "BLI_string.h"
11 #include "BLI_utildefines.h"
12 
13 #include "BLT_translation.h"
14 
15 #include "BKE_context.h"
16 #include "BKE_gpencil.h"
17 #include "BKE_main.h"
18 #include "BKE_report.h"
19 
20 #include "BKE_material.h"
21 #include "BKE_object.h"
22 #include "BKE_scene.h"
23 #include "BKE_unit.h"
24 
25 #include "DNA_gpencil_types.h"
26 #include "DNA_meshdata_types.h"
27 #include "DNA_object_types.h"
28 #include "DNA_view3d_types.h"
29 
30 #include "ED_gizmo_library.h"
31 #include "ED_gizmo_utils.h"
32 #include "ED_gpencil.h"
33 #include "ED_screen.h"
34 #include "ED_transform.h"
36 #include "ED_view3d.h"
37 
38 #include "UI_interface.h"
39 #include "UI_resources.h"
40 
41 #include "MEM_guardedalloc.h"
42 
43 #include "RNA_access.h"
44 
45 #include "WM_api.h"
46 #include "WM_toolsystem.h"
47 #include "WM_types.h"
48 
49 #include "DEG_depsgraph_query.h"
50 
51 #include "view3d_intern.h" /* own include */
52 
53 #include "GPU_immediate.h"
54 #include "GPU_immediate_util.h"
55 #include "GPU_matrix.h"
56 #include "GPU_state.h"
57 
58 #include "BLF_api.h"
59 
64 #define USE_AXIS_CONSTRAINTS
65 
66 static const char *view3d_gzgt_ruler_id = "VIEW3D_GGT_ruler";
67 
68 #define MVAL_MAX_PX_DIST 12.0f
69 
70 /* -------------------------------------------------------------------- */
71 /* Ruler Item (we can have many) */
72 
73 enum {
75  RULERITEM_USE_ANGLE = (1 << 0),
78 };
79 
80 /* keep smaller than selection, since we may want click elsewhere without selecting a ruler */
81 #define RULER_PICK_DIST 12.0f
82 #define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST)
83 
84 /* not clicking on a point */
85 #define PART_LINE 0xff
86 
87 /* -------------------------------------------------------------------- */
88 /* Ruler Info (wmGizmoGroup customdata) */
89 
90 enum {
93 };
94 
95 #ifdef USE_AXIS_CONSTRAINTS
96 /* Constrain axes */
97 enum {
102 };
103 
108 enum {
112 };
113 #endif /* USE_AXIS_CONSTRAINTS */
114 
115 struct RulerItem;
116 
117 typedef struct RulerInfo {
119  int flag;
121  int state;
122 
123 #ifdef USE_AXIS_CONSTRAINTS
125 #endif
126 
127  /* wm state */
131  ARegion *region; /* re-assigned every modal update */
132 
133  /* Track changes in state. */
134  struct {
135 #ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
136  bool do_snap;
137 #endif
140 
141  struct {
145 
147 
148 /* -------------------------------------------------------------------- */
149 /* Ruler Item (two or three points) */
150 
151 typedef struct RulerItem {
153 
155  float co[3][3];
156 
157  int flag;
158  int raycast_dir; /* RULER_DIRECTION_* */
160 
161 typedef struct RulerInteraction {
162  /* selected coord */
163  char co_index; /* 0 -> 2 */
164  float drag_start_co[3];
166 
167 /* -------------------------------------------------------------------- */
172 {
173  /* could pass this as an arg */
174  const wmGizmoType *gzt_ruler = WM_gizmotype_find("VIEW3D_GT_ruler_item", true);
175  RulerItem *ruler_item = (RulerItem *)WM_gizmo_new_ptr(gzt_ruler, gzgroup, NULL);
176  WM_gizmo_set_flag(&ruler_item->gz, WM_GIZMO_DRAW_MODAL, true);
177  return ruler_item;
178 }
179 
180 static void ruler_item_remove(bContext *C, wmGizmoGroup *gzgroup, RulerItem *ruler_item)
181 {
182  RulerInfo *ruler_info = gzgroup->customdata;
183  if (ruler_info->item_active == ruler_item) {
184  ruler_info->item_active = NULL;
185  }
186  WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, &ruler_item->gz, C);
187 }
188 
190  RulerItem *ruler_item, UnitSettings *unit, char *numstr, size_t numstr_size, int prec)
191 {
192  if (ruler_item->flag & RULERITEM_USE_ANGLE) {
193  const float ruler_angle = angle_v3v3v3(
194  ruler_item->co[0], ruler_item->co[1], ruler_item->co[2]);
195 
196  if (unit->system == USER_UNIT_NONE) {
197  BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle));
198  }
199  else {
201  numstr, numstr_size, (double)ruler_angle, prec, B_UNIT_ROTATION, unit, false);
202  }
203  }
204  else {
205  const float ruler_len = len_v3v3(ruler_item->co[0], ruler_item->co[2]);
206 
207  if (unit->system == USER_UNIT_NONE) {
208  BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len);
209  }
210  else {
212  numstr_size,
213  (double)(ruler_len * unit->scale_length),
214  prec,
216  unit,
217  false);
218  }
219  }
220 }
221 
222 static bool view3d_ruler_pick(wmGizmoGroup *gzgroup,
223  RulerItem *ruler_item,
224  const float mval[2],
225  int *r_co_index)
226 {
227  RulerInfo *ruler_info = gzgroup->customdata;
228  ARegion *region = ruler_info->region;
229  bool found = false;
230 
231  float dist_best = RULER_PICK_DIST_SQ;
232  int co_index_best = -1;
233 
234  {
235  float co_ss[3][2];
236  float dist;
237  int j;
238 
239  /* should these be checked? - ok for now not to */
240  for (j = 0; j < 3; j++) {
241  ED_view3d_project_float_global(region, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
242  }
243 
244  if (ruler_item->flag & RULERITEM_USE_ANGLE) {
245  dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]),
246  dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2]));
247  if (dist < dist_best) {
248  dist_best = dist;
249  found = true;
250 
251  {
252  const float dist_points[3] = {
253  len_squared_v2v2(co_ss[0], mval),
254  len_squared_v2v2(co_ss[1], mval),
255  len_squared_v2v2(co_ss[2], mval),
256  };
257  if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) {
258  co_index_best = min_axis_v3(dist_points);
259  }
260  else {
261  co_index_best = -1;
262  }
263  }
264  }
265  }
266  else {
267  dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]);
268  if (dist < dist_best) {
269  dist_best = dist;
270  found = true;
271 
272  {
273  const float dist_points[2] = {
274  len_squared_v2v2(co_ss[0], mval),
275  len_squared_v2v2(co_ss[2], mval),
276  };
277  if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) {
278  co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2;
279  }
280  else {
281  co_index_best = -1;
282  }
283  }
284  }
285  }
286  }
287 
288  *r_co_index = co_index_best;
289  return found;
290 }
291 
296 static void ruler_state_set(RulerInfo *ruler_info, int state)
297 {
298  if (state == ruler_info->state) {
299  return;
300  }
301 
302  if (state == RULER_STATE_NORMAL) {
303  /* pass */
304  }
305  else if (state == RULER_STATE_DRAG) {
306  memset(&ruler_info->drag_state_prev, 0x0, sizeof(ruler_info->drag_state_prev));
307  }
308  else {
309  BLI_assert(0);
310  }
311 
312  ruler_info->state = state;
313 }
314 
315 static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3], const int xy[2])
316 {
317  ED_view3d_win_to_3d_int(ruler_info->area->spacedata.first, ruler_info->region, r_co, xy, r_co);
318 }
319 
324  struct Depsgraph *depsgraph,
325  RulerInfo *ruler_info,
326  RulerItem *ruler_item,
327  const int mval[2],
328  const bool do_thickness
330  ,
331  const bool do_snap
332 #endif
333 )
334 {
335  wmGizmo *snap_gizmo = ruler_info->snap_data.gizmo;
336  const float eps_bias = 0.0002f;
337  float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
338 
339  if (ruler_item) {
340  RulerInteraction *inter = ruler_item->gz.interaction_data;
341  float *co = ruler_item->co[inter->co_index];
342  /* restore the initial depth */
343  copy_v3_v3(co, inter->drag_start_co);
344  view3d_ruler_item_project(ruler_info, co, mval);
345  if (do_thickness && inter->co_index != 1) {
347  View3D *v3d = ruler_info->area->spacedata.first;
348  SnapObjectContext *snap_context = ED_gizmotypes_snap_3d_context_ensure(scene, snap_gizmo);
349  const float mval_fl[2] = {UNPACK2(mval)};
350  float ray_normal[3];
351  float ray_start[3];
352  float *co_other;
353 
354  co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
355 
357  depsgraph,
358  ruler_info->region,
359  v3d,
361  &(const struct SnapObjectParams){
362  .snap_target_select = SCE_SNAP_TARGET_ALL,
363  .edit_mode_type = SNAP_GEOM_CAGE,
364  },
365  NULL,
366  mval_fl,
367  NULL,
368  &dist_px,
369  co,
370  ray_normal)) {
371  negate_v3(ray_normal);
372  /* add some bias */
373  madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
375  depsgraph,
376  v3d,
377  &(const struct SnapObjectParams){
378  .snap_target_select = SCE_SNAP_TARGET_ALL,
379  .edit_mode_type = SNAP_GEOM_CAGE,
380  },
381  ray_start,
382  ray_normal,
383  NULL,
384  co_other,
385  NULL);
386  }
387  }
388  else
389 #ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
390  if (do_snap)
391 #endif
392  {
393  View3D *v3d = ruler_info->area->spacedata.first;
394  float *prev_point = NULL;
395 
396  if (inter->co_index != 1) {
397  if (ruler_item->flag & RULERITEM_USE_ANGLE) {
398  prev_point = ruler_item->co[1];
399  }
400  else if (inter->co_index == 0) {
401  prev_point = ruler_item->co[2];
402  }
403  else {
404  prev_point = ruler_item->co[0];
405  }
406  }
407  if (prev_point != NULL) {
409  snap_gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point);
410  }
411 
412  if (ED_gizmotypes_snap_3d_is_enabled(snap_gizmo)) {
413  ED_gizmotypes_snap_3d_data_get(C, snap_gizmo, co, NULL, NULL, NULL);
414  }
415 
416 #ifdef USE_AXIS_CONSTRAINTS
417  if (!(ruler_item->flag & RULERITEM_USE_ANGLE) &&
418  ruler_info->constrain_mode != CONSTRAIN_MODE_OFF) {
419 
422  RegionView3D *rv3d = ruler_info->region->regiondata;
423  Object *ob = OBACT(view_layer);
424  Object *obedit = OBEDIT_FROM_OBACT(ob);
425 
427 
428  if (ruler_info->constrain_mode == CONSTRAIN_MODE_2) {
429  orient_index = (orient_index == V3D_ORIENT_GLOBAL) ? V3D_ORIENT_LOCAL :
431  }
432 
433  const int pivot_point = scene->toolsettings->transform_pivot_point;
434  float mat[3][3];
435 
437  scene, view_layer, v3d, rv3d, ob, obedit, orient_index, pivot_point, mat);
438 
439  invert_m3(mat);
440  mul_m3_m3_pre(ruler_item->co, mat);
441 
442  /* Loop through the axes and constrain the dragged point to the current constrained axis.
443  */
444  for (int i = 0; i <= 2; i++) {
445  if (ruler_info->constrain_axis != i) {
446  ruler_item->co[inter->co_index][i] = ruler_item->co[(inter->co_index == 0) ? 2 : 0][i];
447  }
448  }
449  invert_m3(mat);
450  mul_m3_m3_pre(ruler_item->co, mat);
451  }
452 #endif
453  }
454  return true;
455  }
456  return false;
457 }
458 
467 static bool gizmo_ruler_check_for_operator(const wmGizmoGroup *gzgroup)
468 {
469  return gzgroup->customdata != NULL;
470 }
471 
474 /* -------------------------------------------------------------------- */
478 /* Helper: Find the layer created as ruler. */
480 {
481  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
482  if (gpl->flag & GP_LAYER_IS_RULER) {
483  return gpl;
484  }
485  }
486  return NULL;
487 }
488 
490 {
491 #ifndef NDEBUG
492  RulerInfo *ruler_info = gzgroup->customdata;
493  BLI_assert(gzgroup->gizmos.first == ruler_info->snap_data.gizmo);
494 #endif
495  return (RulerItem *)((wmGizmo *)gzgroup->gizmos.first)->next;
496 }
497 
498 #define RULER_ID "RulerData3D"
500 {
501  // RulerInfo *ruler_info = gzgroup->customdata;
502  Main *bmain = CTX_data_main(C);
504 
505  bGPdata *gpd;
506  bGPDlayer *gpl;
507  bGPDframe *gpf;
508  bGPDstroke *gps;
509  RulerItem *ruler_item;
510  const char *ruler_name = RULER_ID;
511  bool changed = false;
512 
513  if (scene->gpd == NULL) {
514  scene->gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
515  }
516  gpd = scene->gpd;
517 
518  gpl = view3d_ruler_layer_get(gpd);
519  if (gpl == NULL) {
520  gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false, false);
521  copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
522  gpl->thickness = 1;
524  }
525 
528 
529  for (ruler_item = gzgroup_ruler_item_first_get(gzgroup); ruler_item;
530  ruler_item = (RulerItem *)ruler_item->gz.next) {
531  bGPDspoint *pt;
532  int j;
533 
534  /* allocate memory for a new stroke */
535  gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
536  if (ruler_item->flag & RULERITEM_USE_ANGLE) {
537  gps->totpoints = 3;
538  pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
539  for (j = 0; j < 3; j++) {
540  copy_v3_v3(&pt->x, ruler_item->co[j]);
541  pt->pressure = 1.0f;
542  pt->strength = 1.0f;
543  pt++;
544  }
545  }
546  else {
547  gps->totpoints = 2;
548  pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
549  for (j = 0; j < 3; j += 2) {
550  copy_v3_v3(&pt->x, ruler_item->co[j]);
551  pt->pressure = 1.0f;
552  pt->strength = 1.0f;
553  pt++;
554  }
555  }
556  gps->flag = GP_STROKE_3DSPACE;
557  gps->thickness = 3;
558  gps->hardeness = 1.0f;
559  gps->fill_opacity_fac = 1.0f;
560  copy_v2_fl(gps->aspect_ratio, 1.0f);
561  gps->uv_scale = 1.0f;
562 
563  BLI_addtail(&gpf->strokes, gps);
564  changed = true;
565  }
566 
567  return changed;
568 }
569 
570 static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
571 {
573  bool changed = false;
574 
575  if (scene->gpd) {
576  bGPDlayer *gpl;
578  if (gpl) {
579  bGPDframe *gpf;
581  if (gpf) {
582  bGPDstroke *gps;
583  for (gps = gpf->strokes.first; gps; gps = gps->next) {
584  bGPDspoint *pt = gps->points;
585  int j;
586  RulerItem *ruler_item = NULL;
587  if (gps->totpoints == 3) {
588  ruler_item = ruler_item_add(gzgroup);
589  for (j = 0; j < 3; j++) {
590  copy_v3_v3(ruler_item->co[j], &pt->x);
591  pt++;
592  }
593  ruler_item->flag |= RULERITEM_USE_ANGLE;
594  changed = true;
595  }
596  else if (gps->totpoints == 2) {
597  ruler_item = ruler_item_add(gzgroup);
598  for (j = 0; j < 3; j += 2) {
599  copy_v3_v3(ruler_item->co[j], &pt->x);
600  pt++;
601  }
602  changed = true;
603  }
604  }
605  }
606  }
607  }
608 
609  return changed;
610 }
611 
614 /* -------------------------------------------------------------------- */
618 static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
619 {
621  UnitSettings *unit = &scene->unit;
622  RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
623  RulerItem *ruler_item = (RulerItem *)gz;
624  ARegion *region = ruler_info->region;
625  RegionView3D *rv3d = region->regiondata;
626  const float cap_size = 4.0f * U.dpi_fac;
627  const float bg_margin = 4.0f * U.dpi_fac;
628  const float arc_size = 64.0f * U.dpi_fac;
629 #define ARC_STEPS 24
630  const int arc_steps = ARC_STEPS;
631  const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f};
632  const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f};
633  uchar color_text[3];
634  uchar color_wire[3];
635  float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
636 
637  /* Pixel Space. */
639  GPU_matrix_push();
642 
643  /* anti-aliased lines for more consistent appearance */
644  GPU_line_smooth(true);
645  GPU_line_width(1.0f);
646 
648  BLF_size(blf_mono_font, 14.0f * U.pixelsize, U.dpi);
650 
651  UI_GetThemeColor3ubv(TH_TEXT, color_text);
652  UI_GetThemeColor3ubv(TH_WIRE, color_wire);
653 
654  /* Avoid white on white text. (TODO: Fix by using theme). */
655  if ((int)color_text[0] + (int)color_text[1] + (int)color_text[2] > 127 * 3 * 0.6f) {
656  copy_v3_fl(color_back, 0.0f);
657  }
658 
659  const bool is_act = (ruler_info->item_active == ruler_item);
660  float dir_ruler[2];
661  float co_ss[3][2];
662  bool proj_ok[3];
663  int j;
664 
665  /* Check if each corner is behind the near plane. If it is, we do not draw certain lines. */
666  for (j = 0; j < 3; j++) {
668  region, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_CLIP_NEAR);
669  proj_ok[j] = (status == V3D_PROJ_RET_OK);
670  }
671 
672  /* 3d drawing. */
673 
675  GPU_matrix_push();
677  GPU_matrix_set(rv3d->viewmat);
678 
680 
681  const uint shdr_pos_3d = GPU_vertformat_attr_add(
683 
684  if (ruler_item->flag & RULERITEM_USE_ANGLE) {
686 
687  float viewport_size[4];
688  GPU_viewport_size_get_f(viewport_size);
689  immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
690 
691  immUniform1i("colors_len", 2); /* "advanced" mode */
692  const float *col = is_act ? color_act : color_base;
693  immUniform4f("color", 0.67f, 0.67f, 0.67f, 1.0f);
694  immUniform4f("color2", col[0], col[1], col[2], col[3]);
695  immUniform1f("dash_width", 6.0f);
696  immUniform1f("dash_factor", 0.5f);
697 
699 
700  immVertex3fv(shdr_pos_3d, ruler_item->co[0]);
701  immVertex3fv(shdr_pos_3d, ruler_item->co[1]);
702  immVertex3fv(shdr_pos_3d, ruler_item->co[2]);
703 
704  immEnd();
705 
707 
709 
710  /* arc */
711  {
712  float dir_tmp[3];
713  float ar_coord[3];
714 
715  float dir_a[3];
716  float dir_b[3];
717  float quat[4];
718  float axis[3];
719  float angle;
720  const float px_scale = (ED_view3d_pixel_size_no_ui_scale(rv3d, ruler_item->co[1]) *
721  min_fff(arc_size,
722  len_v2v2(co_ss[0], co_ss[1]) / 2.0f,
723  len_v2v2(co_ss[2], co_ss[1]) / 2.0f));
724 
725  sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]);
726  sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]);
727  normalize_v3(dir_a);
728  normalize_v3(dir_b);
729 
730  cross_v3_v3v3(axis, dir_a, dir_b);
731  angle = angle_normalized_v3v3(dir_a, dir_b);
732 
733  axis_angle_to_quat(quat, axis, angle / arc_steps);
734 
735  copy_v3_v3(dir_tmp, dir_a);
736 
737  immUniformColor3ubv(color_wire);
738 
739  immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1);
740 
741  for (j = 0; j <= arc_steps; j++) {
742  madd_v3_v3v3fl(ar_coord, ruler_item->co[1], dir_tmp, px_scale);
743  mul_qt_v3(quat, dir_tmp);
744 
745  immVertex3fv(shdr_pos_3d, ar_coord);
746  }
747 
748  immEnd();
749  }
750 
752  }
753  else {
755 
756  float viewport_size[4];
757  GPU_viewport_size_get_f(viewport_size);
758  immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
759 
760  immUniform1i("colors_len", 2); /* "advanced" mode */
761  const float *col = is_act ? color_act : color_base;
762  immUniform4f("color", 0.67f, 0.67f, 0.67f, 1.0f);
763  immUniform4f("color2", col[0], col[1], col[2], col[3]);
764  immUniform1f("dash_width", 6.0f);
765  immUniform1f("dash_factor", 0.5f);
766 
768 
769  immVertex3fv(shdr_pos_3d, ruler_item->co[0]);
770  immVertex3fv(shdr_pos_3d, ruler_item->co[2]);
771 
772  immEnd();
773 
775  }
776 
777  /* 2d drawing. */
778 
779  GPU_matrix_pop();
781 
782  const uint shdr_pos_2d = GPU_vertformat_attr_add(
784 
785  if (ruler_item->flag & RULERITEM_USE_ANGLE) {
787  /* capping */
788  {
789  float rot_90_vec_a[2];
790  float rot_90_vec_b[2];
791  float cap[2];
792 
793  sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
794  rot_90_vec_a[0] = -dir_ruler[1];
795  rot_90_vec_a[1] = dir_ruler[0];
796  normalize_v2(rot_90_vec_a);
797 
798  sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]);
799  rot_90_vec_b[0] = -dir_ruler[1];
800  rot_90_vec_b[1] = dir_ruler[0];
801  normalize_v2(rot_90_vec_b);
802 
804 
805  if (proj_ok[1] && is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
806  GPU_line_width(3.0f);
807  immUniformColor3fv(color_act);
809  /* angle vertex */
810  immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
811  immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
812  immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
813  immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
814 
815  immEnd();
816  GPU_line_width(1.0f);
817  }
818 
819  immUniformColor3ubv(color_wire);
820 
821  if (proj_ok[0] || proj_ok[2] || proj_ok[1]) {
822  immBegin(GPU_PRIM_LINES, proj_ok[0] * 2 + proj_ok[2] * 2 + proj_ok[1] * 4);
823 
824  if (proj_ok[0]) {
825  madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
826  immVertex2fv(shdr_pos_2d, cap);
827  madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
828  immVertex2fv(shdr_pos_2d, cap);
829  }
830 
831  if (proj_ok[2]) {
832  madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
833  immVertex2fv(shdr_pos_2d, cap);
834  madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
835  immVertex2fv(shdr_pos_2d, cap);
836  }
837 
838  /* angle vertex */
839  if (proj_ok[1]) {
840  immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
841  immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
842  immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
843  immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
844  }
845 
846  immEnd();
847  }
848 
850  }
851 
852  /* text */
853  char numstr[256];
854  float numstr_size[2];
855  float posit[2];
856  const int prec = 2; /* XXX, todo, make optional */
857 
858  ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
859 
860  BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
861 
862  posit[0] = co_ss[1][0] + (cap_size * 2.0f);
863  posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
864 
865  /* draw text (bg) */
866  if (proj_ok[1]) {
867  immUniformColor4fv(color_back);
869  immRectf(shdr_pos_2d,
870  posit[0] - bg_margin,
871  posit[1] - bg_margin,
872  posit[0] + bg_margin + numstr_size[0],
873  posit[1] + bg_margin + numstr_size[1]);
875  }
876 
878 
879  /* draw text */
880  if (proj_ok[1]) {
881  BLF_color3ubv(blf_mono_font, color_text);
882  BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
884  BLF_draw(blf_mono_font, numstr, sizeof(numstr));
885  }
886  }
887  else {
889 
890  sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
891 
892  /* capping */
893  {
894  float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
895  float cap[2];
896 
897  normalize_v2(rot_90_vec);
898 
900 
901  immUniformColor3ubv(color_wire);
902 
903  if (proj_ok[0] || proj_ok[2]) {
904  immBegin(GPU_PRIM_LINES, proj_ok[0] * 2 + proj_ok[2] * 2);
905 
906  if (proj_ok[0]) {
907  madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
908  immVertex2fv(shdr_pos_2d, cap);
909  madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
910  immVertex2fv(shdr_pos_2d, cap);
911  }
912 
913  if (proj_ok[2]) {
914  madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
915  immVertex2fv(shdr_pos_2d, cap);
916  madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
917  immVertex2fv(shdr_pos_2d, cap);
918  }
919 
920  immEnd();
921  }
922 
924  }
925 
926  /* text */
927  char numstr[256];
928  float numstr_size[2];
929  const int prec = 6; /* XXX, todo, make optional */
930  float posit[2];
931 
932  ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
933 
934  BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]);
935 
936  mid_v2_v2v2(posit, co_ss[0], co_ss[2]);
937 
938  /* center text */
939  posit[0] -= numstr_size[0] / 2.0f;
940  posit[1] -= numstr_size[1] / 2.0f;
941 
942  /* draw text (bg) */
943  if (proj_ok[0] && proj_ok[2]) {
944  immUniformColor4fv(color_back);
946  immRectf(shdr_pos_2d,
947  posit[0] - bg_margin,
948  posit[1] - bg_margin,
949  posit[0] + bg_margin + numstr_size[0],
950  posit[1] + bg_margin + numstr_size[1]);
952  }
953 
955 
956  /* draw text */
957  if (proj_ok[0] && proj_ok[2]) {
958  BLF_color3ubv(blf_mono_font, color_text);
959  BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
960  BLF_draw(blf_mono_font, numstr, sizeof(numstr));
961  }
962  }
963 
964  GPU_line_smooth(false);
965 
967 
968  GPU_matrix_pop();
970 
971 #undef ARC_STEPS
972 }
973 
974 static int gizmo_ruler_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
975 {
976  RulerItem *ruler_item_pick = (RulerItem *)gz;
977  const float mval_fl[2] = {UNPACK2(mval)};
978  int co_index;
979 
980  /* select and drag */
981  if (view3d_ruler_pick(gz->parent_gzgroup, ruler_item_pick, mval_fl, &co_index)) {
982  if (co_index == -1) {
983  if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
984  return PART_LINE;
985  }
986  }
987  else {
988  return co_index;
989  }
990  }
991  return -1;
992 }
993 
995  wmGizmo *gz,
996  const wmEvent *event,
997  eWM_GizmoFlagTweak tweak_flag)
998 {
999  bool do_draw = false;
1000  int exit_code = OPERATOR_RUNNING_MODAL;
1001  RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
1002  RulerItem *ruler_item = (RulerItem *)gz;
1003  ARegion *region = CTX_wm_region(C);
1004  bool do_cursor_update = (event->val == KM_RELEASE) || (event->type == MOUSEMOVE);
1005 
1006  ruler_info->region = region;
1007 
1008 #ifdef USE_AXIS_CONSTRAINTS
1009  if ((event->val == KM_PRESS) && ELEM(event->type, EVT_XKEY, EVT_YKEY, EVT_ZKEY)) {
1010  /* Go to Mode 1 if a new axis is selected. */
1011  if (event->type == EVT_XKEY && ruler_info->constrain_axis != CONSTRAIN_AXIS_X) {
1012  ruler_info->constrain_axis = CONSTRAIN_AXIS_X;
1013  ruler_info->constrain_mode = CONSTRAIN_MODE_1;
1014  }
1015  else if (event->type == EVT_YKEY && ruler_info->constrain_axis != CONSTRAIN_AXIS_Y) {
1016  ruler_info->constrain_axis = CONSTRAIN_AXIS_Y;
1017  ruler_info->constrain_mode = CONSTRAIN_MODE_1;
1018  }
1019  else if (event->type == EVT_ZKEY && ruler_info->constrain_axis != CONSTRAIN_AXIS_Z) {
1020  ruler_info->constrain_axis = CONSTRAIN_AXIS_Z;
1021  ruler_info->constrain_mode = CONSTRAIN_MODE_1;
1022  }
1023  else {
1024  /* Cycle to the next mode if the same key is pressed again. */
1025  if (ruler_info->constrain_mode != CONSTRAIN_MODE_2) {
1026  ruler_info->constrain_mode++;
1027  }
1028  else {
1029  ruler_info->constrain_mode = CONSTRAIN_MODE_OFF;
1030  ruler_info->constrain_axis = CONSTRAIN_AXIS_NONE;
1031  }
1032  }
1033  do_cursor_update = true;
1034  }
1035 #endif
1036 
1037 #ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
1038  const bool do_snap = !(tweak_flag & WM_GIZMO_TWEAK_SNAP);
1039 #endif
1040  const bool do_thickness = tweak_flag & WM_GIZMO_TWEAK_PRECISE;
1041  if ((ruler_info->drag_state_prev.do_thickness != do_thickness)) {
1042  do_cursor_update = true;
1043  }
1044 
1045  if (do_cursor_update) {
1046  if (ruler_info->state == RULER_STATE_DRAG) {
1049  depsgraph,
1050  ruler_info,
1051  ruler_item,
1052  event->mval,
1053  do_thickness
1055  ,
1056  do_snap
1057 #endif
1058  )) {
1059  do_draw = true;
1060  }
1061  }
1062  }
1063 
1064  ruler_info->drag_state_prev.do_thickness = do_thickness;
1065 
1066  if (do_draw) {
1068  }
1069  return exit_code;
1070 }
1071 
1072 static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
1073 {
1074  wmGizmoGroup *gzgroup = gz->parent_gzgroup;
1075  RulerInfo *ruler_info = gzgroup->customdata;
1076  RulerItem *ruler_item_pick = (RulerItem *)gz;
1077  RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__);
1078  gz->interaction_data = inter;
1079 
1080  ARegion *region = ruler_info->region;
1081 
1082  float mval_fl[2];
1083  WM_event_drag_start_mval_fl(event, region, mval_fl);
1084 
1085 #ifdef USE_AXIS_CONSTRAINTS
1086  ruler_info->constrain_axis = CONSTRAIN_AXIS_NONE;
1087  ruler_info->constrain_mode = CONSTRAIN_MODE_OFF;
1088 #endif
1089 
1090  /* select and drag */
1091  if (gz->highlight_part == PART_LINE) {
1092  if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
1093  /* Add Center Point */
1094  ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
1095  inter->co_index = 1;
1096  ruler_state_set(ruler_info, RULER_STATE_DRAG);
1097 
1098  /* find the factor */
1099  {
1100  float co_ss[2][2];
1101  float fac;
1102 
1104  region, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP);
1106  region, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP);
1107 
1108  fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
1109  CLAMP(fac, 0.0f, 1.0f);
1110 
1112  ruler_item_pick->co[1], ruler_item_pick->co[0], ruler_item_pick->co[2], fac);
1113  }
1114 
1115  /* update the new location */
1118  depsgraph,
1119  ruler_info,
1120  ruler_item_pick,
1121  event->mval,
1122  false
1124  ,
1125  false
1126 #endif
1127  );
1128  }
1129  }
1130  else {
1131  inter->co_index = gz->highlight_part;
1132  ruler_state_set(ruler_info, RULER_STATE_DRAG);
1133 
1134  /* store the initial depth */
1135  copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]);
1136  }
1137 
1138  if (inter->co_index == 1) {
1139  ruler_item_pick->flag |= RULERITEM_USE_ANGLE_ACTIVE;
1140  }
1141  else {
1142  ruler_item_pick->flag &= ~RULERITEM_USE_ANGLE_ACTIVE;
1143  }
1144 
1145  {
1146  /* Set Snap prev point. */
1147  float *prev_point;
1148  if (ruler_item_pick->flag & RULERITEM_USE_ANGLE) {
1149  prev_point = (inter->co_index != 1) ? ruler_item_pick->co[1] : NULL;
1150  }
1151  else if (inter->co_index == 0) {
1152  prev_point = ruler_item_pick->co[2];
1153  }
1154  else {
1155  prev_point = ruler_item_pick->co[0];
1156  }
1157 
1158  if (prev_point) {
1160  ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point);
1161  }
1162  else {
1163  RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint);
1164  }
1165  }
1166 
1167  ruler_info->item_active = ruler_item_pick;
1168 
1169  return OPERATOR_RUNNING_MODAL;
1170 }
1171 
1172 static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
1173 {
1174  wmGizmoGroup *gzgroup = gz->parent_gzgroup;
1175  RulerInfo *ruler_info = gzgroup->customdata;
1176 
1177  if (!cancel) {
1178  if (ruler_info->state == RULER_STATE_DRAG) {
1179  RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint);
1180  ruler_state_set(ruler_info, RULER_STATE_NORMAL);
1181  }
1182  /* We could convert only the current gizmo, for now just re-generate. */
1183  view3d_ruler_to_gpencil(C, gzgroup);
1184  }
1185 
1187 
1188  ruler_state_set(ruler_info, RULER_STATE_NORMAL);
1189 }
1190 
1192 {
1193  if (gz->highlight_part == PART_LINE) {
1194  return WM_CURSOR_CROSS;
1195  }
1196  return WM_CURSOR_NSEW_SCROLL;
1197 }
1198 
1200 {
1201  /* identifiers */
1202  gzt->idname = "VIEW3D_GT_ruler_item";
1203 
1204  /* api callbacks */
1205  gzt->draw = gizmo_ruler_draw;
1207  gzt->modal = gizmo_ruler_modal;
1208  gzt->invoke = gizmo_ruler_invoke;
1209  gzt->exit = gizmo_ruler_exit;
1211 
1212  gzt->struct_size = sizeof(RulerItem);
1213 }
1214 
1217 /* -------------------------------------------------------------------- */
1221 static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup)
1222 {
1223  RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__);
1224 
1225  wmGizmo *gizmo;
1226  {
1227  /* The gizmo snap has to be the first gizmo. */
1228  const wmGizmoType *gzt_snap;
1229  gzt_snap = WM_gizmotype_find("GIZMO_GT_snap_3d", true);
1230  gizmo = WM_gizmo_new_ptr(gzt_snap, gzgroup, NULL);
1231 
1232  RNA_enum_set(gizmo->ptr, "snap_elements_force", SCE_SNAP_MODE_GEOM);
1234  WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
1235 
1236  wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_ruler_add", true);
1237  WM_gizmo_operator_set(gizmo, 0, ot, NULL);
1238  }
1239 
1240  if (view3d_ruler_from_gpencil(C, gzgroup)) {
1241  /* nop */
1242  }
1243 
1245  wmWindow *win = CTX_wm_window(C);
1246  ScrArea *area = CTX_wm_area(C);
1247  ARegion *region = CTX_wm_region(C);
1248 
1249  ruler_info->wm = wm;
1250  ruler_info->win = win;
1251  ruler_info->area = area;
1252  ruler_info->region = region;
1253  ruler_info->snap_data.gizmo = gizmo;
1254  ruler_info->snap_data.prop_prevpoint = RNA_struct_find_property(gizmo->ptr, "prev_point");
1255 
1256  gzgroup->customdata = ruler_info;
1257 }
1258 
1260 {
1261  gzgt->name = "Ruler Widgets";
1262  gzgt->idname = view3d_gzgt_ruler_id;
1263 
1265 
1268 
1271 }
1272 
1275 /* -------------------------------------------------------------------- */
1280 {
1282  if ((tref_rt == NULL) || !STREQ(view3d_gzgt_ruler_id, tref_rt->gizmo_group) ||
1283  CTX_wm_region_view3d(C) == NULL) {
1284  return false;
1285  }
1286  return true;
1287 }
1288 
1289 static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1290 {
1291  ARegion *region = CTX_wm_region(C);
1292  View3D *v3d = CTX_wm_view3d(C);
1293  RegionView3D *rv3d = region->regiondata;
1294 
1296  BKE_report(op->reports, RPT_WARNING, "Gizmos hidden in this view");
1297  return OPERATOR_CANCELLED;
1298  }
1299 
1300  wmGizmoMap *gzmap = region->gizmo_map;
1302  const bool use_depth = (v3d->shading.type >= OB_SOLID);
1303 
1304  if (!gizmo_ruler_check_for_operator(gzgroup)) {
1305  return OPERATOR_CANCELLED;
1306  }
1307 
1308  int mval[2];
1309  WM_event_drag_start_mval(event, region, mval);
1310 
1311  /* Create new line */
1312  RulerItem *ruler_item;
1313  ruler_item = ruler_item_add(gzgroup);
1314 
1315  /* This is a little weak, but there is no real good way to tweak directly. */
1316  WM_gizmo_highlight_set(gzmap, &ruler_item->gz);
1318  C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_REGION_WIN, NULL, event) ==
1320  RulerInfo *ruler_info = gzgroup->customdata;
1321  RulerInteraction *inter = ruler_item->gz.interaction_data;
1322  if (use_depth) {
1324  /* snap the first point added, not essential but handy */
1325  inter->co_index = 0;
1327  depsgraph,
1328  ruler_info,
1329  ruler_item,
1330  mval,
1331  false
1333  ,
1334  true
1335 #endif
1336  );
1337  copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]);
1339  ruler_info->snap_data.prop_prevpoint,
1340  inter->drag_start_co);
1341  }
1342  else {
1343  negate_v3_v3(inter->drag_start_co, rv3d->ofs);
1344  copy_v3_v3(ruler_item->co[0], inter->drag_start_co);
1345  view3d_ruler_item_project(ruler_info, ruler_item->co[0], mval);
1346  }
1347 
1348  copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
1349  ruler_item->gz.highlight_part = inter->co_index = 2;
1350  }
1351  return OPERATOR_FINISHED;
1352 }
1353 
1355 {
1356  /* identifiers */
1357  ot->name = "Ruler Add";
1358  ot->idname = "VIEW3D_OT_ruler_add";
1359  ot->description = "Add ruler";
1360 
1363 
1364  /* flags */
1366 }
1367 
1370 /* -------------------------------------------------------------------- */
1375 {
1376  ARegion *region = CTX_wm_region(C);
1377  View3D *v3d = CTX_wm_view3d(C);
1378 
1380  BKE_report(op->reports, RPT_WARNING, "Gizmos hidden in this view");
1381  return OPERATOR_CANCELLED;
1382  }
1383 
1384  wmGizmoMap *gzmap = region->gizmo_map;
1386  if (gzgroup) {
1387  if (!gizmo_ruler_check_for_operator(gzgroup)) {
1388  return OPERATOR_CANCELLED;
1389  }
1390  RulerInfo *ruler_info = gzgroup->customdata;
1391  if (ruler_info->item_active) {
1392  RulerItem *ruler_item = ruler_info->item_active;
1393  if ((ruler_item->flag & RULERITEM_USE_ANGLE) &&
1394  (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
1396  }
1397  else {
1398  ruler_item_remove(C, gzgroup, ruler_item);
1399  }
1400 
1401  /* Update the annotation layer. */
1402  view3d_ruler_to_gpencil(C, gzgroup);
1403 
1405  return OPERATOR_FINISHED;
1406  }
1407  }
1408  return OPERATOR_PASS_THROUGH;
1409 }
1410 
1412 {
1413  /* identifiers */
1414  ot->name = "Ruler Remove";
1415  ot->idname = "VIEW3D_OT_ruler_remove";
1416 
1419 
1420  /* flags */
1422 }
1423 
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:793
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
bool BKE_gpencil_free_strokes(struct bGPDframe *gpf)
Definition: gpencil.c:414
struct bGPDlayer * BKE_gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive, bool add_to_header)
Definition: gpencil.c:621
struct bGPDframe * BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
Definition: gpencil.c:1232
struct bGPdata * BKE_gpencil_data_addnew(struct Main *bmain, const char name[])
Definition: gpencil.c:705
@ GP_GETFRAME_ADD_NEW
Definition: BKE_gpencil.h:341
@ GP_GETFRAME_USE_PREV
Definition: BKE_gpencil.h:338
General operations, lookup, etc. for materials.
General operations, lookup, etc. for blender objects.
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
int BKE_scene_orientation_get_index(struct Scene *scene, int slot_index)
Definition: scene.cc:2470
@ B_UNIT_LENGTH
Definition: BKE_unit.h:101
@ B_UNIT_ROTATION
Definition: BKE_unit.h:105
size_t BKE_unit_value_as_string(char *str, int len_max, double value, int prec, int type, const struct UnitSettings *settings, bool pad)
@ BLF_ROTATION
Definition: BLF_api.h:334
void BLF_color3ubv(int fontid, const unsigned char rgb[3])
Definition: blf.c:407
void BLF_width_and_height(int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL()
Definition: blf.c:662
void BLF_disable(int fontid, int option)
Definition: blf.c:279
void BLF_rotation(int fontid, float angle)
Definition: blf.c:766
void BLF_draw(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2)
Definition: blf.c:538
int blf_mono_font
Definition: blf.c:48
void BLF_enable(int fontid, int option)
Definition: blf.c:270
void BLF_size(int fontid, float size, int dpi)
Definition: blf.c:363
void BLF_position(int fontid, float x, float y, float z)
Definition: blf.c:308
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
MINLINE float min_ff(float a, float b)
MINLINE float min_fff(float a, float b, float c)
float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:3274
MINLINE int min_axis_v3(const float vec[3])
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:283
void mul_m3_m3_pre(float R[3][3], const float A[3][3])
Definition: math_matrix.c:401
bool invert_m3(float R[3][3])
Definition: math_matrix.c:1171
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:59
#define RAD2DEGF(_rad)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
void mid_v2_v2v2(float r[2], const float a[2], const float b[2])
Definition: math_vector.c:244
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:361
MINLINE float normalize_v2(float r[2])
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:445
MINLINE void copy_v2_fl(float r[2], float f)
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK2(a)
#define UNUSED(x)
#define UNPACK3(a)
#define ELEM(...)
#define STREQ(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Scene * DEG_get_input_scene(const Depsgraph *graph)
struct ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
@ GP_STROKE_3DSPACE
@ GP_LAYER_IS_RULER
@ GP_LAYER_HIDE
@ OB_SOLID
Object is a sort of wrapper for general info.
#define OBEDIT_FROM_OBACT(ob)
@ SCE_SNAP_TARGET_ALL
#define USER_UNIT_NONE
#define OBACT(_view_layer)
@ SCE_ORIENT_DEFAULT
@ SCE_SNAP_MODE_FACE_RAYCAST
@ SCE_SNAP_MODE_GEOM
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
@ V3D_ORIENT_GLOBAL
@ V3D_ORIENT_LOCAL
@ V3D_GIZMO_HIDE_TOOL
@ V3D_GIZMO_HIDE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
bool ED_gizmo_poll_or_unlink_delayed_from_tool(const struct bContext *C, struct wmGizmoGroupType *gzgt)
void ED_region_tag_redraw_editor_overlays(struct ARegion *region)
Definition: area.c:690
short ED_transform_calc_orientation_from_type_ex(const struct Scene *scene, struct ViewLayer *view_layer, const struct View3D *v3d, const struct RegionView3D *rv3d, struct Object *ob, struct Object *obedit, short orientation_index, int pivot_point, float r_mat[3][3])
eSnapMode ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx, struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const eSnapMode snap_to, const struct SnapObjectParams *params, const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3])
bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx, struct Depsgraph *depsgraph, const View3D *v3d, const struct SnapObjectParams *params, const float ray_origin[3], const float ray_direction[3], float *ray_depth, float r_co[3], float r_no[3])
@ V3D_PROJ_TEST_CLIP_NEAR
Definition: ED_view3d.h:237
@ V3D_PROJ_TEST_NOP
Definition: ED_view3d.h:234
void ED_view3d_win_to_3d_int(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const int mval[2], float r_out[3])
#define USE_SNAP_DETECT_FROM_KEYMAP_HACK
Definition: ED_view3d.h:282
eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
eV3DProjStatus
Definition: ED_view3d.h:216
@ V3D_PROJ_RET_OK
Definition: ED_view3d.h:217
float ED_view3d_pixel_size_no_ui_scale(const struct RegionView3D *rv3d, const float co[3])
@ V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE
Definition: ED_view3d.h:288
void immUniform4f(const char *name, float x, float y, float z, float w)
void immUniform2f(const char *name, float x, float y)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex2fv(uint attr_id, const float data[2])
void immUniformColor3ubv(const unsigned char rgb[3])
void immUniform1i(const char *name, int x)
void immUniform1f(const char *name, float x)
void immUniformColor4fv(const float rgba[4])
GPUVertFormat * immVertexFormat(void)
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
void immUniformColor3fv(const float rgb[3])
void immRectf(uint pos, float x1, float y1, float x2, float y2)
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:126
void GPU_matrix_pop_projection(void)
Definition: gpu_matrix.cc:140
#define GPU_matrix_set(x)
Definition: GPU_matrix.h:225
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:119
#define GPU_matrix_projection_set(x)
Definition: GPU_matrix.h:226
void GPU_matrix_identity_set(void)
Definition: gpu_matrix.cc:168
void GPU_matrix_push_projection(void)
Definition: gpu_matrix.cc:133
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_LINE_STRIP
Definition: GPU_primitive.h:22
@ GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR
Definition: GPU_shader.h:350
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:201
@ GPU_SHADER_3D_UNIFORM_COLOR
Definition: GPU_shader.h:230
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
void GPU_line_width(float width)
Definition: gpu_state.cc:158
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:75
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:259
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define C
Definition: RandGen.cpp:25
@ TH_WIRE
Definition: UI_resources.h:69
@ TH_TEXT
Definition: UI_resources.h:42
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
Definition: resources.c:1323
eWM_GizmoFlagTweak
Gizmo tweak flag. Bit-flag passed to gizmo while tweaking.
@ WM_GIZMO_TWEAK_PRECISE
@ WM_GIZMO_TWEAK_SNAP
@ WM_GIZMO_DRAW_MODAL
@ WM_GIZMOGROUPTYPE_SCALE
@ WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL
@ WM_GIZMOGROUPTYPE_3D
@ KM_PRESS
Definition: WM_types.h:267
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_INTERNAL
Definition: WM_types.h:168
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ WM_OP_INVOKE_REGION_WIN
Definition: WM_types.h:202
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
Scene scene
const Depsgraph * depsgraph
uint col
const int state
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])
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
Definition: rna_access.c:2978
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5281
void ED_gizmotypes_snap_3d_flag_set(struct wmGizmo *gz, int flag)
Definition: snap3d_gizmo.c:64
bool ED_gizmotypes_snap_3d_is_enabled(const wmGizmo *UNUSED(gz))
Definition: snap3d_gizmo.c:88
SnapObjectContext * ED_gizmotypes_snap_3d_context_ensure(Scene *scene, wmGizmo *UNUSED(gz))
Definition: snap3d_gizmo.c:59
void ED_gizmotypes_snap_3d_data_get(const struct bContext *C, wmGizmo *gz, float r_loc[3], float r_nor[3], int r_elem_index[3], eSnapMode *r_snap_elem)
Definition: snap3d_gizmo.c:94
void * regiondata
struct wmGizmoMap * gizmo_map
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
float viewmat[4][4]
float winmat[4][4]
wmWindowManager * wm
ScrArea * area
wmGizmo * gizmo
ARegion * region
struct RulerInfo::@570 drag_state_prev
struct RulerItem * item_active
PropertyRNA * prop_prevpoint
wmWindow * win
struct RulerInfo::@571 snap_data
float co[3][3]
struct ToolSettings * toolsettings
struct bGPdata * gpd
struct RenderData r
struct UnitSettings unit
ListBase spacedata
char transform_pivot_point
char gizmo_flag
View3DShading shading
ListBase strokes
float color[4]
bGPDspoint * points
float fill_opacity_fac
float aspect_ratio[2]
struct bGPDstroke * next
ListBase layers
short val
Definition: WM_types.h:680
int mval[2]
Definition: WM_types.h:684
short type
Definition: WM_types.h:678
wmGizmoGroupFnInit setup
const char * idname
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
struct wmGizmoMapType_Params gzmap_params
const char * name
ListBase gizmos
struct wmGizmoMap * parent_gzmap
wmGizmoFnDraw draw
wmGizmoFnModal modal
const char * idname
wmGizmoFnTestSelect test_select
wmGizmoFnExit exit
wmGizmoFnCursorGet cursor_get
wmGizmoFnInvoke invoke
void * interaction_data
struct wmGizmoGroup * parent_gzgroup
int highlight_part
struct wmGizmo * next
struct PointerRNA * ptr
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
const char * description
Definition: WM_types.h:893
struct ReportList * reports
static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup)
@ CONSTRAIN_AXIS_Z
@ CONSTRAIN_AXIS_Y
@ CONSTRAIN_AXIS_NONE
@ CONSTRAIN_AXIS_X
static void ruler_item_remove(bContext *C, wmGizmoGroup *gzgroup, RulerItem *ruler_item)
@ RULERITEM_USE_ANGLE
@ RULERITEM_USE_ANGLE_ACTIVE
struct RulerInteraction RulerInteraction
static bGPDlayer * view3d_ruler_layer_get(bGPdata *gpd)
static bool gizmo_ruler_check_for_operator(const wmGizmoGroup *gzgroup)
static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static bool view3d_ruler_poll(bContext *C)
static void ruler_state_set(RulerInfo *ruler_info, int state)
static const char * view3d_gzgt_ruler_id
#define ARC_STEPS
void VIEW3D_OT_ruler_remove(wmOperatorType *ot)
static int view3d_ruler_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
void VIEW3D_GGT_ruler(wmGizmoGroupType *gzgt)
@ RULER_STATE_DRAG
@ RULER_STATE_NORMAL
static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
void VIEW3D_OT_ruler_add(wmOperatorType *ot)
static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit, char *numstr, size_t numstr_size, int prec)
static bool view3d_ruler_item_mousemove(const bContext *C, struct Depsgraph *depsgraph, RulerInfo *ruler_info, RulerItem *ruler_item, const int mval[2], const bool do_thickness)
static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup)
static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3], const int xy[2])
static RulerItem * gzgroup_ruler_item_first_get(wmGizmoGroup *gzgroup)
@ CONSTRAIN_MODE_1
@ CONSTRAIN_MODE_OFF
@ CONSTRAIN_MODE_2
static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
static RulerItem * ruler_item_add(wmGizmoGroup *gzgroup)
static int gizmo_ruler_cursor_get(wmGizmo *gz)
#define PART_LINE
static int gizmo_ruler_modal(bContext *C, wmGizmo *gz, const wmEvent *event, eWM_GizmoFlagTweak tweak_flag)
static int gizmo_ruler_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
#define RULER_ID
struct RulerItem RulerItem
static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
struct RulerInfo RulerInfo
static bool view3d_ruler_pick(wmGizmoGroup *gzgroup, RulerItem *ruler_item, const float mval[2], int *r_co_index)
void VIEW3D_GT_ruler_item(wmGizmoType *gzt)
#define RULER_PICK_DIST_SQ
#define MVAL_MAX_PX_DIST
@ WM_CURSOR_NSEW_SCROLL
Definition: wm_cursors.h:51
@ WM_CURSOR_CROSS
Definition: wm_cursors.h:26
int xy[2]
Definition: wm_draw.c:135
void WM_event_drag_start_mval_fl(const wmEvent *event, const ARegion *region, float r_mval[2])
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
int WM_operator_name_call(bContext *C, const char *opstring, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
@ EVT_YKEY
@ EVT_XKEY
@ MOUSEMOVE
@ EVT_ZKEY
wmOperatorType * ot
Definition: wm_files.c:3479
PointerRNA * WM_gizmo_operator_set(wmGizmo *gz, int part_index, wmOperatorType *ot, IDProperty *properties)
Definition: wm_gizmo.c:203
wmGizmo * WM_gizmo_new_ptr(const wmGizmoType *gzt, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition: wm_gizmo.c:81
bool WM_gizmo_highlight_set(wmGizmoMap *gzmap, wmGizmo *gz)
Definition: wm_gizmo.c:402
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition: wm_gizmo.c:304
void WM_gizmo_set_color(wmGizmo *gz, const float color[4])
Definition: wm_gizmo.c:328
void WM_gizmo_unlink(ListBase *gizmolist, wmGizmoMap *gzmap, wmGizmo *gz, bContext *C)
Definition: wm_gizmo.c:165
wmGizmoGroup * WM_gizmomap_group_find(struct wmGizmoMap *gzmap, const char *idname)
Definition: wm_gizmo_map.c:202
const wmGizmoType * WM_gizmotype_find(const char *idname, bool quiet)
Definition: wm_gizmo_type.c:45
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void wmOrtho2_region_pixelspace(const ARegion *region)
Definition: wm_subwindow.c:103
struct bToolRef_Runtime * WM_toolsystem_runtime_from_context(struct bContext *C)
Definition: wm_toolsystem.c:77