Blender V4.3
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"
22#include "BLI_rect.h"
23
24#include "BKE_context.hh"
25
26#include "GPU_immediate.hh"
27#include "GPU_immediate_util.hh"
28#include "GPU_matrix.hh"
29#include "GPU_select.hh"
30#include "GPU_shader.hh"
31#include "GPU_state.hh"
32
33#include "RNA_access.hh"
34#include "RNA_define.hh"
35
36#include "WM_api.hh"
37#include "WM_types.hh"
38
39#include "ED_gizmo_library.hh"
40#include "ED_screen.hh"
41
42/* own includes */
44
45#define GIZMO_MARGIN_OFFSET_SCALE 1.5f
46/* The same as in `draw_cache.cc`. */
47#define CIRCLE_RESOL 32
48
49static int gizmo_cage2d_transform_flag_get(const wmGizmo *gz);
50
51static void gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], float scale[2])
52{
53 float matrix_final_no_offset[4][4];
54 float asp[2] = {1.0f, 1.0f};
55 if (dims[0] > dims[1]) {
56 asp[0] = dims[1] / dims[0];
57 }
58 else {
59 asp[1] = dims[0] / dims[1];
60 }
61 float x_axis[3], y_axis[3];
62 WM_gizmo_calc_matrix_final_no_offset(gz, matrix_final_no_offset);
63 mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, gz->matrix_offset[0]);
64 mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, gz->matrix_offset[1]);
65
66 mul_v2_v2(x_axis, asp);
67 mul_v2_v2(y_axis, asp);
68
69 float len_x_axis = len_v3(x_axis);
70 float len_y_axis = len_v3(y_axis);
71
72 /* Set scale to zero if axis length is zero. */
73 scale[0] = safe_divide(1.0f, len_x_axis);
74 scale[1] = safe_divide(1.0f, len_y_axis);
75}
76
77static void gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[2], float margin[2])
78{
79 float handle_size;
80 handle_size = 0.15f;
81 handle_size *= gz->scale_final;
82 float scale_xy[2];
83 gizmo_calc_rect_view_scale(gz, dims, scale_xy);
84
85 margin[0] = (handle_size * scale_xy[0]);
86 margin[1] = (handle_size * scale_xy[1]);
87}
88
89/* -------------------------------------------------------------------- */
94
95static void cage2d_draw_box_corners(const rctf *r,
96 const float margin[2],
97 const float color[3],
98 const float line_width)
99{
100 /* NOTE(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */
102
105
106 float viewport[4];
107 GPU_viewport_size_get_f(viewport);
108 immUniform2fv("viewportSize", &viewport[2]);
109
110 immUniform1f("lineWidth", line_width * U.pixelsize);
111
113
114 immVertex3f(pos, r->xmin, r->ymin + margin[1], 0.0f);
115 immVertex3f(pos, r->xmin, r->ymin, 0.0f);
116 immVertex3f(pos, r->xmin, r->ymin, 0.0f);
117 immVertex3f(pos, r->xmin + margin[0], r->ymin, 0.0f);
118
119 immVertex3f(pos, r->xmax, r->ymin + margin[1], 0.0f);
120 immVertex3f(pos, r->xmax, r->ymin, 0.0f);
121 immVertex3f(pos, r->xmax, r->ymin, 0.0f);
122 immVertex3f(pos, r->xmax - margin[0], r->ymin, 0.0f);
123
124 immVertex3f(pos, r->xmax, r->ymax - margin[1], 0.0f);
125 immVertex3f(pos, r->xmax, r->ymax, 0.0f);
126 immVertex3f(pos, r->xmax, r->ymax, 0.0f);
127 immVertex3f(pos, r->xmax - margin[0], r->ymax, 0.0f);
128
129 immVertex3f(pos, r->xmin, r->ymax - margin[1], 0.0f);
130 immVertex3f(pos, r->xmin, r->ymax, 0.0f);
131 immVertex3f(pos, r->xmin, r->ymax, 0.0f);
132 immVertex3f(pos, r->xmin + margin[0], r->ymax, 0.0f);
133
134 immEnd();
135
137}
138
139static void cage2d_draw_box_interaction(const float color[4],
140 const int highlighted,
141 const float size[2],
142 const float margin[2],
143 const float line_width,
144 const bool is_solid,
145 const int draw_options)
146{
147 /* 4 verts for translate, otherwise only 3 are used. */
148 float verts[4][2];
149 uint verts_len = 0;
150 GPUPrimType prim_type = GPU_PRIM_NONE;
151
152 switch (highlighted) {
154 rctf r;
155 r.xmin = -size[0];
156 r.xmax = -size[0] + margin[0];
157 r.ymin = -size[1] + margin[1];
158 r.ymax = size[1] - margin[1];
159
160 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
161 ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
162 verts_len = 2;
163 if (is_solid) {
164 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
165 ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
166 verts_len += 2;
167 prim_type = GPU_PRIM_TRI_FAN;
168 }
169 else {
170 prim_type = GPU_PRIM_LINE_STRIP;
171 }
172 break;
173 }
175 rctf r;
176 r.xmin = size[0] - margin[0];
177 r.xmax = size[0];
178 r.ymin = -size[1] + margin[1];
179 r.ymax = size[1] - margin[1];
180
181 ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
182 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
183 verts_len = 2;
184 if (is_solid) {
185 ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
186 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
187 verts_len += 2;
188 prim_type = GPU_PRIM_TRI_FAN;
189 }
190 else {
191 prim_type = GPU_PRIM_LINE_STRIP;
192 }
193 break;
194 }
196 rctf r;
197 r.xmin = -size[0] + margin[0];
198 r.xmax = size[0] - margin[0];
199 r.ymin = -size[1];
200 r.ymax = -size[1] + margin[1];
201
202 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
203 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
204 verts_len = 2;
205 if (is_solid) {
206 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
207 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
208 verts_len += 2;
209 prim_type = GPU_PRIM_TRI_FAN;
210 }
211 else {
212 prim_type = GPU_PRIM_LINE_STRIP;
213 }
214 break;
215 }
217 rctf r;
218 r.xmin = -size[0] + margin[0];
219 r.xmax = size[0] - margin[0];
220 r.ymin = size[1] - margin[1];
221 r.ymax = size[1];
222
223 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
224 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
225 verts_len = 2;
226 if (is_solid) {
227 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
228 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
229 verts_len += 2;
230 prim_type = GPU_PRIM_TRI_FAN;
231 }
232 else {
233 prim_type = GPU_PRIM_LINE_STRIP;
234 }
235 break;
236 }
238 rctf r;
239 r.xmin = -size[0];
240 r.xmax = -size[0] + margin[0];
241 r.ymin = -size[1];
242 r.ymax = -size[1] + margin[1];
243
244 ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
245 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
246 ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
247 verts_len = 3;
248 if (is_solid) {
249 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
250 verts_len += 1;
251 prim_type = GPU_PRIM_TRI_FAN;
252 }
253 else {
254 prim_type = GPU_PRIM_LINE_STRIP;
255 }
256 break;
257 }
259 rctf r;
260 r.xmin = -size[0];
261 r.xmax = -size[0] + margin[0];
262 r.ymin = size[1] - margin[1];
263 r.ymax = size[1];
264
265 ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymax);
266 ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
267 ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymin);
268 verts_len = 3;
269 if (is_solid) {
270 ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
271 verts_len += 1;
272 prim_type = GPU_PRIM_TRI_FAN;
273 }
274 else {
275 prim_type = GPU_PRIM_LINE_STRIP;
276 }
277 break;
278 }
280 rctf r;
281 r.xmin = size[0] - margin[0];
282 r.xmax = size[0];
283 r.ymin = -size[1];
284 r.ymax = -size[1] + margin[1];
285
286 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
287 ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
288 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
289 verts_len = 3;
290 if (is_solid) {
291 ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
292 verts_len += 1;
293 prim_type = GPU_PRIM_TRI_FAN;
294 }
295 else {
296 prim_type = GPU_PRIM_LINE_STRIP;
297 }
298 break;
299 }
301 rctf r;
302 r.xmin = size[0] - margin[0];
303 r.xmax = size[0];
304 r.ymin = size[1] - margin[1];
305 r.ymax = size[1];
306
307 ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
308 ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymin);
309 ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
310 verts_len = 3;
311 if (is_solid) {
312 ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymax);
313 verts_len += 1;
314 prim_type = GPU_PRIM_TRI_FAN;
315 }
316 else {
317 prim_type = GPU_PRIM_LINE_STRIP;
318 }
319 break;
320 }
322 const float rotate_pt[2] = {0.0f, size[1] + margin[1]};
323 rctf r_rotate{};
324 r_rotate.xmin = rotate_pt[0] - margin[0] / 2.0f;
325 r_rotate.xmax = rotate_pt[0] + margin[0] / 2.0f;
326 r_rotate.ymin = rotate_pt[1] - margin[1] / 2.0f;
327 r_rotate.ymax = rotate_pt[1] + margin[1] / 2.0f;
328
329 ARRAY_SET_ITEMS(verts[0], r_rotate.xmin, r_rotate.ymin);
330 ARRAY_SET_ITEMS(verts[1], r_rotate.xmin, r_rotate.ymax);
331 ARRAY_SET_ITEMS(verts[2], r_rotate.xmax, r_rotate.ymax);
332 ARRAY_SET_ITEMS(verts[3], r_rotate.xmax, r_rotate.ymin);
333
334 verts_len = 4;
335 if (is_solid) {
336 prim_type = GPU_PRIM_TRI_FAN;
337 }
338 else {
339 prim_type = GPU_PRIM_LINE_STRIP;
340 }
341 break;
342 }
343
346 ARRAY_SET_ITEMS(verts[0], -margin[0] / 2, -margin[1] / 2);
347 ARRAY_SET_ITEMS(verts[1], margin[0] / 2, margin[1] / 2);
348 ARRAY_SET_ITEMS(verts[2], -margin[0] / 2, margin[1] / 2);
349 ARRAY_SET_ITEMS(verts[3], margin[0] / 2, -margin[1] / 2);
350 verts_len = 4;
351 if (is_solid) {
352 prim_type = GPU_PRIM_TRI_FAN;
353 }
354 else {
355 prim_type = GPU_PRIM_LINES;
356 }
357 }
358 else {
359 /* Only used for 3D view selection, never displayed to the user. */
360 ARRAY_SET_ITEMS(verts[0], -size[0], -size[1]);
361 ARRAY_SET_ITEMS(verts[1], -size[0], size[1]);
362 ARRAY_SET_ITEMS(verts[2], size[0], size[1]);
363 ARRAY_SET_ITEMS(verts[3], size[0], -size[1]);
364 verts_len = 4;
365 if (is_solid) {
366 prim_type = GPU_PRIM_TRI_FAN;
367 }
368 else {
369 /* unreachable */
370 BLI_assert(0);
371 prim_type = GPU_PRIM_LINE_STRIP;
372 }
373 }
374 break;
375 default:
376 return;
377 }
378
379 BLI_assert(prim_type != GPU_PRIM_NONE);
380
382 struct {
383 uint pos, col;
384 } attr_id{};
388
389 {
390 if (is_solid) {
391
392 if (margin[0] == 0.0f && margin[1] == 0.0) {
393 prim_type = GPU_PRIM_POINTS;
394 }
395 else if (margin[0] == 0.0f || margin[1] == 0.0) {
396 prim_type = GPU_PRIM_LINE_STRIP;
397 }
398 else {
399 BLI_assert(ELEM(prim_type, GPU_PRIM_TRI_FAN));
400 }
401
402 immBegin(prim_type, verts_len);
403 immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
404 for (uint i = 0; i < verts_len; i++) {
405 immVertex2fv(attr_id.pos, verts[i]);
406 }
407 immEnd();
408 }
409 else {
411
412 float viewport[4];
413 GPU_viewport_size_get_f(viewport);
414 immUniform2fv("viewportSize", &viewport[2]);
415
416 immUniform1f("lineWidth", (line_width * 3.0f) * U.pixelsize);
417
418 immBegin(prim_type, verts_len);
419 immAttr3f(attr_id.col, 0.0f, 0.0f, 0.0f);
420 for (uint i = 0; i < verts_len; i++) {
421 immVertex2fv(attr_id.pos, verts[i]);
422 }
423 immEnd();
424
425 immUniform1f("lineWidth", line_width * U.pixelsize);
426
427 immBegin(prim_type, verts_len);
429 for (uint i = 0; i < verts_len; i++) {
430 immVertex2fv(attr_id.pos, verts[i]);
431 }
432 immEnd();
433 }
434 }
435
437}
438
440
441/* -------------------------------------------------------------------- */
446
448 uint pos, float x, float y, float rad_x, float rad_y, bool solid)
449{
450 if (rad_x == 0 && rad_y == 0) {
452 immVertex2f(pos, x, y);
453 immEnd();
454 return;
455 }
456
457 if (rad_x == 0 || rad_y == 0) {
458 /* Do not draw anything if only on of the radii is zero. */
459 return;
460 }
461
462 if (solid) {
463 /* NOTE(Metal/AMD): Small Triangle-list primitives more optimal for GPU HW than Triangle-strip.
464 */
466 immVertex2f(pos, x - rad_x, y - rad_y);
467 immVertex2f(pos, x - rad_x, y + rad_y);
468 immVertex2f(pos, x + rad_x, y + rad_y);
469
470 immVertex2f(pos, x - rad_x, y - rad_y);
471 immVertex2f(pos, x + rad_x, y + rad_y);
472 immVertex2f(pos, x + rad_x, y - rad_y);
473 immEnd();
474 }
475 else {
476 /* NOTE(Metal/AMD): Small Line-list primitives more optimal for GPU HW than Line-strip. */
478 immVertex2f(pos, x - rad_x, y - rad_y);
479 immVertex2f(pos, x - rad_x, y + rad_y);
480
481 immVertex2f(pos, x - rad_x, y + rad_y);
482 immVertex2f(pos, x + rad_x, y + rad_y);
483
484 immVertex2f(pos, x + rad_x, y + rad_y);
485 immVertex2f(pos, x + rad_x, y - rad_y);
486
487 immVertex2f(pos, x + rad_x, y - rad_y);
488 immVertex2f(pos, x - rad_x, y - rad_y);
489 immEnd();
490 }
491}
492
493static void cage2d_draw_rect_wire(const rctf *r,
494 const float margin[2],
495 const float color[3],
496 const int transform_flag,
497 const int draw_options,
498 const float line_width)
499{
500 /* NOTE(Metal): Prefer using 3D coordinates with 3D shader input, even if rendering 2D gizmo's.
501 */
503
506
507 float viewport[4];
508 GPU_viewport_size_get_f(viewport);
509 immUniform2fv("viewportSize", &viewport[2]);
510 immUniform1f("lineWidth", line_width * U.pixelsize);
511
512 /* Small 'lines' primitives more efficient for hardware processing than line-strip. */
514 immVertex3f(pos, r->xmin, r->ymin, 0.0f);
515 immVertex3f(pos, r->xmax, r->ymin, 0.0f);
516
517 immVertex3f(pos, r->xmax, r->ymin, 0.0f);
518 immVertex3f(pos, r->xmax, r->ymax, 0.0f);
519
520 immVertex3f(pos, r->xmax, r->ymax, 0.0f);
521 immVertex3f(pos, r->xmin, r->ymax, 0.0f);
522
523 immVertex3f(pos, r->xmin, r->ymax, 0.0f);
524 immVertex3f(pos, r->xmin, r->ymin, 0.0f);
525 immEnd();
526
527 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
529 immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax, 0.0f);
530 immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1], 0.0f);
531
532 immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1], 0.0f);
533 immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax, 0.0f);
534 immEnd();
535 }
536
537 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
539 const float rad[2] = {margin[0] / 2, margin[1] / 2};
540 const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)};
541
543 immVertex3f(pos, center[0] - rad[0], center[1] - rad[1], 0.0f);
544 immVertex3f(pos, center[0] + rad[0], center[1] + rad[1], 0.0f);
545 immVertex3f(pos, center[0] + rad[0], center[1] - rad[1], 0.0f);
546 immVertex3f(pos, center[0] - rad[0], center[1] + rad[1], 0.0f);
547 immEnd();
548 }
549 }
550
552}
553
554static void cage2d_draw_circle_wire(const float color[3],
555 const float size[2],
556 const float margin[2],
557 const float line_width)
558{
560
561 const bool use_points = is_zero_v2(margin);
565
566 if (use_points) {
567 /* Draw a central point. */
568 immUniform1f("size", 1.0 * U.pixelsize);
570 immVertex3f(pos, 0.0f, 0.0f, 0.0f);
571 immEnd();
572 }
573 else {
574 float viewport[4];
575 GPU_viewport_size_get_f(viewport);
576 immUniform2fv("viewportSize", &viewport[2]);
577 immUniform1f("lineWidth", line_width * U.pixelsize);
579 }
580
582}
583
585 const int highlighted,
586 const float margin[2],
587 const float color[3],
588 const int transform_flag,
589 bool solid)
590{
591 /* Only draw corner handles when hovering over the corners. */
592 if (highlighted < ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y ||
594 {
595 return;
596 }
597
599 void (*circle_fn)(uint, float, float, float, float, int) = (solid) ?
602 const int resolu = 12;
603 const float rad[2] = {margin[0] / 3, margin[1] / 3};
604
607
608 /* should really divide by two, but looks too bulky. */
609 {
610 imm_draw_point_aspect_2d(pos, r->xmin, r->ymin, rad[0], rad[1], solid);
611 imm_draw_point_aspect_2d(pos, r->xmax, r->ymin, rad[0], rad[1], solid);
612 imm_draw_point_aspect_2d(pos, r->xmax, r->ymax, rad[0], rad[1], solid);
613 imm_draw_point_aspect_2d(pos, r->xmin, r->ymax, rad[0], rad[1], solid);
614 }
615
616 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
617 const float handle[2] = {
619 r->ymax + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE),
620 };
621 circle_fn(pos, handle[0], handle[1], rad[0], rad[1], resolu);
622 }
623
625}
626
628 const int highlighted,
629 const float size[2],
630 const float margin[2],
631 const float color[3],
632 bool solid)
633{
635
638
639 switch (highlighted) {
642 const float rad[2] = {0.2f * margin[0], 0.4f * size[1]};
643 imm_draw_point_aspect_2d(pos, r->xmin, 0.0f, rad[0], rad[1], solid);
644 imm_draw_point_aspect_2d(pos, r->xmax, 0.0f, rad[0], rad[1], solid);
645 break;
646 }
649 const float rad[2] = {0.4f * size[0], 0.2f * margin[1]};
650 imm_draw_point_aspect_2d(pos, 0.0f, r->ymin, rad[0], rad[1], solid);
651 imm_draw_point_aspect_2d(pos, 0.0f, r->ymax, rad[0], rad[1], solid);
652 break;
653 }
654 }
655
657}
658
660
662 const bool select,
663 const bool highlight,
664 const int select_id)
665{
666 // const bool use_clamp = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0;
667 float dims[2];
668 RNA_float_get_array(gz->ptr, "dimensions", dims);
669 float matrix_final[4][4];
670
671 const int transform_flag = gizmo_cage2d_transform_flag_get(gz);
672 const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
673 const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
674
675 const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
676
677 WM_gizmo_calc_matrix_final(gz, matrix_final);
678
680 GPU_matrix_mul(matrix_final);
681
682 float margin[2];
683 gizmo_calc_rect_view_margin(gz, dims, margin);
684
685 /* Handy for quick testing draw (if it's outside bounds). */
686 if (false) {
690 immUniformColor4f(1, 1, 1, 0.5f);
691 float s = 0.5f;
692 immRectf(pos, -s, -s, s, s);
695 }
696
697 if (select) {
698 /* Expand for hot-spot. */
699 const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
700 if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
701 /* Only scaling is needed for now. */
703
704 cage2d_draw_circle_wire(gz->color, size_real, margin, gz->line_width);
705 }
706 else {
707 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE) {
708 int scale_parts[] = {
713
718 };
719 for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) {
720 GPU_select_load_id(select_id | scale_parts[i]);
722 gz->color, scale_parts[i], size, margin, gz->line_width, true, draw_options);
723 }
724 }
725 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
726 const int transform_part = ED_GIZMO_CAGE2D_PART_TRANSLATE;
727 GPU_select_load_id(select_id | transform_part);
729 gz->color, transform_part, size, margin, gz->line_width, true, draw_options);
730 }
731 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
734 size_real,
735 margin,
736 gz->line_width,
737 true,
738 draw_options);
739 }
740 }
741 }
742 else {
743 rctf r;
744 r.xmin = -size_real[0];
745 r.ymin = -size_real[1];
746 r.xmax = size_real[0];
747 r.ymax = size_real[1];
748
749 if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
750 float color[4], black[3] = {0, 0, 0};
751 gizmo_color_get(gz, highlight, color);
752
753 /* corner gizmos */
754 cage2d_draw_box_corners(&r, margin, black, gz->line_width + 3.0f);
755
756 /* corner gizmos */
757 cage2d_draw_box_corners(&r, margin, color, gz->line_width);
758
759 bool show = false;
761 /* Only show if we're drawing the center handle
762 * otherwise the entire rectangle is the hot-spot. */
764 show = true;
765 }
766 }
767 else {
768 show = true;
769 }
770
771 if (show) {
773 gz->color, gz->highlight_part, size_real, margin, gz->line_width, false, draw_options);
774 }
775
776 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
779 size_real,
780 margin,
781 gz->line_width,
782 false,
783 draw_options);
784 }
785 }
786 else {
787 float color[4], black[3] = {0, 0, 0};
788 gizmo_color_get(gz, highlight, color);
789
791
792 float outline_line_width = gz->line_width + 3.0f;
793
794 if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX_TRANSFORM) {
795 cage2d_draw_rect_wire(&r, margin, black, transform_flag, draw_options, outline_line_width);
796 cage2d_draw_rect_wire(&r, margin, color, transform_flag, draw_options, gz->line_width);
797
798 /* Edge handles. */
799 cage2d_draw_rect_edge_handles(&r, gz->highlight_part, size_real, margin, color, true);
800 cage2d_draw_rect_edge_handles(&r, gz->highlight_part, size_real, margin, black, false);
801
802 /* Corner handles. */
804 &r, gz->highlight_part, margin, color, transform_flag, true);
806 &r, gz->highlight_part, margin, black, transform_flag, false);
807 }
808 else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
809 cage2d_draw_circle_wire(black, size_real, margin, outline_line_width);
810 cage2d_draw_circle_wire(color, size_real, margin, gz->line_width);
811 }
812 else {
813 BLI_assert(0);
814 }
816 }
817 }
818
820}
821
825static void gizmo_cage2d_draw_select(const bContext * /*C*/, wmGizmo *gz, int select_id)
826{
827 gizmo_cage2d_draw_intern(gz, true, false, select_id);
828}
829
830static void gizmo_cage2d_draw(const bContext * /*C*/, wmGizmo *gz)
831{
832 const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
833 gizmo_cage2d_draw_intern(gz, false, is_highlight, -1);
834}
835
837{
838 int highlight_part = gz->highlight_part;
839
842 }
843
844 switch (highlight_part) {
853
854 /* TODO: diagonal cursor. */
862 return WM_CURSOR_CROSS;
863 default:
864 return WM_CURSOR_DEFAULT;
865 }
866}
867
868static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
869{
870 float point_local[2];
871 float dims[2];
872 RNA_float_get_array(gz->ptr, "dimensions", dims);
873 const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
874
875 if (gizmo_window_project_2d(C, gz, blender::float2(blender::int2(mval)), 2, true, point_local) ==
876 false)
877 {
878 return -1;
879 }
880
881 float margin[2];
882 gizmo_calc_rect_view_margin(gz, dims, margin);
883
884 /* Expand for hots-pot. */
885 const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
886
887 const int transform_flag = gizmo_cage2d_transform_flag_get(gz);
888 const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
889
890 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
891 rctf r;
893 r.xmin = -margin[0] / 2;
894 r.ymin = -margin[1] / 2;
895 r.xmax = margin[0] / 2;
896 r.ymax = margin[1] / 2;
897 }
898 else {
899 r.xmin = -size[0] + margin[0];
900 r.ymin = -size[1] + margin[1];
901 r.xmax = size[0] - margin[0];
902 r.ymax = size[1] - margin[1];
903 }
904 bool isect = BLI_rctf_isect_pt_v(&r, point_local);
905 if (isect) {
907 }
908 }
909
910 /* if gizmo does not have a scale intersection, don't do it */
912 rctf r_xmin{};
913 r_xmin.xmin = -size[0];
914 r_xmin.ymin = -size[1];
915 r_xmin.xmax = -size[0] + margin[0];
916 r_xmin.ymax = size[1];
917
918 rctf r_xmax{};
919 r_xmax.xmin = size[0] - margin[0];
920 r_xmax.ymin = -size[1];
921 r_xmax.xmax = size[0];
922 r_xmax.ymax = size[1];
923
924 rctf r_ymin{};
925 r_ymin.xmin = -size[0];
926 r_ymin.ymin = -size[1];
927 r_ymin.xmax = size[0];
928 r_ymin.ymax = -size[1] + margin[1];
929
930 rctf r_ymax{};
931 r_ymax.xmin = -size[0];
932 r_ymax.ymin = size[1] - margin[1];
933 r_ymax.xmax = size[0];
934 r_ymax.ymax = size[1];
935
936 if (BLI_rctf_isect_pt_v(&r_xmin, point_local)) {
937 if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
939 }
940 if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
942 }
944 }
945 if (BLI_rctf_isect_pt_v(&r_xmax, point_local)) {
946 if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
948 }
949 if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
951 }
953 }
954 if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
956 }
957 if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
959 }
960 }
961
962 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
963 /* Rotate:
964 * (*) <-- hot spot is here!
965 * +---+
966 * | |
967 * +---+ */
968 const float r_rotate_pt[2] = {0.0f, size_real[1] + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE)};
969 rctf r_rotate{};
970 r_rotate.xmin = r_rotate_pt[0] - margin[0] / 2.0f;
971 r_rotate.xmax = r_rotate_pt[0] + margin[0] / 2.0f;
972 r_rotate.ymin = r_rotate_pt[1] - margin[1] / 2.0f;
973 r_rotate.ymax = r_rotate_pt[1] + margin[1] / 2.0f;
974
975 if (BLI_rctf_isect_pt_v(&r_rotate, point_local)) {
977 }
978 }
979
980 return -1;
981}
982
990
992{
994 int transform_flag = RNA_enum_get(gz->ptr, "transform");
995 if (data) {
996 if (data->use_temp_uniform) {
998 }
999 }
1000 return transform_flag;
1001}
1002
1007
1008static int gizmo_cage2d_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
1009{
1011 MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction"));
1012
1013 copy_m4_m4(data->orig_matrix_offset, gz->matrix_offset);
1014 WM_gizmo_calc_matrix_final_no_offset(gz, data->orig_matrix_final_no_offset);
1015
1017 C, gz, blender::float2(blender::int2(event->mval)), 2, false, data->orig_mouse) == 0)
1018 {
1019 zero_v2(data->orig_mouse);
1020 }
1021
1022 gz->interaction_data = data;
1023
1025}
1026
1027static void gizmo_constrain_from_scale_part(int part, bool r_constrain_axis[2])
1028{
1029 r_constrain_axis[0] = (part > ED_GIZMO_CAGE2D_PART_SCALE_MAX_X &&
1031 true :
1032 false;
1033 r_constrain_axis[1] = (part > ED_GIZMO_CAGE2D_PART_SCALE &&
1035 true :
1036 false;
1037}
1038
1039static void gizmo_pivot_from_scale_part(int part, float r_pt[2])
1040{
1041 switch (part) {
1043 ARRAY_SET_ITEMS(r_pt, 0.0, 0.0);
1044 break;
1045 }
1047 ARRAY_SET_ITEMS(r_pt, 0.5, 0.0);
1048 break;
1049 }
1051 ARRAY_SET_ITEMS(r_pt, -0.5, 0.0);
1052 break;
1053 }
1055 ARRAY_SET_ITEMS(r_pt, 0.0, 0.5);
1056 break;
1057 }
1059 ARRAY_SET_ITEMS(r_pt, 0.0, -0.5);
1060 break;
1061 }
1063 ARRAY_SET_ITEMS(r_pt, 0.5, 0.5);
1064 break;
1065 }
1067 ARRAY_SET_ITEMS(r_pt, 0.5, -0.5);
1068 break;
1069 }
1071 ARRAY_SET_ITEMS(r_pt, -0.5, 0.5);
1072 break;
1073 }
1075 ARRAY_SET_ITEMS(r_pt, -0.5, -0.5);
1076 break;
1077 }
1078 default:
1079 BLI_assert(0);
1080 }
1081}
1082
1084 wmGizmo *gz,
1085 const wmEvent *event,
1086 eWM_GizmoFlagTweak /*tweak_flag*/)
1087{
1089 int transform_flag = RNA_enum_get(gz->ptr, "transform");
1090 if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) == 0) {
1091 /* WARNING: Checking the events modifier only makes sense as long as `tweak_flag`
1092 * remains unused (this controls #WM_GIZMO_TWEAK_PRECISE by default). */
1093 const bool use_temp_uniform = (event->modifier & KM_SHIFT) != 0;
1094 const bool changed = data->use_temp_uniform != use_temp_uniform;
1095 data->use_temp_uniform = use_temp_uniform;
1096 if (use_temp_uniform) {
1098 }
1099
1100 if (changed) {
1101 /* Always refresh. */
1102 }
1103 else if (event->type != MOUSEMOVE) {
1105 }
1106 }
1107
1108 float point_local[2];
1109
1110 float dims[2];
1111 RNA_float_get_array(gz->ptr, "dimensions", dims);
1112
1113 {
1114 float matrix_back[4][4];
1115 copy_m4_m4(matrix_back, gz->matrix_offset);
1116 copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
1117
1118 /* The mouse coords are projected into the matrix so we don't need to worry about axis
1119 * alignment. */
1120 bool ok = gizmo_window_project_2d(
1121 C, gz, blender::float2(blender::int2(event->mval)), 2, false, point_local);
1122 copy_m4_m4(gz->matrix_offset, matrix_back);
1123 if (!ok) {
1125 }
1126 }
1127
1128 wmGizmoProperty *gz_prop;
1129
1130 gz_prop = WM_gizmo_target_property_find(gz, "matrix");
1131 if (gz_prop->type != nullptr) {
1133 }
1134
1136 /* do this to prevent clamping from changing size */
1137 copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
1138 gz->matrix_offset[3][0] = data->orig_matrix_offset[3][0] +
1139 (point_local[0] - data->orig_mouse[0]);
1140 gz->matrix_offset[3][1] = data->orig_matrix_offset[3][1] +
1141 (point_local[1] - data->orig_mouse[1]);
1142 }
1144
1145#define MUL_V2_V3_M4_FINAL(test_co, mouse_co) \
1146 mul_v3_m4v3(test_co, data->orig_matrix_final_no_offset, blender::float3{UNPACK2(mouse_co), 0.0})
1147
1148 float test_co[3];
1149
1150 if (data->dial == nullptr) {
1151 MUL_V2_V3_M4_FINAL(test_co, data->orig_matrix_offset[3]);
1152
1153 data->dial = BLI_dial_init(test_co, FLT_EPSILON);
1154
1155 MUL_V2_V3_M4_FINAL(test_co, data->orig_mouse);
1156 BLI_dial_angle(data->dial, test_co);
1157 }
1158
1159 /* rotate */
1160 MUL_V2_V3_M4_FINAL(test_co, point_local);
1161 const float angle = BLI_dial_angle(data->dial, test_co);
1162
1163 float matrix_space_inv[4][4];
1164 float matrix_rotate[4][4];
1165 float pivot[3];
1166
1167 copy_v3_v3(pivot, data->orig_matrix_offset[3]);
1168
1169 invert_m4_m4(matrix_space_inv, gz->matrix_space);
1170
1171 unit_m4(matrix_rotate);
1172 mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv);
1173 rotate_m4(matrix_rotate, 'Z', -angle);
1174 mul_m4_m4m4(matrix_rotate, matrix_rotate, gz->matrix_space);
1175
1176 zero_v3(matrix_rotate[3]);
1177 transform_pivot_set_m4(matrix_rotate, pivot);
1178
1179 mul_m4_m4m4(gz->matrix_offset, matrix_rotate, data->orig_matrix_offset);
1180
1181#undef MUL_V2_V3_M4_FINAL
1182 }
1183 else {
1184 /* scale */
1185 copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
1186 const int draw_style = RNA_enum_get(gz->ptr, "draw_style");
1187
1188 float pivot[2];
1189 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
1191 mul_v2_v2(pivot, dims);
1192 }
1193 else {
1194 zero_v2(pivot);
1195 }
1196
1197 bool constrain_axis[2] = {false};
1199
1200 float size_new[2], size_orig[2];
1201 for (int i = 0; i < 2; i++) {
1202 size_orig[i] = len_v3(data->orig_matrix_offset[i]);
1203 size_new[i] = size_orig[i];
1204 if (constrain_axis[i] == false) {
1205 /* Original cursor position relative to pivot. */
1206 const float delta_orig = data->orig_mouse[i] - data->orig_matrix_offset[3][i] -
1207 pivot[i] * size_orig[i];
1208 const float delta_curr = point_local[i] - data->orig_matrix_offset[3][i] -
1209 pivot[i] * size_orig[i];
1210
1211 if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED) == 0) {
1212 if (signum_i(delta_orig) != signum_i(delta_curr)) {
1213 size_new[i] = 0.0f;
1214 continue;
1215 }
1216 }
1217
1218 /* Original cursor position does not exactly lie on the cage boundary due to margin. */
1219 size_new[i] = delta_curr / (signf(delta_orig) * 0.5f * dims[i] - pivot[i]);
1220 }
1221 }
1222
1223 float scale[2] = {1.0f, 1.0f};
1224 for (int i = 0; i < 2; i++) {
1225 if (size_orig[i] == 0) {
1226 size_orig[i] = 1.0f;
1227 gz->matrix_offset[i][i] = 1.0f;
1228 }
1229 scale[i] = size_new[i] / size_orig[i];
1230 }
1231
1232 if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) {
1233 if (constrain_axis[0] == false && constrain_axis[1] == false) {
1234 if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
1235 /* So that the cursor lies on the circle. */
1236 scale[1] = scale[0] = len_v2(scale);
1237 }
1238 else {
1239 scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
1240 }
1241 }
1242 else if (constrain_axis[0] == false) {
1243 scale[1] = scale[0];
1244 }
1245 else if (constrain_axis[1] == false) {
1246 scale[0] = scale[1];
1247 }
1248 else {
1249 BLI_assert(0);
1250 }
1251 }
1252
1253 /* Scale around pivot. */
1254 float matrix_scale[4][4];
1255 unit_m4(matrix_scale);
1256
1257 mul_v3_fl(matrix_scale[0], scale[0]);
1258 mul_v3_fl(matrix_scale[1], scale[1]);
1259
1260 transform_pivot_set_m4(matrix_scale, blender::float3(UNPACK2(pivot), 0.0f));
1261 mul_m4_m4_post(gz->matrix_offset, matrix_scale);
1262 }
1263
1264 if (gz_prop->type != nullptr) {
1266 }
1267
1268 /* tag the region for redraw */
1271
1273}
1274
1276{
1277 if (STREQ(gz_prop->type->idname, "matrix")) {
1278 if (WM_gizmo_target_property_array_length(gz, gz_prop) == 16) {
1280 }
1281 else {
1282 BLI_assert(0);
1283 }
1284 }
1285 else {
1286 BLI_assert(0);
1287 }
1288}
1289
1290static void gizmo_cage2d_exit(bContext *C, wmGizmo *gz, const bool cancel)
1291{
1293
1294 MEM_SAFE_FREE(data->dial);
1295
1296 if (!cancel) {
1297 return;
1298 }
1299
1300 wmGizmoProperty *gz_prop;
1301
1302 /* reset properties */
1303 gz_prop = WM_gizmo_target_property_find(gz, "matrix");
1304 if (gz_prop->type != nullptr) {
1305 WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &data->orig_matrix_offset[0][0]);
1306 }
1307
1308 copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset);
1309}
1310
1311/* -------------------------------------------------------------------- */
1314
1316{
1317 /* identifiers */
1318 gzt->idname = "GIZMO_GT_cage_2d";
1319
1320 /* api callbacks */
1321 gzt->draw = gizmo_cage2d_draw;
1328 gzt->exit = gizmo_cage2d_exit;
1330
1331 gzt->struct_size = sizeof(wmGizmo);
1332
1333 /* rna */
1334 static const EnumPropertyItem rna_enum_draw_style[] = {
1335 {ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
1336 {ED_GIZMO_CAGE2D_STYLE_BOX_TRANSFORM, "BOX_TRANSFORM", 0, "Box Transform", ""},
1337 {ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
1338 {0, nullptr, 0, nullptr, nullptr},
1339 };
1340 static const EnumPropertyItem rna_enum_transform[] = {
1341 {ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
1342 {ED_GIZMO_CAGE_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""},
1343 {ED_GIZMO_CAGE_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
1344 {ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
1345 {0, nullptr, 0, nullptr, nullptr},
1346 };
1347 static const EnumPropertyItem rna_enum_draw_options[] = {
1348 {ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
1349 {0, nullptr, 0, nullptr, nullptr},
1350 };
1351 static const float unit_v2[2] = {1.0f, 1.0f};
1353 gzt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
1354 RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
1355 RNA_def_enum(gzt->srna,
1356 "draw_style",
1357 rna_enum_draw_style,
1359 "Draw Style",
1360 "");
1362 "draw_options",
1363 rna_enum_draw_options,
1365 "Draw Options",
1366 "");
1367
1368 WM_gizmotype_target_property_def(gzt, "matrix", PROP_FLOAT, 16);
1369}
1370
1375
wmWindow * CTX_wm_window(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
#define BLI_assert(a)
Definition BLI_assert.h:50
Dial * BLI_dial_init(const float start_position[2], float threshold)
Definition BLI_dial_2d.c:37
float BLI_dial_angle(Dial *dial, const float current_position[2])
Definition BLI_dial_2d.c:47
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 unit_m4(float m[4][4])
Definition rct.c:1127
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])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_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 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_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:184
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
Definition BLI_rect.h:180
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_XFORM_CENTER_HANDLE
void ED_region_tag_redraw_editor_overlays(ARegion *region)
Definition area.cc:669
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:262
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
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 Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
@ PROP_FLOAT
Definition RNA_types.hh:67
#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:255
#define U
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
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_rect_corner_handles(const rctf *r, const int highlighted, const float margin[2], const float color[3], const int transform_flag, bool solid)
static void cage2d_draw_box_corners(const rctf *r, const float margin[2], const float color[3], const float line_width)
static void gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[2], float margin[2])
static int 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])
static void cage2d_draw_circle_wire(const float color[3], const float size[2], const float margin[2], const float line_width)
static void gizmo_cage2d_draw_select(const bContext *, wmGizmo *gz, int select_id)
static void gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], float scale[2])
static void imm_draw_point_aspect_2d(uint pos, float x, float y, float rad_x, float rad_y, bool solid)
static int gizmo_cage2d_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
#define MUL_V2_V3_M4_FINAL(test_co, mouse_co)
static void gizmo_cage2d_setup(wmGizmo *gz)
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 CIRCLE_RESOL
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
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 col
struct @157336070235062372277311340362362342103123126032::@132215023242101136103363133227133264017254024241 attr_id
format
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
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 orig_matrix_final_no_offset[4][4]
float xmax
float xmin
float ymax
float ymin
int mval[2]
Definition WM_types.hh:728
short type
Definition WM_types.hh:722
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
@ WM_CURSOR_NSEW_SCROLL
Definition wm_cursors.hh:51
@ 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:569
void WM_gizmo_calc_matrix_final_no_offset(const wmGizmo *gz, float r_mat[4][4])
Definition wm_gizmo.cc:556
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 *))