Blender V5.0
draw_manager_text.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include "BLI_math_color.h"
12#include "BLI_math_geom.h"
13#include "BLI_math_matrix.h"
14#include "BLI_math_matrix.hh"
15#include "BLI_math_rotation.h"
16#include "BLI_math_vector.h"
17#include "BLI_memiter.h"
18#include "BLI_rect.h"
19#include "BLI_string.h"
20
21#include "BKE_editmesh.hh"
22#include "BKE_editmesh_cache.hh"
23#include "BKE_global.hh"
24#include "BKE_mesh.hh"
25#include "BKE_mesh_types.hh"
26#include "BKE_mesh_wrapper.hh"
27#include "BKE_object.hh"
28#include "BKE_unit.hh"
29
30#include "DNA_mesh_types.h"
31#include "DNA_object_types.h"
32#include "DNA_scene_types.h"
33#include "DNA_screen_types.h"
34#include "DNA_userdef_types.h"
35#include "DNA_view3d_types.h"
36
37#include "GPU_matrix.hh"
38#include "GPU_state.hh"
39
40#include "ED_view3d.hh"
41
42#include "UI_interface.hh"
43#include "UI_resources.hh"
44
45#include "BLF_api.hh"
46#include "WM_api.hh"
47
48#include "draw_manager_text.hh"
50
51using blender::float3;
52using blender::Span;
53
55 float vec[3];
56 union {
58 int pack;
59 } col;
60 short sco[2];
61 short xoffs, yoffs;
62 short flag;
64 bool shadow;
66
67 /* str is allocated past the end */
68 char str[0];
69};
70
74
76{
78 dt->cache_strings = BLI_memiter_create(1 << 14); /* 16kb */
79 return dt;
80}
81
83{
84 if (dt == nullptr) {
85 return;
86 }
88 MEM_freeN(dt);
89}
90
92 const float co[3],
93 const char *str,
94 const int str_len,
95 short xoffs,
96 short yoffs,
97 short flag,
98 const uchar col[4],
99 const bool shadow,
100 const bool align_center)
101{
102 int alloc_len;
103 ViewCachedString *vos;
104
106 BLI_assert(str_len == strlen(str));
107 alloc_len = sizeof(void *);
108 }
109 else {
110 alloc_len = str_len + 1;
111 }
112
113 vos = static_cast<ViewCachedString *>(
114 BLI_memiter_alloc(dt->cache_strings, sizeof(ViewCachedString) + alloc_len));
115
116 copy_v3_v3(vos->vec, co);
117 copy_v4_v4_uchar(vos->col.ub, col);
118 vos->xoffs = xoffs;
119 vos->yoffs = yoffs;
120 vos->flag = flag;
121 vos->str_len = str_len;
122 vos->shadow = shadow;
123 vos->align_center = align_center;
124
125 /* allocate past the end */
127 memcpy(vos->str, &str, alloc_len);
128 }
129 else {
130 memcpy(vos->str, str, alloc_len);
131 }
132}
133
134static void drw_text_cache_draw_ex(const DRWTextStore *dt, const ARegion *region)
135{
136 ViewCachedString *vos;
138 int col_pack_prev = 0;
139
140 float original_proj[4][4];
141 GPU_matrix_projection_get(original_proj);
143
146
147 BLF_default_size(UI_style_get()->widget.points);
148 const int font_id = BLF_set_default();
149
150 float outline_dark_color[4] = {0, 0, 0, 0.8f};
151 float outline_light_color[4] = {1, 1, 1, 0.8f};
152 bool outline_is_dark = true;
153
155 while ((vos = static_cast<ViewCachedString *>(BLI_memiter_iter_step(&it)))) {
156 if (vos->sco[0] != IS_CLIPPED) {
157 if (col_pack_prev != vos->col.pack) {
158 BLF_color4ubv(font_id, vos->col.ub);
159 const uchar lightness = srgb_to_grayscale_byte(vos->col.ub);
160 outline_is_dark = lightness > 96;
161 col_pack_prev = vos->col.pack;
162 }
163
164 if (vos->align_center) {
165 /* Measure the size of the string, then offset to align to the vertex. */
166 float width, height;
167 BLF_width_and_height(font_id,
168 (vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) :
169 vos->str,
170 vos->str_len,
171 &width,
172 &height);
173 vos->xoffs -= short(width / 2.0f);
174 vos->yoffs -= short(height / 2.0f);
175 }
176
177 const int font_id = BLF_default();
178 if (vos->shadow) {
179 BLF_enable(font_id, BLF_SHADOW);
180 BLF_shadow(font_id,
182 outline_is_dark ? outline_dark_color : outline_light_color);
183 BLF_shadow_offset(font_id, 0, 0);
184 }
185 else {
186 BLF_disable(font_id, BLF_SHADOW);
187 }
188 BLF_draw_default(float(vos->sco[0] + vos->xoffs),
189 float(vos->sco[1] + vos->yoffs),
190 2.0f,
191 (vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) :
192 vos->str,
193 vos->str_len);
194 }
195 }
196
198 GPU_matrix_projection_set(original_proj);
199}
200
201void DRW_text_cache_draw(const DRWTextStore *dt, const ARegion *region, const View3D *v3d)
202{
203 ViewCachedString *vos;
204 if (v3d) {
205 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
206 int tot = 0;
207 /* project first and test */
210 while ((vos = static_cast<ViewCachedString *>(BLI_memiter_iter_step(&it)))) {
212 region,
213 (vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
214 (vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0,
215 vos->vec,
216 vos->sco,
219 {
220 tot++;
221 }
222 else {
223 vos->sco[0] = IS_CLIPPED;
224 }
225 }
226
227 if (tot) {
228 /* Disable clipping for text */
229 const bool rv3d_clipping_enabled = RV3D_CLIPPING_ENABLED(v3d, rv3d);
230 if (rv3d_clipping_enabled) {
232 }
233
234 drw_text_cache_draw_ex(dt, region);
235
236 if (rv3d_clipping_enabled) {
238 }
239 }
240 }
241 else {
242 /* project first */
245 const View2D *v2d = &region->v2d;
246 float viewmat[4][4];
247 rctf region_space = {0.0f, float(region->winx), 0.0f, float(region->winy)};
248 BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &region_space, viewmat);
249
250 while ((vos = static_cast<ViewCachedString *>(BLI_memiter_iter_step(&it)))) {
251 float p[3];
252 copy_v3_v3(p, vos->vec);
253 mul_m4_v3(viewmat, p);
254
255 vos->sco[0] = p[0];
256 vos->sco[1] = p[1];
257 }
258
259 drw_text_cache_draw_ex(dt, region);
260 }
261}
262
264 const View3D *v3d,
265 const Object *ob,
266 const UnitSettings &unit,
267 DRWTextStore *dt)
268{
269 /* Do not use ASCII when using non-default unit system, some unit chars are UTF8
270 * (micro, square, etc.). See #36090. */
271 const short txt_flag = DRW_TEXT_CACHE_GLOBALSPACE;
272 const Mesh *mesh = BKE_object_get_editmesh_eval_cage(ob);
273 if (!mesh) {
274 return;
275 }
276 const BMEditMesh *em = mesh->runtime->edit_mesh.get();
278 return;
279 }
280 char numstr[32]; /* Stores the measurement display text here */
281 const char *conv_float; /* Use a float conversion matching the grid size */
282 blender::uchar4 col = {0, 0, 0, 255}; /* color of the text to draw */
283 const float grid = unit.system ? unit.scale_length : v3d->grid;
284 const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0;
285 const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0;
286 blender::float4x4 clip_planes;
287 /* allow for displaying shape keys and deform mods */
288 BMIter iter;
289 const Span<float3> vert_positions = BKE_mesh_wrapper_vert_coords(mesh);
290 const bool use_coords = !vert_positions.is_empty();
291
292 /* when 2 or more edge-info options are enabled, space apart */
293 short edge_tex_count = 0;
295 edge_tex_count += 1;
296 }
298 edge_tex_count += 1;
299 }
301 edge_tex_count += 1;
302 }
303 const short edge_tex_sep = short((edge_tex_count - 1) * 5.0f * UI_SCALE_FAC);
304
305 /* Make the precision of the display value proportionate to the grid-size. */
306
307 if (grid <= 0.01f) {
308 conv_float = "%.6g";
309 }
310 else if (grid <= 0.1f) {
311 conv_float = "%.5g";
312 }
313 else if (grid <= 1.0f) {
314 conv_float = "%.4g";
315 }
316 else if (grid <= 10.0f) {
317 conv_float = "%.3g";
318 }
319 else {
320 conv_float = "%.2g";
321 }
322
323 if (v3d->overlay.edit_flag &
325 {
326 BoundBox bb;
327 const rcti rect = {0, region->winx, 0, region->winy};
328
329 ED_view3d_clipping_calc(&bb, clip_planes.ptr(), region, ob, &rect);
330 }
331
333 BMEdge *eed;
334
336
337 if (use_coords) {
339 }
340
341 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
342 /* draw selected edges, or edges next to selected verts while dragging */
344 (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
346 {
347 float3 v1, v2;
348 float3 v1_clip, v2_clip;
349
350 if (use_coords) {
351 v1 = vert_positions[BM_elem_index_get(eed->v1)];
352 v2 = vert_positions[BM_elem_index_get(eed->v2)];
353 }
354 else {
355 v1 = eed->v1->co;
356 v2 = eed->v2->co;
357 }
358
359 if (clip_segment_v3_plane_n(v1, v2, clip_planes.ptr(), 4, v1_clip, v2_clip)) {
360 const float3 co = blender::math::transform_point(ob->object_to_world(),
361 0.5 * (v1_clip + v2_clip));
362
363 if (do_global) {
364 v1 = ob->object_to_world().view<3, 3>() * v1;
365 v2 = ob->object_to_world().view<3, 3>() * v2;
366 }
367
368 const size_t numstr_len =
369 unit.system ?
371 numstr, sizeof(numstr), len_v3v3(v1, v2), 3, B_UNIT_LENGTH, unit, false) :
372 SNPRINTF_RLEN(numstr, conv_float, len_v3v3(v1, v2));
373
374 DRW_text_cache_add(dt, co, numstr, numstr_len, 0, edge_tex_sep, txt_flag, col);
375 }
376 }
377 }
378 }
379
381 const bool is_rad = (unit.system_rotation == USER_UNIT_ROT_RADIANS);
382 BMEdge *eed;
383
385
386 Span<float3> face_normals;
387 if (use_coords) {
389 /* TODO: This is not const correct for wrapper meshes, but it should be okay because
390 * every evaluated object gets its own evaluated cage mesh (they are not shared). */
391 face_normals = BKE_mesh_wrapper_face_normals(const_cast<Mesh *>(mesh));
392 }
393
394 BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
395 BMLoop *l_a, *l_b;
396 if (BM_edge_loop_pair(eed, &l_a, &l_b)) {
397 /* Draw selected edges, or edges next to selected verts while dragging. */
399 (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
401 /* Special case, this is useful to show when verts connected
402 * to this edge via a face are being transformed. */
405 BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) ||
407 {
408 float3 v1, v2;
409 float3 v1_clip, v2_clip;
410
411 if (use_coords) {
412 v1 = vert_positions[BM_elem_index_get(eed->v1)];
413 v2 = vert_positions[BM_elem_index_get(eed->v2)];
414 }
415 else {
416 v1 = eed->v1->co;
417 v2 = eed->v2->co;
418 }
419
420 if (clip_segment_v3_plane_n(v1, v2, clip_planes.ptr(), 4, v1_clip, v2_clip)) {
421 float3 no_a, no_b;
422
423 const float3 co = blender::math::transform_point(ob->object_to_world(),
424 0.5 * (v1_clip + v2_clip));
425
426 if (use_coords) {
427 no_a = face_normals[BM_elem_index_get(l_a->f)];
428 no_b = face_normals[BM_elem_index_get(l_b->f)];
429 }
430 else {
431 no_a = l_a->f->no;
432 no_b = l_b->f->no;
433 }
434
435 if (do_global) {
436 no_a = blender::math::normalize(ob->world_to_object().view<3, 3>() * no_a);
437 no_b = blender::math::normalize(ob->world_to_object().view<3, 3>() * no_b);
438 }
439
440 const float angle = angle_normalized_v3v3(no_a, no_b);
441
442 const size_t numstr_len = SNPRINTF_RLEN(numstr,
443 "%.3f%s",
444 (is_rad) ? angle : RAD2DEGF(angle),
445 (is_rad) ? "r" : BLI_STR_UTF8_DEGREE_SIGN);
446
447 DRW_text_cache_add(dt, co, numstr, numstr_len, 0, -edge_tex_sep, txt_flag, col);
448 }
449 }
450 }
451 }
452 }
453
455 /* would be nice to use BM_face_calc_area, but that is for 2d faces
456 * so instead add up tessellation triangle areas */
457
459
460 int i;
461 BMFace *f = nullptr;
462 /* Alternative to using `poly_to_tri_count(i, BM_elem_index_get(f->l_first))`
463 * without having to add an extra loop. */
464 int tri_index = 0;
465 BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, i) {
466 const int f_corner_tris_len = f->len - 2;
468 int n = 0;
469 float area = 0; /* area of the face */
470 float3 vmid(0.0f);
471 const std::array<BMLoop *, 3> *ltri_array = &em->looptris[tri_index];
472 for (int j = 0; j < f_corner_tris_len; j++) {
473 float3 v1, v2, v3;
474
475 if (use_coords) {
476 v1 = vert_positions[BM_elem_index_get(ltri_array[j][0]->v)];
477 v2 = vert_positions[BM_elem_index_get(ltri_array[j][1]->v)];
478 v3 = vert_positions[BM_elem_index_get(ltri_array[j][2]->v)];
479 }
480 else {
481 v1 = ltri_array[j][0]->v->co;
482 v2 = ltri_array[j][1]->v->co;
483 v3 = ltri_array[j][2]->v->co;
484 }
485
486 vmid += v1;
487 vmid += v2;
488 vmid += v3;
489 n += 3;
490
491 if (do_global) {
492 v1 = ob->object_to_world().view<3, 3>() * v1;
493 v2 = ob->object_to_world().view<3, 3>() * v2;
494 v3 = ob->object_to_world().view<3, 3>() * v3;
495 }
496
497 area += area_tri_v3(v1, v2, v3);
498 }
499
500 vmid *= 1.0f / float(n);
501 vmid = blender::math::transform_point(ob->object_to_world(), vmid);
502
503 const size_t numstr_len =
505 numstr, sizeof(numstr), area, 3, B_UNIT_AREA, unit, false) :
506 SNPRINTF_RLEN(numstr, conv_float, area);
507
508 DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, 0, txt_flag, col);
509 }
510 tri_index += f_corner_tris_len;
511 }
512 }
513
515 BMFace *efa;
516 const bool is_rad = (unit.system_rotation == USER_UNIT_ROT_RADIANS);
517
519
520 if (use_coords) {
522 }
523
524 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
525 const bool is_face_sel = BM_elem_flag_test_bool(efa, BM_ELEM_SELECT);
526
527 if (is_face_sel || do_moving) {
528 BMIter liter;
529 BMLoop *loop;
530 bool is_first = true;
531
532 BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
533 if (is_face_sel || (do_moving && (BM_elem_flag_test(loop->v, BM_ELEM_SELECT) ||
536 {
537 float3 v1, v2, v3;
538 float3 vmid;
539
540 /* lazy init center calc */
541 if (is_first) {
542 if (use_coords) {
543 BM_face_calc_center_bounds_vcos(em->bm, efa, vmid, vert_positions);
544 }
545 else {
547 }
548 is_first = false;
549 }
550 if (use_coords) {
551 v1 = vert_positions[BM_elem_index_get(loop->prev->v)];
552 v2 = vert_positions[BM_elem_index_get(loop->v)];
553 v3 = vert_positions[BM_elem_index_get(loop->next->v)];
554 }
555 else {
556 v1 = loop->prev->v->co;
557 v2 = loop->v->co;
558 v3 = loop->next->v->co;
559 }
560
561 const float3 v2_local = v2;
562
563 if (do_global) {
564 v1 = ob->object_to_world().view<3, 3>() * v1;
565 v2 = ob->object_to_world().view<3, 3>() * v2;
566 v3 = ob->object_to_world().view<3, 3>() * v3;
567 }
568
569 const float angle = angle_v3v3v3(v1, v2, v3);
570
571 const size_t numstr_len = SNPRINTF_RLEN(numstr,
572 "%.3f%s",
573 (is_rad) ? angle : RAD2DEGF(angle),
574 (is_rad) ? "r" : BLI_STR_UTF8_DEGREE_SIGN);
576 ob->object_to_world(), blender::math::interpolate(vmid, v2_local, 0.8f));
577 DRW_text_cache_add(dt, co, numstr, numstr_len, 0, 0, txt_flag, col);
578 }
579 }
580 }
581 }
582 }
583
584 /* This option is for mesh ops and addons debugging; only available in UI if Blender starts
585 * with
586 * --debug */
588 int i;
589
591
592 if (em->selectmode & SCE_SELECT_VERTEX) {
593 BMVert *v;
594
595 if (use_coords) {
597 }
598 BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) {
601 ob->object_to_world(), use_coords ? vert_positions[BM_elem_index_get(v)] : v->co);
602
603 const size_t numstr_len = SNPRINTF_RLEN(numstr, "%d", i);
604 DRW_text_cache_add(dt, co, numstr, numstr_len, 0, 0, txt_flag, col, true, false);
605 }
606 }
607 }
608
609 if (em->selectmode & SCE_SELECT_EDGE) {
610 BMEdge *eed;
611
612 const bool use_edge_tex_sep = (edge_tex_count == 2);
613 const bool use_edge_tex_len = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_LEN);
614
615 BM_ITER_MESH_INDEX (eed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
617 float3 v1, v2;
618 float3 v1_clip, v2_clip;
619
620 if (use_coords) {
621 v1 = vert_positions[BM_elem_index_get(eed->v1)];
622 v2 = vert_positions[BM_elem_index_get(eed->v2)];
623 }
624 else {
625 v1 = eed->v1->co;
626 v2 = eed->v2->co;
627 }
628
629 if (clip_segment_v3_plane_n(v1, v2, clip_planes.ptr(), 4, v1_clip, v2_clip)) {
630 const float3 co = blender::math::transform_point(ob->object_to_world(),
631 0.5 * (v1_clip + v2_clip));
632
633 const size_t numstr_len = SNPRINTF_RLEN(numstr, "%d", i);
635 dt,
636 co,
637 numstr,
638 numstr_len,
639 0,
640 (use_edge_tex_sep) ? (use_edge_tex_len) ? -edge_tex_sep : edge_tex_sep : 0,
641 txt_flag,
642 col,
643 true,
644 false);
645 }
646 }
647 }
648 }
649
650 if (em->selectmode & SCE_SELECT_FACE) {
651 BMFace *f;
652
653 if (use_coords) {
655 }
656
657 BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, i) {
659 float3 co;
660
661 if (use_coords) {
662 BM_face_calc_center_median_vcos(em->bm, f, co, vert_positions);
663 }
664 else {
666 }
667
668 co = blender::math::transform_point(ob->object_to_world(), co);
669
670 const size_t numstr_len = SNPRINTF_RLEN(numstr, "%d", i);
671 DRW_text_cache_add(dt, co, numstr, numstr_len, 0, 0, txt_flag, col, true, false);
672 }
673 }
674 }
675 }
676}
bool BKE_editmesh_eval_orig_map_available(const Mesh &mesh_eval, const Mesh *mesh_orig)
Definition editmesh.cc:67
@ G_TRANSFORM_EDIT
blender::Span< blender::float3 > BKE_mesh_wrapper_face_normals(Mesh *mesh)
blender::Span< blender::float3 > BKE_mesh_wrapper_vert_coords(const Mesh *mesh)
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_editmesh_eval_cage(const Object *object)
const Mesh * BKE_object_get_pre_modified_mesh(const Object *object)
@ B_UNIT_AREA
Definition BKE_unit.hh:138
@ B_UNIT_LENGTH
Definition BKE_unit.hh:137
size_t BKE_unit_value_as_string_scaled(char *str, int str_maxncpy, double value, int prec, int type, const UnitSettings &settings, bool pad)
Definition unit.cc:1895
int BLF_set_default()
void BLF_enable(int fontid, FontFlags flag)
Definition blf.cc:320
void BLF_shadow(int fontid, FontShadowType type, const float rgba[4]=nullptr)
Definition blf.cc:934
void BLF_width_and_height(int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL()
Definition blf.cc:789
void BLF_shadow_offset(int fontid, int x, int y)
Definition blf.cc:946
int BLF_default()
void BLF_default_size(float size)
void BLF_disable(int fontid, FontFlags flag)
Definition blf.cc:329
void BLF_color4ubv(int fontid, const unsigned char rgba[4])
Definition blf.cc:452
void BLF_draw_default(float x, float y, float z, const char *str, size_t str_len) ATTR_NONNULL()
@ BLF_SHADOW
Definition BLF_enums.hh:35
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE unsigned char srgb_to_grayscale_byte(const unsigned char rgb[3])
#define RAD2DEGF(_rad)
bool clip_segment_v3_plane_n(const float p1[3], const float p2[3], const float plane_array[][4], int plane_num, float r_p1[3], float r_p2[3])
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:100
void mul_m4_v3(const float M[4][4], float r[3])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
void BLI_memiter_destroy(BLI_memiter *mi) ATTR_NONNULL(1)
void * BLI_memiter_iter_step(BLI_memiter_handle *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
BLI_memiter * BLI_memiter_create(unsigned int chunk_size_min) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
void * BLI_memiter_alloc(BLI_memiter *mi, unsigned int elem_size) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
void BLI_memiter_iter_init(BLI_memiter *mi, BLI_memiter_handle *iter) ATTR_NONNULL(1
void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4])
Definition rct.cc:551
#define SNPRINTF_RLEN(dst, format,...)
Definition BLI_string.h:605
#define BLI_STR_UTF8_DEGREE_SIGN
unsigned char uchar
Object is a sort of wrapper for general info.
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
@ SCE_SELECT_EDGE
@ USER_UNIT_ROT_RADIANS
#define UI_SCALE_FAC
#define RV3D_CLIPPING_ENABLED(v3d, rv3d)
@ V3D_GLOBAL_STATS
@ V3D_OVERLAY_EDIT_INDICES
@ V3D_OVERLAY_EDIT_FACE_AREA
@ V3D_OVERLAY_EDIT_EDGE_ANG
@ V3D_OVERLAY_EDIT_FACE_ANG
@ V3D_OVERLAY_EDIT_EDGE_LEN
void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *region, const Object *ob, const rcti *rect)
@ V3D_PROJ_TEST_CLIP_NEAR
Definition ED_view3d.hh:282
@ V3D_PROJ_TEST_CLIP_WIN
Definition ED_view3d.hh:281
@ V3D_PROJ_TEST_CLIP_BB
Definition ED_view3d.hh:280
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:256
#define IS_CLIPPED
Definition ED_view3d.hh:252
eV3DProjStatus ED_view3d_project_short_ex(const ARegion *region, float perspmat[4][4], bool is_local, const float co[3], short r_co[2], eV3DProjTest flag)
void GPU_matrix_identity_set()
void GPU_matrix_push()
#define GPU_matrix_projection_get(x)
#define GPU_matrix_projection_set(x)
void GPU_matrix_pop()
void GPU_clip_distances(int distances_enabled)
Definition gpu_state.cc:124
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
Read Guarded memory(de)allocation.
const uiStyle * UI_style_get()
@ TH_DRAWEXTRA_EDGEANG
@ TH_DRAWEXTRA_FACEANG
@ TH_DRAWEXTRA_EDGELEN
@ TH_DRAWEXTRA_FACEAREA
@ TH_TEXT_HI
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
@ BM_ELEM_SELECT
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_test_bool(ele, hflag)
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_FACE
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
#define BM_FACE
#define BM_VERT
void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
void BM_face_calc_center_bounds_vcos(const BMesh *bm, const BMFace *f, float r_cent[3], const blender::Span< blender::float3 > vert_positions)
void BM_face_calc_center_median_vcos(const BMesh *bm, const BMFace *f, float r_cent[3], const blender::Span< blender::float3 > vert_positions)
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr bool is_empty() const
Definition BLI_span.hh:260
nullptr float
static void drw_text_cache_draw_ex(const DRWTextStore *dt, const ARegion *region)
void DRW_text_cache_add(DRWTextStore *dt, const float co[3], const char *str, const int str_len, short xoffs, short yoffs, short flag, const uchar col[4], const bool shadow, const bool align_center)
void DRW_text_cache_draw(const DRWTextStore *dt, const ARegion *region, const View3D *v3d)
DRWTextStore * DRW_text_cache_create()
void DRW_text_edit_mesh_measure_stats(const ARegion *region, const View3D *v3d, const Object *ob, const UnitSettings &unit, DRWTextStore *dt)
void DRW_text_cache_destroy(DRWTextStore *dt)
@ DRW_TEXT_CACHE_LOCALCLIP
@ DRW_TEXT_CACHE_GLOBALSPACE
@ DRW_TEXT_CACHE_STRING_PTR
#define str(s)
uint col
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
T interpolate(const T &a, const T &b, const FactorT &t)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 3 > float3
void * regiondata
BMVert * v1
BMVert * v2
short selectmode
blender::Array< std::array< BMLoop *, 3 > > looptris
float no[3]
struct BMVert * v
struct BMLoop * prev
struct BMFace * f
struct BMLoop * next
float co[3]
BLI_memiter * cache_strings
MeshRuntimeHandle * runtime
float persmat[4][4]
float persmatob[4][4]
View3DOverlay overlay
union ViewCachedString::@212360372223235011205204371145153043271204115255 col
const c_style_mat & ptr() const
i
Definition text_draw.cc:230
void wmOrtho2_region_pixelspace(const ARegion *region)
uint8_t flag
Definition wm_window.cc:145