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
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/* -------------------------------------------------------------------- */
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
104 immUniformColor3fv(color);
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);
428 immAttr3fv(attr_id.col, color);
429 for (uint i = 0; i < verts_len; i++) {
430 immVertex2fv(attr_id.pos, verts[i]);
431 }
432 immEnd();
433 }
434 }
435
437}
438
441/* -------------------------------------------------------------------- */
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
505 immUniformColor3fv(color);
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);
564 immUniformColor3fv(color);
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);
578 imm_draw_circle_wire_aspect_3d(pos, 0.0f, 0.0f, size[0], size[1], CIRCLE_RESOL);
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
606 immUniformColor3fv(color);
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
637 immUniformColor3fv(color);
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
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) {
1265 WM_gizmo_target_property_float_set_array(C, gz, gz_prop, &gz->matrix_offset[0][0]);
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/* -------------------------------------------------------------------- */
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_DRAW_FLAG_XFORM_CENTER_HANDLE
@ ED_GIZMO_CAGE2D_STYLE_BOX_TRANSFORM
@ ED_GIZMO_CAGE2D_STYLE_BOX
@ ED_GIZMO_CAGE2D_STYLE_CIRCLE
@ 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_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
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
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
@ PROP_FLOAT
Definition RNA_types.hh:67
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
unsigned int U
Definition btGjkEpa3.h:78
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])
#define CIRCLE_RESOL
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)
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])
struct @620::@623 attr_id
uint col
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)
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 *))