Blender V4.5
cage2d_gizmo.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
15
16#include "MEM_guardedalloc.h"
17
18#include "BLI_dial_2d.h"
19#include "BLI_math_base_safe.h"
20#include "BLI_math_matrix.h"
21#include "BLI_math_rotation.h"
22#include "BLI_math_vector.h"
24#include "BLI_rect.h"
25
26#include "BKE_context.hh"
27
28#include "GPU_immediate.hh"
29#include "GPU_immediate_util.hh"
30#include "GPU_matrix.hh"
31#include "GPU_select.hh"
32#include "GPU_state.hh"
33
34#include "RNA_access.hh"
35#include "RNA_define.hh"
36
37#include "WM_api.hh"
38#include "WM_types.hh"
39
40#include "ED_gizmo_library.hh"
41#include "ED_screen.hh"
42
43/* own includes */
45
46#define GIZMO_MARGIN_OFFSET_SCALE 1.5f
47/* The same as in `draw_cache.cc`. */
48#define CIRCLE_RESOL 32
49
50static int gizmo_cage2d_transform_flag_get(const wmGizmo *gz);
51
52static void gizmo_calc_rect_view_scale(const wmGizmo *gz, float scale[2])
53{
54 float matrix_final_no_offset[4][4];
55 float x_axis[3], y_axis[3];
56 WM_gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset);
57 mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, gz->matrix_offset[0]);
58 mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, gz->matrix_offset[1]);
59
60 float len_x_axis = len_v3(x_axis);
61 float len_y_axis = len_v3(y_axis);
62
63 /* Set scale to zero if axis length is zero. */
64 scale[0] = safe_divide(1.0f, len_x_axis);
65 scale[1] = safe_divide(1.0f, len_y_axis);
66}
67
68static void gizmo_calc_rect_view_margin(const wmGizmo *gz, float margin[2])
69{
70 float handle_size;
71 handle_size = 0.15f;
72 handle_size *= gz->scale_final;
73 float scale_xy[2];
74 gizmo_calc_rect_view_scale(gz, scale_xy);
75
76 margin[0] = (handle_size * scale_xy[0]);
77 margin[1] = (handle_size * scale_xy[1]);
78}
79
80/* -------------------------------------------------------------------- */
85
86static void cage2d_draw_box_corners(const rctf *r,
87 const float margin[2],
88 const float color[3],
89 const float line_width)
90{
91 /* NOTE(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */
93
95 immUniformColor3fv(color);
96
97 float viewport[4];
99 immUniform2fv("viewportSize", &viewport[2]);
100
101 immUniform1f("lineWidth", line_width * U.pixelsize);
102
104
105 immVertex3f(pos, r->xmin, r->ymin + margin[1], 0.0f);
106 immVertex3f(pos, r->xmin, r->ymin, 0.0f);
107 immVertex3f(pos, r->xmin, r->ymin, 0.0f);
108 immVertex3f(pos, r->xmin + margin[0], r->ymin, 0.0f);
109
110 immVertex3f(pos, r->xmax, r->ymin + margin[1], 0.0f);
111 immVertex3f(pos, r->xmax, r->ymin, 0.0f);
112 immVertex3f(pos, r->xmax, r->ymin, 0.0f);
113 immVertex3f(pos, r->xmax - margin[0], r->ymin, 0.0f);
114
115 immVertex3f(pos, r->xmax, r->ymax - margin[1], 0.0f);
116 immVertex3f(pos, r->xmax, r->ymax, 0.0f);
117 immVertex3f(pos, r->xmax, r->ymax, 0.0f);
118 immVertex3f(pos, r->xmax - margin[0], r->ymax, 0.0f);
119
120 immVertex3f(pos, r->xmin, r->ymax - margin[1], 0.0f);
121 immVertex3f(pos, r->xmin, r->ymax, 0.0f);
122 immVertex3f(pos, r->xmin, r->ymax, 0.0f);
123 immVertex3f(pos, r->xmin + margin[0], r->ymax, 0.0f);
124
125 immEnd();
126
128}
129
130static void cage2d_draw_box_interaction(const float color[4],
131 const int highlighted,
132 const float size[2],
133 const float margin[2],
134 const float line_width,
135 const bool is_solid,
136 const int draw_options)
137{
138 /* 4 verts for translate, otherwise only 3 are used. */
139 float verts[4][2];
140 uint verts_len = 0;
141 GPUPrimType prim_type = GPU_PRIM_NONE;
142
143 switch (highlighted) {
145 rctf r;
146 r.xmin = -size[0];
147 r.xmax = -size[0] + margin[0];
148 r.ymin = -size[1] + margin[1];
149 r.ymax = size[1] - margin[1];
150
151 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
152 ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
153 verts_len = 2;
154 if (is_solid) {
155 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
156 ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
157 verts_len += 2;
158 prim_type = GPU_PRIM_TRI_FAN;
159 }
160 else {
161 prim_type = GPU_PRIM_LINE_STRIP;
162 }
163 break;
164 }
166 rctf r;
167 r.xmin = size[0] - margin[0];
168 r.xmax = size[0];
169 r.ymin = -size[1] + margin[1];
170 r.ymax = size[1] - margin[1];
171
172 ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
173 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
174 verts_len = 2;
175 if (is_solid) {
176 ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
177 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
178 verts_len += 2;
179 prim_type = GPU_PRIM_TRI_FAN;
180 }
181 else {
182 prim_type = GPU_PRIM_LINE_STRIP;
183 }
184 break;
185 }
187 rctf r;
188 r.xmin = -size[0] + margin[0];
189 r.xmax = size[0] - margin[0];
190 r.ymin = -size[1];
191 r.ymax = -size[1] + margin[1];
192
193 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
194 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
195 verts_len = 2;
196 if (is_solid) {
197 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
198 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
199 verts_len += 2;
200 prim_type = GPU_PRIM_TRI_FAN;
201 }
202 else {
203 prim_type = GPU_PRIM_LINE_STRIP;
204 }
205 break;
206 }
208 rctf r;
209 r.xmin = -size[0] + margin[0];
210 r.xmax = size[0] - margin[0];
211 r.ymin = size[1] - margin[1];
212 r.ymax = size[1];
213
214 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
215 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
216 verts_len = 2;
217 if (is_solid) {
218 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
219 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
220 verts_len += 2;
221 prim_type = GPU_PRIM_TRI_FAN;
222 }
223 else {
224 prim_type = GPU_PRIM_LINE_STRIP;
225 }
226 break;
227 }
229 rctf r;
230 r.xmin = -size[0];
231 r.xmax = -size[0] + margin[0];
232 r.ymin = -size[1];
233 r.ymax = -size[1] + margin[1];
234
235 ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
236 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
237 ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
238 verts_len = 3;
239 if (is_solid) {
240 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
241 verts_len += 1;
242 prim_type = GPU_PRIM_TRI_FAN;
243 }
244 else {
245 prim_type = GPU_PRIM_LINE_STRIP;
246 }
247 break;
248 }
250 rctf r;
251 r.xmin = -size[0];
252 r.xmax = -size[0] + margin[0];
253 r.ymin = size[1] - margin[1];
254 r.ymax = size[1];
255
256 ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymax);
257 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
258 ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymin);
259 verts_len = 3;
260 if (is_solid) {
261 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
262 verts_len += 1;
263 prim_type = GPU_PRIM_TRI_FAN;
264 }
265 else {
266 prim_type = GPU_PRIM_LINE_STRIP;
267 }
268 break;
269 }
271 rctf r;
272 r.xmin = size[0] - margin[0];
273 r.xmax = size[0];
274 r.ymin = -size[1];
275 r.ymax = -size[1] + margin[1];
276
277 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
278 ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
279 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
280 verts_len = 3;
281 if (is_solid) {
282 ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
283 verts_len += 1;
284 prim_type = GPU_PRIM_TRI_FAN;
285 }
286 else {
287 prim_type = GPU_PRIM_LINE_STRIP;
288 }
289 break;
290 }
292 rctf r;
293 r.xmin = size[0] - margin[0];
294 r.xmax = size[0];
295 r.ymin = size[1] - margin[1];
296 r.ymax = size[1];
297
298 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
299 ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymin);
300 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
301 verts_len = 3;
302 if (is_solid) {
303 ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymax);
304 verts_len += 1;
305 prim_type = GPU_PRIM_TRI_FAN;
306 }
307 else {
308 prim_type = GPU_PRIM_LINE_STRIP;
309 }
310 break;
311 }
313 const float rotate_pt[2] = {0.0f, size[1] + margin[1]};
314 rctf r_rotate{};
315 r_rotate.xmin = rotate_pt[0] - margin[0] / 2.0f;
316 r_rotate.xmax = rotate_pt[0] + margin[0] / 2.0f;
317 r_rotate.ymin = rotate_pt[1] - margin[1] / 2.0f;
318 r_rotate.ymax = rotate_pt[1] + margin[1] / 2.0f;
319
320 ARRAY_SET_ITEMS(verts[0], r_rotate.xmin, r_rotate.ymin);
321 ARRAY_SET_ITEMS(verts[1], r_rotate.xmin, r_rotate.ymax);
322 ARRAY_SET_ITEMS(verts[2], r_rotate.xmax, r_rotate.ymax);
323 ARRAY_SET_ITEMS(verts[3], r_rotate.xmax, r_rotate.ymin);
324
325 verts_len = 4;
326 if (is_solid) {
327 prim_type = GPU_PRIM_TRI_FAN;
328 }
329 else {
330 prim_type = GPU_PRIM_LINE_STRIP;
331 }
332 break;
333 }
334
337 ARRAY_SET_ITEMS(verts[0], -margin[0] / 2, -margin[1] / 2);
338 ARRAY_SET_ITEMS(verts[1], margin[0] / 2, margin[1] / 2);
339 ARRAY_SET_ITEMS(verts[2], -margin[0] / 2, margin[1] / 2);
340 ARRAY_SET_ITEMS(verts[3], margin[0] / 2, -margin[1] / 2);
341 verts_len = 4;
342 if (is_solid) {
343 prim_type = GPU_PRIM_TRI_FAN;
344 }
345 else {
346 prim_type = GPU_PRIM_LINES;
347 }
348 }
349 else {
350 /* Only used for 3D view selection, never displayed to the user. */
351 ARRAY_SET_ITEMS(verts[0], -size[0], -size[1]);
352 ARRAY_SET_ITEMS(verts[1], -size[0], size[1]);
353 ARRAY_SET_ITEMS(verts[2], size[0], size[1]);
354 ARRAY_SET_ITEMS(verts[3], size[0], -size[1]);
355 verts_len = 4;
356 if (is_solid) {
357 prim_type = GPU_PRIM_TRI_FAN;
358 }
359 else {
360 /* unreachable */
361 BLI_assert(0);
362 prim_type = GPU_PRIM_LINE_STRIP;
363 }
364 }
365 break;
366 default:
367 return;
368 }
369
370 BLI_assert(prim_type != GPU_PRIM_NONE);
371
373 struct {
374 uint pos, col;
375 } attr_id{};
379
380 {
381 if (is_solid) {
382
383 if (margin[0] == 0.0f && margin[1] == 0.0) {
384 prim_type = GPU_PRIM_POINTS;
385 }
386 else if (margin[0] == 0.0f || margin[1] == 0.0) {
387 prim_type = GPU_PRIM_LINE_STRIP;
388 }
389 else {
390 BLI_assert(ELEM(prim_type, GPU_PRIM_TRI_FAN));
391 }
392
393 immBegin(prim_type, verts_len);
394 immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
395 for (uint i = 0; i < verts_len; i++) {
397 }
398 immEnd();
399 }
400 else {
402
403 float viewport[4];
404 GPU_viewport_size_get_f(viewport);
405 immUniform2fv("viewportSize", &viewport[2]);
406
407 immUniform1f("lineWidth", (line_width * 3.0f) * U.pixelsize);
408
409 immBegin(prim_type, verts_len);
410 immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
411 for (uint i = 0; i < verts_len; i++) {
413 }
414 immEnd();
415
416 immUniform1f("lineWidth", line_width * U.pixelsize);
417
418 immBegin(prim_type, verts_len);
419 immAttr3fv(attr_id.col, color);
420 for (uint i = 0; i < verts_len; i++) {
422 }
423 immEnd();
424 }
425 }
426
428}
429
431
432/* -------------------------------------------------------------------- */
437
439 uint pos, float x, float y, float rad_x, float rad_y, bool solid)
440{
441 if (rad_x == 0 && rad_y == 0) {
443 immVertex2f(pos, x, y);
444 immEnd();
445 return;
446 }
447
448 if (rad_x == 0 || rad_y == 0) {
449 /* Do not draw anything if only on of the radii is zero. */
450 return;
451 }
452
453 if (solid) {
454 /* NOTE(Metal/AMD): Small Triangle-list primitives more optimal for GPU HW than Triangle-strip.
455 */
457 immVertex2f(pos, x - rad_x, y - rad_y);
458 immVertex2f(pos, x - rad_x, y + rad_y);
459 immVertex2f(pos, x + rad_x, y + rad_y);
460
461 immVertex2f(pos, x - rad_x, y - rad_y);
462 immVertex2f(pos, x + rad_x, y + rad_y);
463 immVertex2f(pos, x + rad_x, y - rad_y);
464 immEnd();
465 }
466 else {
467 /* NOTE(Metal/AMD): Small Line-list primitives more optimal for GPU HW than Line-strip. */
469 immVertex2f(pos, x - rad_x, y - rad_y);
470 immVertex2f(pos, x - rad_x, y + rad_y);
471
472 immVertex2f(pos, x - rad_x, y + rad_y);
473 immVertex2f(pos, x + rad_x, y + rad_y);
474
475 immVertex2f(pos, x + rad_x, y + rad_y);
476 immVertex2f(pos, x + rad_x, y - rad_y);
477
478 immVertex2f(pos, x + rad_x, y - rad_y);
479 immVertex2f(pos, x - rad_x, y - rad_y);
480 immEnd();
481 }
482}
483
484static void cage2d_draw_rect_wire(const rctf *r,
485 const float margin[2],
486 const float color[3],
487 const int transform_flag,
488 const int draw_options,
489 const float line_width)
490{
491 /* NOTE(Metal): Prefer using 3D coordinates with 3D shader input, even if rendering 2D gizmo's.
492 */
494
496 immUniformColor3fv(color);
497
498 float viewport[4];
499 GPU_viewport_size_get_f(viewport);
500 immUniform2fv("viewportSize", &viewport[2]);
501 immUniform1f("lineWidth", line_width * U.pixelsize);
502
503 /* Small 'lines' primitives more efficient for hardware processing than line-strip. */
505 immVertex3f(pos, r->xmin, r->ymin, 0.0f);
506 immVertex3f(pos, r->xmax, r->ymin, 0.0f);
507
508 immVertex3f(pos, r->xmax, r->ymin, 0.0f);
509 immVertex3f(pos, r->xmax, r->ymax, 0.0f);
510
511 immVertex3f(pos, r->xmax, r->ymax, 0.0f);
512 immVertex3f(pos, r->xmin, r->ymax, 0.0f);
513
514 immVertex3f(pos, r->xmin, r->ymax, 0.0f);
515 immVertex3f(pos, r->xmin, r->ymin, 0.0f);
516 immEnd();
517
518 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
520 immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax, 0.0f);
521 immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1], 0.0f);
522
523 immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1], 0.0f);
524 immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax, 0.0f);
525 immEnd();
526 }
527
528 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
530 const float rad[2] = {margin[0] / 2, margin[1] / 2};
531 const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)};
532
534 immVertex3f(pos, center[0] - rad[0], center[1] - rad[1], 0.0f);
535 immVertex3f(pos, center[0] + rad[0], center[1] + rad[1], 0.0f);
536 immVertex3f(pos, center[0] + rad[0], center[1] - rad[1], 0.0f);
537 immVertex3f(pos, center[0] - rad[0], center[1] + rad[1], 0.0f);
538 immEnd();
539 }
540 }
541
543}
544
545static void cage2d_draw_circle_wire(const float color[3],
546 const float size[2],
547 const float margin[2],
548 const int transform_flag,
549 const int draw_options,
550 const float line_width)
551{
553
554 const bool use_points = is_zero_v2(margin);
557 immUniformColor3fv(color);
558
559 if (use_points) {
560 /* Draw a central point. */
561 immUniform1f("size", 1.0 * U.pixelsize);
563 immVertex3f(pos, 0.0f, 0.0f, 0.0f);
564 immEnd();
565 }
566 else {
567 float viewport[4];
568 GPU_viewport_size_get_f(viewport);
569 immUniform2fv("viewportSize", &viewport[2]);
570 immUniform1f("lineWidth", line_width * U.pixelsize);
572 }
573
574 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
576 immVertex3f(pos, 0.0f, size[1], 0.0f);
577 immVertex3f(pos, 0.0f, size[1] + margin[1], 0.0f);
578
579 immVertex3f(pos, 0.0f, size[1] + margin[1], 0.0f);
580 immVertex3f(pos, 0.0f, size[1], 0.0f);
581 immEnd();
582 }
583
584 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
586 const float rad[2] = {margin[0] / 2, margin[1] / 2};
587 const float center[2] = {0.0f, 0.0f};
588
590 immVertex3f(pos, center[0] - rad[0], center[1] - rad[1], 0.0f);
591 immVertex3f(pos, center[0] + rad[0], center[1] + rad[1], 0.0f);
592 immVertex3f(pos, center[0] + rad[0], center[1] - rad[1], 0.0f);
593 immVertex3f(pos, center[0] - rad[0], center[1] + rad[1], 0.0f);
594 immEnd();
595 }
596 }
597
599}
600
609
611 const float margin[2],
612 const float color[3],
613 bool solid)
614{
616 void (*circle_fn)(uint, float, float, float, float, int) = (solid) ?
619 const int resolu = 12;
620 const float rad[2] = {margin[0] / 3, margin[1] / 3};
621
623 immUniformColor3fv(color);
624
625 const float handle[2] = {
627 r->ymax + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE),
628 };
629 circle_fn(pos, handle[0], handle[1], rad[0], rad[1], resolu);
630
632}
633
635 const float margin[2],
636 const float color[3],
637 bool solid)
638{
640 const float rad[2] = {margin[0] / 3, margin[1] / 3};
641
643 immUniformColor3fv(color);
644
645 /* should really divide by two, but looks too bulky. */
646 {
647 imm_draw_point_aspect_2d(pos, r->xmin, r->ymin, rad[0], rad[1], solid);
648 imm_draw_point_aspect_2d(pos, r->xmax, r->ymin, rad[0], rad[1], solid);
649 imm_draw_point_aspect_2d(pos, r->xmax, r->ymax, rad[0], rad[1], solid);
650 imm_draw_point_aspect_2d(pos, r->xmin, r->ymax, rad[0], rad[1], solid);
651 }
652
654}
655
657 const int highlighted,
658 const float size[2],
659 const float margin[2],
660 const float color[3],
661 bool solid)
662{
664
666 immUniformColor3fv(color);
667
668 switch (highlighted) {
671 const float rad[2] = {0.2f * margin[0], 0.4f * size[1]};
672 imm_draw_point_aspect_2d(pos, r->xmin, 0.0f, rad[0], rad[1], solid);
673 imm_draw_point_aspect_2d(pos, r->xmax, 0.0f, rad[0], rad[1], solid);
674 break;
675 }
678 const float rad[2] = {0.4f * size[0], 0.2f * margin[1]};
679 imm_draw_point_aspect_2d(pos, 0.0f, r->ymin, rad[0], rad[1], solid);
680 imm_draw_point_aspect_2d(pos, 0.0f, r->ymax, rad[0], rad[1], solid);
681 break;
682 }
683 }
684
686}
687
689
691 const bool select,
692 const bool highlight,
693 const int select_id)
694{
695 // const bool use_clamp = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
696 float dims[2];
697 RNA_float_get_array(gz->ptr, "dimensions", dims);
698 float matrix_final[4][4];
699
700 const int transform_flag = gizmo_cage2d_transform_flag_get(gz);
701 const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
702 const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
703
704 const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
705
706 WM_gizmo_calc_matrix_final(gz, matrix_final);
707
709 GPU_matrix_mul(matrix_final);
710
711 float margin[2];
712 gizmo_calc_rect_view_margin(gz, margin);
713
714 /* Handy for quick testing draw (if it's outside bounds). */
715 if (false) {
719 immUniformColor4f(1, 1, 1, 0.5f);
720 float s = 0.5f;
721 immRectf(pos, -s, -s, s, s);
724 }
725
726 if (select) {
727 /* Expand for hot-spot. */
728 const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
729 if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
730 /* Only scaling is needed for now. */
732
733 cage2d_draw_circle_wire(gz->color, size_real, margin, 0, draw_options, gz->line_width);
734 }
735 else {
736 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE) {
737 int scale_parts[] = {
742
747 };
748 for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) {
749 GPU_select_load_id(select_id | scale_parts[i]);
751 gz->color, scale_parts[i], size, margin, gz->line_width, true, draw_options);
752 }
753 }
754 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
755 const int transform_part = ED_GIZMO_CAGE2D_PART_TRANSLATE;
756 GPU_select_load_id(select_id | transform_part);
758 gz->color, transform_part, size, margin, gz->line_width, true, draw_options);
759 }
760 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
763 size_real,
764 margin,
765 gz->line_width,
766 true,
767 draw_options);
768 }
769 }
770 }
771 else {
772 rctf r;
773 r.xmin = -size_real[0];
774 r.ymin = -size_real[1];
775 r.xmax = size_real[0];
776 r.ymax = size_real[1];
777
778 if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
779 float color[4], black[3] = {0, 0, 0};
780 gizmo_color_get(gz, highlight, color);
781
782 /* corner gizmos */
783 cage2d_draw_box_corners(&r, margin, black, gz->line_width + 3.0f);
784
785 /* corner gizmos */
786 cage2d_draw_box_corners(&r, margin, color, gz->line_width);
787
788 bool show = false;
790 /* Only show if we're drawing the center handle
791 * otherwise the entire rectangle is the hot-spot. */
793 show = true;
794 }
795 }
796 else {
797 show = true;
798 }
799
800 if (show) {
802 gz->color, gz->highlight_part, size_real, margin, gz->line_width, false, draw_options);
803 }
804
805 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
808 size_real,
809 margin,
810 gz->line_width,
811 false,
812 draw_options);
813 }
814 }
815 else {
816 float color[4], black[3] = {0, 0, 0};
817 gizmo_color_get(gz, highlight, color);
818
820
821 float outline_line_width = gz->line_width + 3.0f;
822
823 if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX_TRANSFORM) {
824 cage2d_draw_rect_wire(&r, margin, black, transform_flag, draw_options, outline_line_width);
825 cage2d_draw_rect_wire(&r, margin, color, transform_flag, draw_options, gz->line_width);
826
827 /* Edge handles. */
828 cage2d_draw_rect_edge_handles(&r, gz->highlight_part, size_real, margin, color, true);
829 cage2d_draw_rect_edge_handles(&r, gz->highlight_part, size_real, margin, black, false);
830
831 /* Only draw corner handles when hovering over the corners. */
833 cage2d_draw_rect_corner_handles(&r, margin, color, true);
834 cage2d_draw_rect_corner_handles(&r, margin, black, false);
835 }
836
837 /* Rotate handles. */
838 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
839 cage2d_draw_rect_rotate_handle(&r, margin, color, true);
840 cage2d_draw_rect_rotate_handle(&r, margin, black, false);
841 }
842 }
843 else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
845 black, size_real, margin, transform_flag, draw_options, outline_line_width);
847 color, size_real, margin, transform_flag, draw_options, gz->line_width);
848
849 /* Edge handles. */
850 cage2d_draw_rect_edge_handles(&r, gz->highlight_part, size_real, margin, color, true);
851 cage2d_draw_rect_edge_handles(&r, gz->highlight_part, size_real, margin, black, false);
852
853 /* Draw corner handles. */
854 if (draw_options & ED_GIZMO_CAGE_DRAW_FLAG_CORNER_HANDLES) {
855 cage2d_draw_rect_corner_handles(&r, margin, color, true);
856 cage2d_draw_rect_corner_handles(&r, margin, black, false);
857 }
858
859 /* Rotation handles. */
860 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
861 cage2d_draw_rect_rotate_handle(&r, margin, color, true);
862 cage2d_draw_rect_rotate_handle(&r, margin, black, false);
863 }
864 }
865 else {
866 BLI_assert(0);
867 }
869 }
870 }
871
873}
874
878static void gizmo_cage2d_draw_select(const bContext * /*C*/, wmGizmo *gz, int select_id)
879{
880 gizmo_cage2d_draw_intern(gz, true, false, select_id);
881}
882
883static void gizmo_cage2d_draw(const bContext * /*C*/, wmGizmo *gz)
884{
885 const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
886 gizmo_cage2d_draw_intern(gz, false, is_highlight, -1);
887}
888
890{
891 int highlight_part = gz->highlight_part;
892
895 }
896
897 switch (highlight_part) {
906
907 /* TODO: diagonal cursor. */
915 return WM_CURSOR_CROSS;
916 default:
917 return WM_CURSOR_DEFAULT;
918 }
919}
920
921static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
922{
923 float point_local[2];
924 float dims[2];
925 RNA_float_get_array(gz->ptr, "dimensions", dims);
926 const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
927
928 if (gizmo_window_project_2d(C, gz, blender::float2(blender::int2(mval)), 2, true, point_local) ==
929 false)
930 {
931 return -1;
932 }
933
934 float margin[2];
935 gizmo_calc_rect_view_margin(gz, margin);
936
937 /* Expand for hots-pot. */
938 const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
939
940 const int transform_flag = gizmo_cage2d_transform_flag_get(gz);
941 const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
942
943 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
944 rctf r;
946 r.xmin = -margin[0] / 2;
947 r.ymin = -margin[1] / 2;
948 r.xmax = margin[0] / 2;
949 r.ymax = margin[1] / 2;
950 }
951 else {
952 r.xmin = -size[0] + margin[0];
953 r.ymin = -size[1] + margin[1];
954 r.xmax = size[0] - margin[0];
955 r.ymax = size[1] - margin[1];
956 if (!BLI_rctf_is_valid(&r)) {
957 /* Typically happens when gizmo width or height is very small. */
959 }
960 }
961 bool isect = BLI_rctf_isect_pt_v(&r, point_local);
962 if (isect) {
964 }
965 }
966
967 /* if gizmo does not have a scale intersection, don't do it */
969 rctf r_xmin{};
970 r_xmin.xmin = -size[0];
971 r_xmin.ymin = -size[1];
972 r_xmin.xmax = -size[0] + margin[0];
973 r_xmin.ymax = size[1];
974
975 rctf r_xmax{};
976 r_xmax.xmin = size[0] - margin[0];
977 r_xmax.ymin = -size[1];
978 r_xmax.xmax = size[0];
979 r_xmax.ymax = size[1];
980
981 rctf r_ymin{};
982 r_ymin.xmin = -size[0];
983 r_ymin.ymin = -size[1];
984 r_ymin.xmax = size[0];
985 r_ymin.ymax = -size[1] + margin[1];
986
987 rctf r_ymax{};
988 r_ymax.xmin = -size[0];
989 r_ymax.ymin = size[1] - margin[1];
990 r_ymax.xmax = size[0];
991 r_ymax.ymax = size[1];
992
993 const bool draw_corners = draw_options & ED_GIZMO_CAGE_DRAW_FLAG_CORNER_HANDLES;
994
995 if (BLI_rctf_isect_pt_v(&r_xmin, point_local)) {
996 if (draw_corners) {
997 if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
999 }
1000 if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
1002 }
1003 }
1005 }
1006 if (BLI_rctf_isect_pt_v(&r_xmax, point_local)) {
1007 if (draw_corners) {
1008 if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
1010 }
1011 if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
1013 }
1014 }
1016 }
1017 if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
1019 }
1020 if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
1022 }
1023 }
1024
1025 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
1026 /* Rotate:
1027 * (*) <-- hot spot is here!
1028 * +---+
1029 * | |
1030 * +---+ */
1031 const float r_rotate_pt[2] = {0.0f, size_real[1] + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE)};
1032 rctf r_rotate{};
1033 r_rotate.xmin = r_rotate_pt[0] - margin[0] / 2.0f;
1034 r_rotate.xmax = r_rotate_pt[0] + margin[0] / 2.0f;
1035 r_rotate.ymin = r_rotate_pt[1] - margin[1] / 2.0f;
1036 r_rotate.ymax = r_rotate_pt[1] + margin[1] / 2.0f;
1037
1038 if (BLI_rctf_isect_pt_v(&r_rotate, point_local)) {
1040 }
1041 }
1042
1043 return -1;
1044}
1045
1046namespace {
1047
1048struct RectTransformInteraction {
1049 float orig_mouse[2];
1050 float orig_matrix_offset[4][4];
1051 float orig_matrix_final_no_offset[4][4];
1052 Dial *dial;
1053 bool use_temp_uniform;
1054};
1055
1056} // namespace
1057
1059{
1060 RectTransformInteraction *data = static_cast<RectTransformInteraction *>(gz->interaction_data);
1061 int transform_flag = RNA_enum_get(gz->ptr, "transform");
1062 if (data) {
1063 if (data->use_temp_uniform) {
1065 }
1066 }
1067 return transform_flag;
1068}
1069
1074
1076{
1077 RectTransformInteraction *data = MEM_callocN<RectTransformInteraction>("cage_interaction");
1078
1079 copy_m4_m4(data->orig_matrix_offset, gz->matrix_offset);
1080 WM_gizmo_calc_matrix_final_no_offset(gz, data->orig_matrix_final_no_offset);
1081
1083 C, gz, blender::float2(blender::int2(event->mval)), 2, false, data->orig_mouse) == 0)
1084 {
1085 zero_v2(data->orig_mouse);
1086 }
1087
1088 gz->interaction_data = data;
1089
1091}
1092
1093static void gizmo_constrain_from_scale_part(int part, bool r_constrain_axis[2])
1094{
1095 r_constrain_axis[0] = (part > ED_GIZMO_CAGE2D_PART_SCALE_MAX_X &&
1097 true :
1098 false;
1099 r_constrain_axis[1] = (part > ED_GIZMO_CAGE2D_PART_SCALE &&
1101 true :
1102 false;
1103}
1104
1105static void gizmo_pivot_from_scale_part(int part, float r_pt[2])
1106{
1107 switch (part) {
1109 ARRAY_SET_ITEMS(r_pt, 0.0, 0.0);
1110 break;
1111 }
1113 ARRAY_SET_ITEMS(r_pt, 0.5, 0.0);
1114 break;
1115 }
1117 ARRAY_SET_ITEMS(r_pt, -0.5, 0.0);
1118 break;
1119 }
1121 ARRAY_SET_ITEMS(r_pt, 0.0, 0.5);
1122 break;
1123 }
1125 ARRAY_SET_ITEMS(r_pt, 0.0, -0.5);
1126 break;
1127 }
1129 ARRAY_SET_ITEMS(r_pt, 0.5, 0.5);
1130 break;
1131 }
1133 ARRAY_SET_ITEMS(r_pt, 0.5, -0.5);
1134 break;
1135 }
1137 ARRAY_SET_ITEMS(r_pt, -0.5, 0.5);
1138 break;
1139 }
1141 ARRAY_SET_ITEMS(r_pt, -0.5, -0.5);
1142 break;
1143 }
1144 default:
1145 BLI_assert(0);
1146 }
1147}
1148
1150 wmGizmo *gz,
1151 const wmEvent *event,
1152 eWM_GizmoFlagTweak /*tweak_flag*/)
1153{
1154 RectTransformInteraction *data = static_cast<RectTransformInteraction *>(gz->interaction_data);
1155 int transform_flag = RNA_enum_get(gz->ptr, "transform");
1156 if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) == 0) {
1157 /* WARNING: Checking the events modifier only makes sense as long as `tweak_flag`
1158 * remains unused (this controls #WM_GIZMO_TWEAK_PRECISE by default). */
1159 const bool use_temp_uniform = (event->modifier & KM_SHIFT) != 0;
1160 const bool changed = data->use_temp_uniform != use_temp_uniform;
1161 data->use_temp_uniform = use_temp_uniform;
1162 if (use_temp_uniform) {
1164 }
1165
1166 if (changed) {
1167 /* Always refresh. */
1168 }
1169 else if (event->type != MOUSEMOVE) {
1171 }
1172 }
1173
1174 float point_local[2];
1175
1176 float dims[2];
1177 RNA_float_get_array(gz->ptr, "dimensions", dims);
1178
1179 {
1180 float matrix_back[4][4];
1181 copy_m4_m4(matrix_back, gz->matrix_offset);
1182 copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
1183
1184 /* The mouse coords are projected into the matrix so we don't need to worry about axis
1185 * alignment. */
1186 bool ok = gizmo_window_project_2d(
1187 C, gz, blender::float2(blender::int2(event->mval)), 2, false, point_local);
1188 copy_m4_m4(gz->matrix_offset, matrix_back);
1189 if (!ok) {
1191 }
1192 }
1193
1194 wmGizmoProperty *gz_prop;
1195
1196 gz_prop = WM_gizmo_target_property_find(gz, "matrix");
1197 if (gz_prop->type != nullptr) {
1199 }
1200
1202 /* do this to prevent clamping from changing size */
1203 copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
1204 gz->matrix_offset[3][0] = data->orig_matrix_offset[3][0] +
1205 (point_local[0] - data->orig_mouse[0]);
1206 gz->matrix_offset[3][1] = data->orig_matrix_offset[3][1] +
1207 (point_local[1] - data->orig_mouse[1]);
1208 }
1210
1211#define MUL_V2_V3_M4_FINAL(test_co, mouse_co) \
1212 mul_v3_m4v3(test_co, data->orig_matrix_final_no_offset, blender::float3{UNPACK2(mouse_co), 0.0})
1213
1214 float test_co[3];
1215
1216 if (data->dial == nullptr) {
1217 MUL_V2_V3_M4_FINAL(test_co, data->orig_matrix_offset[3]);
1218
1219 data->dial = BLI_dial_init(test_co, FLT_EPSILON);
1220
1221 MUL_V2_V3_M4_FINAL(test_co, data->orig_mouse);
1222 BLI_dial_angle(data->dial, test_co);
1223 }
1224
1225 /* rotate */
1226 MUL_V2_V3_M4_FINAL(test_co, point_local);
1227 const float angle = BLI_dial_angle(data->dial, test_co);
1228
1229 float matrix_space_inv[4][4];
1230 float matrix_rotate[4][4];
1231 float pivot[3];
1232
1233 copy_v3_v3(pivot, data->orig_matrix_offset[3]);
1234
1235 invert_m4_m4(matrix_space_inv, gz->matrix_space);
1236
1237 unit_m4(matrix_rotate);
1238 mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv);
1239 rotate_m4(matrix_rotate, 'Z', -angle);
1240 mul_m4_m4m4(matrix_rotate, matrix_rotate, gz->matrix_space);
1241
1242 zero_v3(matrix_rotate[3]);
1243 transform_pivot_set_m4(matrix_rotate, pivot);
1244
1245 mul_m4_m4m4(gz->matrix_offset, matrix_rotate, data->orig_matrix_offset);
1246
1247#undef MUL_V2_V3_M4_FINAL
1248 }
1249 else {
1250 /* scale */
1251 copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
1252 const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
1253
1254 float pivot[2];
1255 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
1257 mul_v2_v2(pivot, dims);
1258 }
1259 else {
1260 zero_v2(pivot);
1261 }
1262
1263 float curr_mouse[2];
1264 copy_v2_v2(curr_mouse, data->orig_mouse);
1265
1266 /* Rotate current and original mouse coordinates around gizmo center. */
1267 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
1268 float rot[3][3];
1269 float loc[3];
1270 float size[3];
1272
1273 invert_m3(rot);
1274 sub_v2_v2(point_local, loc);
1275 mul_m3_v2(rot, point_local);
1276 add_v2_v2(point_local, loc);
1277
1278 sub_v2_v2(curr_mouse, loc);
1279 mul_m3_v2(rot, curr_mouse);
1280 add_v2_v2(curr_mouse, loc);
1281 }
1282
1283 bool constrain_axis[2] = {false};
1285
1286 float size_new[2], size_orig[2];
1287 for (int i = 0; i < 2; i++) {
1288 size_orig[i] = len_v3(data->orig_matrix_offset[i]);
1289 size_new[i] = size_orig[i];
1290 if (constrain_axis[i] == false) {
1291 /* Original cursor position relative to pivot. */
1292 const float delta_orig = curr_mouse[i] - data->orig_matrix_offset[3][i] -
1293 pivot[i] * size_orig[i];
1294 const float delta_curr = point_local[i] - data->orig_matrix_offset[3][i] -
1295 pivot[i] * size_orig[i];
1296
1297 if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED) == 0) {
1298 if (signum_i(delta_orig) != signum_i(delta_curr)) {
1299 size_new[i] = 0.0f;
1300 continue;
1301 }
1302 }
1303 /* Original cursor position does not exactly lie on the cage boundary due to margin. */
1304 size_new[i] = delta_curr / (signf(delta_orig) * 0.5f * dims[i] - pivot[i]);
1305 }
1306 }
1307
1308 float scale[2] = {1.0f, 1.0f};
1309 for (int i = 0; i < 2; i++) {
1310 if (size_orig[i] == 0) {
1311 size_orig[i] = 1.0f;
1312 gz->matrix_offset[i][i] = 1.0f;
1313 }
1314 scale[i] = size_new[i] / size_orig[i];
1315 }
1316
1317 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) {
1318 if (constrain_axis[0] == false && constrain_axis[1] == false) {
1319 if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
1320 /* So that the cursor lies on the circle. */
1321 scale[1] = scale[0] = len_v2(scale);
1322 }
1323 else {
1324 scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
1325 }
1326 }
1327 else if (constrain_axis[0] == false) {
1328 scale[1] = scale[0];
1329 }
1330 else if (constrain_axis[1] == false) {
1331 scale[0] = scale[1];
1332 }
1333 else {
1334 BLI_assert(0);
1335 }
1336 }
1337
1338 /* Scale around pivot. */
1339 float matrix_scale[4][4];
1340 unit_m4(matrix_scale);
1341
1342 mul_v3_fl(matrix_scale[0], scale[0]);
1343 mul_v3_fl(matrix_scale[1], scale[1]);
1344
1345 transform_pivot_set_m4(matrix_scale, blender::float3(UNPACK2(pivot), 0.0f));
1346 mul_m4_m4_post(gz->matrix_offset, matrix_scale);
1347 }
1348
1349 if (gz_prop->type != nullptr) {
1351 }
1352
1353 /* tag the region for redraw */
1356
1358}
1359
1361{
1362 if (STREQ(gz_prop->type->idname, "matrix")) {
1363 if (WM_gizmo_target_property_array_length(gz, gz_prop) == 16) {
1365 }
1366 else {
1367 BLI_assert(0);
1368 }
1369 }
1370 else {
1371 BLI_assert(0);
1372 }
1373}
1374
1375static void gizmo_cage2d_exit(bContext *C, wmGizmo *gz, const bool cancel)
1376{
1377 RectTransformInteraction *data = static_cast<RectTransformInteraction *>(gz->interaction_data);
1378
1379 if (data->dial) {
1380 BLI_dial_free(data->dial);
1381 data->dial = nullptr;
1382 }
1383
1384 if (!cancel) {
1385 return;
1386 }
1387
1388 wmGizmoProperty *gz_prop;
1389
1390 /* reset properties */
1391 gz_prop = WM_gizmo_target_property_find(gz, "matrix");
1392 if (gz_prop->type != nullptr) {
1393 WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &data->orig_matrix_offset[0][0]);
1394 }
1395
1396 copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
1397}
1398
1399/* -------------------------------------------------------------------- */
1402
1404{
1405 /* identifiers */
1406 gzt->idname = "GIZMO_GT_cage_2d";
1407
1408 /* API callbacks. */
1409 gzt->draw = gizmo_cage2d_draw;
1416 gzt->exit = gizmo_cage2d_exit;
1418
1419 gzt->struct_size = sizeof(wmGizmo);
1420
1421 /* rna */
1422 static const EnumPropertyItem rna_enum_draw_style[] = {
1423 {ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
1424 {ED_GIZMO_CAGE2D_STYLE_BOX_TRANSFORM, "BOX_TRANSFORM", 0, "Box Transform", ""},
1425 {ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
1426 {0, nullptr, 0, nullptr, nullptr},
1427 };
1428 static const EnumPropertyItem rna_enum_transform[] = {
1429 {ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
1430 {ED_GIZMO_CAGE_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""},
1431 {ED_GIZMO_CAGE_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
1432 {ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
1433 {0, nullptr, 0, nullptr, nullptr},
1434 };
1435 static const EnumPropertyItem rna_enum_draw_options[] = {
1436 {ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
1437 {ED_GIZMO_CAGE_DRAW_FLAG_CORNER_HANDLES, "CORNER_HANDLES", 0, "Corner Handles", ""},
1438 {0, nullptr, 0, nullptr, nullptr},
1439 };
1440 static const float unit_v2[2] = {1.0f, 1.0f};
1442 gzt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
1443 RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
1444 RNA_def_enum(gzt->srna,
1445 "draw_style",
1446 rna_enum_draw_style,
1448 "Draw Style",
1449 "");
1451 "draw_options",
1452 rna_enum_draw_options,
1454 "Draw Options",
1455 "");
1456
1457 WM_gizmotype_target_property_def(gzt, "matrix", PROP_FLOAT, 16);
1458}
1459
1464
wmWindow * CTX_wm_window(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
#define BLI_assert(a)
Definition BLI_assert.h:46
void BLI_dial_free(Dial *dial)
struct Dial Dial
Definition BLI_dial_2d.h:36
Dial * BLI_dial_init(const float start_position[2], float threshold)
float BLI_dial_angle(Dial *dial, const float current_position[2])
MINLINE float signf(float f)
MINLINE int signum_i(float a)
MINLINE float safe_divide(float a, float b)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void mul_m3_v2(const float m[3][3], float r[2])
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
void transform_pivot_set_m4(float mat[4][4], const float pivot[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void rotate_m4(float mat[4][4], char axis, float angle)
void mul_m4_m4_post(float R[4][4], const float B[4][4])
void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m3(float mat[3][3])
void unit_m4(float m[4][4])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void mul_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE bool is_zero_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void zero_v2(float r[2])
MINLINE void zero_v3(float r[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
bool BLI_rctf_is_valid(const struct rctf *rect)
bool BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2])
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
Definition BLI_rect.h:189
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
Definition BLI_rect.h:185
void BLI_rctf_sanitize(struct rctf *rect)
Definition rct.cc:434
unsigned int uint
#define UNPACK2(a)
#define ARRAY_SIZE(arr)
#define ARRAY_SET_ITEMS(...)
#define ELEM(...)
#define STREQ(a, b)
@ OPERATOR_RUNNING_MODAL
@ ED_GIZMO_CAGE_XFORM_FLAG_SCALE
@ ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE
@ ED_GIZMO_CAGE_XFORM_FLAG_ROTATE
@ ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM
@ ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED
@ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y
@ ED_GIZMO_CAGE2D_PART_TRANSLATE
@ ED_GIZMO_CAGE2D_PART_ROTATE
@ ED_GIZMO_CAGE2D_PART_SCALE
@ ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y
@ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y
@ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X
@ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y
@ ED_GIZMO_CAGE2D_PART_SCALE_MAX_X
@ ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y
@ ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y
@ ED_GIZMO_CAGE2D_STYLE_BOX_TRANSFORM
@ ED_GIZMO_CAGE2D_STYLE_BOX
@ ED_GIZMO_CAGE2D_STYLE_CIRCLE
@ ED_GIZMO_CAGE_DRAW_FLAG_CORNER_HANDLES
@ ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE
void ED_region_tag_redraw_editor_overlays(ARegion *region)
Definition area.cc:675
void immEnd()
void immUniform2fv(const char *name, const float data[2])
void immUnbindProgram()
void immUniformColor4f(float r, float g, float b, float a)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex3f(uint attr_id, float x, float y, float z)
void immVertex2fv(uint attr_id, const float data[2])
void immUniform1f(const char *name, float x)
GPUVertFormat * immVertexFormat()
void immAttr3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immAttr3f(uint attr_id, float x, float y, float z)
void immUniformColor3fv(const float rgb[3])
void imm_draw_circle_wire_aspect_3d(uint pos, float x, float y, float radius_x, float radius_y, int nsegments)
void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments)
void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
void GPU_matrix_push()
#define GPU_matrix_mul(x)
void GPU_matrix_pop()
GPUPrimType
@ GPU_PRIM_TRI_FAN
@ GPU_PRIM_NONE
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_PRIM_LINE_STRIP
@ GPU_PRIM_TRIS
bool GPU_select_load_id(unsigned int id)
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
@ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_3D_FLAT_COLOR
@ GPU_SHADER_3D_POLYLINE_FLAT_COLOR
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:273
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
Read Guarded memory(de)allocation.
@ PROP_FLOAT
Definition RNA_types.hh:152
#define C
Definition RandGen.cpp:29
eWM_GizmoFlagTweak
Gizmo tweak flag. Bit-flag passed to gizmo while tweaking.
@ WM_GIZMO_DRAW_NO_SCALE
@ WM_GIZMO_DRAW_MODAL
@ WM_GIZMOGROUPTYPE_3D
@ WM_GIZMO_STATE_HIGHLIGHT
@ KM_SHIFT
Definition WM_types.hh:275
#define U
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static void gizmo_calc_rect_view_margin(const wmGizmo *gz, float margin[2])
void ED_gizmotypes_cage_2d()
static void gizmo_constrain_from_scale_part(int part, bool r_constrain_axis[2])
static void GIZMO_GT_cage_2d(wmGizmoType *gzt)
#define GIZMO_MARGIN_OFFSET_SCALE
static void cage2d_draw_rect_edge_handles(const rctf *r, const int highlighted, const float size[2], const float margin[2], const float color[3], bool solid)
static int gizmo_cage2d_get_cursor(wmGizmo *gz)
static void cage2d_draw_box_interaction(const float color[4], const int highlighted, const float size[2], const float margin[2], const float line_width, const bool is_solid, const int draw_options)
static void cage2d_draw_box_corners(const rctf *r, const float margin[2], const float color[3], const float line_width)
static wmOperatorStatus gizmo_cage2d_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
static void cage2d_draw_rect_rotate_handle(const rctf *r, const float margin[2], const float color[3], bool solid)
static bool is_corner_highlighted(const int highlighted)
static void cage2d_draw_circle_wire(const float color[3], const float size[2], const float margin[2], const int transform_flag, const int draw_options, const float line_width)
static wmOperatorStatus gizmo_cage2d_modal(bContext *C, wmGizmo *gz, const wmEvent *event, eWM_GizmoFlagTweak)
static void cage2d_draw_rect_wire(const rctf *r, const float margin[2], const float color[3], const int transform_flag, const int draw_options, const float line_width)
static void gizmo_pivot_from_scale_part(int part, float r_pt[2])
static void gizmo_cage2d_draw(const bContext *, wmGizmo *gz)
static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
#define CIRCLE_RESOL
static void gizmo_calc_rect_view_scale(const wmGizmo *gz, float scale[2])
static void gizmo_cage2d_draw_select(const bContext *, wmGizmo *gz, int select_id)
static void imm_draw_point_aspect_2d(uint pos, float x, float y, float rad_x, float rad_y, bool solid)
#define MUL_V2_V3_M4_FINAL(test_co, mouse_co)
static void gizmo_cage2d_setup(wmGizmo *gz)
static void cage2d_draw_rect_corner_handles(const rctf *r, const float margin[2], const float color[3], bool solid)
static void gizmo_cage2d_exit(bContext *C, wmGizmo *gz, const bool cancel)
static void gizmo_cage2d_draw_intern(wmGizmo *gz, const bool select, const bool highlight, const int select_id)
static int gizmo_cage2d_transform_flag_get(const wmGizmo *gz)
static void gizmo_cage2d_property_update(wmGizmo *gz, wmGizmoProperty *gz_prop)
#define rot(x, k)
static float verts[][3]
void gizmo_color_get(const wmGizmo *gz, bool highlight, float r_color[4])
bool gizmo_window_project_2d(bContext *C, const wmGizmo *gz, const float mval[2], int axis, bool use_offset, float r_co[2])
uint pos
struct @064345207361167251075330302113175271221317160336::@201157344026354305110036153026103256267276205234 attr_id
uint col
#define select(A, B, C)
format
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum_flag(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
#define FLT_MAX
Definition stdcycles.h:14
float xmax
float xmin
float ymax
float ymin
wmEventType type
Definition WM_types.hh:754
int mval[2]
Definition WM_types.hh:760
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupType * type
const wmGizmoPropertyType * type
StructRNA * srna
wmGizmoFnDraw draw
wmGizmoFnModal modal
wmGizmoFnSetup setup
const char * idname
wmGizmoFnTestSelect test_select
wmGizmoFnExit exit
wmGizmoFnCursorGet cursor_get
wmGizmoFnInvoke invoke
wmGizmoFnDrawSelect draw_select
wmGizmoFnPropertyUpdate property_update
wmGizmoGroup * parent_gzgroup
void * interaction_data
eWM_GizmoFlagState state
float matrix_offset[4][4]
float scale_final
float color[4]
PointerRNA * ptr
float matrix_space[4][4]
float line_width
eWM_GizmoFlag flag
i
Definition text_draw.cc:230
@ WM_CURSOR_NSEW_SCROLL
Definition wm_cursors.hh:52
@ WM_CURSOR_CROSS
Definition wm_cursors.hh:26
@ WM_CURSOR_DEFAULT
Definition wm_cursors.hh:15
void WM_event_add_mousemove(wmWindow *win)
@ MOUSEMOVE
void WM_gizmo_calc_matrix_final(const wmGizmo *gz, float r_mat[4][4])
Definition wm_gizmo.cc:570
void WM_gizmo_calc_matrix_final_no_offset(const wmGizmo *gz, float r_mat[4][4])
Definition wm_gizmo.cc:557
void WM_gizmo_target_property_float_get_array(const wmGizmo *gz, wmGizmoProperty *gz_prop, float *value)
int WM_gizmo_target_property_array_length(const wmGizmo *, wmGizmoProperty *gz_prop)
void WM_gizmotype_target_property_def(wmGizmoType *gzt, const char *idname, int data_type, int array_length)
void WM_gizmo_target_property_float_set_array(bContext *C, const wmGizmo *gz, wmGizmoProperty *gz_prop, const float *value)
wmGizmoProperty * WM_gizmo_target_property_find(wmGizmo *gz, const char *idname)
void WM_gizmotype_append(void(*gtfunc)(wmGizmoType *))