Blender  V3.3
editmesh_add_gizmo.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "MEM_guardedalloc.h"
10 
11 #include "BLI_math.h"
12 
13 #include "DNA_object_types.h"
14 #include "DNA_scene_types.h"
15 
16 #include "BKE_context.h"
17 #include "BKE_editmesh.h"
18 #include "BKE_scene.h"
19 
20 #include "ED_gizmo_library.h"
21 #include "ED_gizmo_utils.h"
22 #include "ED_mesh.h"
23 #include "ED_object.h"
24 #include "ED_screen.h"
25 #include "ED_undo.h"
26 #include "ED_view3d.h"
27 
28 #include "RNA_access.h"
29 #include "RNA_define.h"
30 
31 #include "WM_api.h"
32 #include "WM_types.h"
33 
34 #include "UI_resources.h"
35 
36 #include "BLT_translation.h"
37 
38 #include "mesh_intern.h" /* own include */
39 
40 /* -------------------------------------------------------------------- */
52  const float mval[2],
53  float r_location[3],
54  float r_rotation[3][3])
55 {
56 
58  ARegion *region = CTX_wm_region(C);
59  RegionView3D *rv3d = region->regiondata;
60 
61  bool use_mouse_project = true; /* TODO: make optional */
62 
63  float cursor_matrix[4][4];
64  float orient_matrix[3][3];
65  BKE_scene_cursor_to_mat4(&scene->cursor, cursor_matrix);
66 
67  const float dots[3] = {
68  dot_v3v3(rv3d->viewinv[2], cursor_matrix[0]),
69  dot_v3v3(rv3d->viewinv[2], cursor_matrix[1]),
70  dot_v3v3(rv3d->viewinv[2], cursor_matrix[2]),
71  };
72  const int axis = axis_dominant_v3_single(dots);
73 
74  copy_v3_v3(orient_matrix[0], cursor_matrix[(axis + 1) % 3]);
75  copy_v3_v3(orient_matrix[1], cursor_matrix[(axis + 2) % 3]);
76  copy_v3_v3(orient_matrix[2], cursor_matrix[axis]);
77 
78  if (dot_v3v3(rv3d->viewinv[2], orient_matrix[2]) < 0.0f) {
79  negate_v3(orient_matrix[2]);
80  }
81  if (is_negative_m3(orient_matrix)) {
82  swap_v3_v3(orient_matrix[0], orient_matrix[1]);
83  }
84 
85  if (use_mouse_project) {
86  float plane[4];
87  plane_from_point_normal_v3(plane, cursor_matrix[3], orient_matrix[2]);
88  if (ED_view3d_win_to_3d_on_plane(region, plane, mval, true, r_location)) {
89  copy_m3_m3(r_rotation, orient_matrix);
90  return;
91  }
92  }
93 
94  /* fallback */
95  copy_v3_v3(r_location, cursor_matrix[3]);
96  copy_m3_m3(r_rotation, orient_matrix);
97 }
98 
101 /* -------------------------------------------------------------------- */
105 typedef struct GizmoPlacementGroup {
106  struct wmGizmo *cage;
107  struct {
111  } data;
113 
120 {
121  wmOperator *op = ggd->data.op;
122  if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
124  }
125 }
126 
128 {
129  wmOperator *op = ggd->data.op;
130  UNUSED_VARS(op);
131  /* For now don't read back from the operator. */
132 #if 0
134 #endif
135 }
136 
137 /* translate callbacks */
139  wmGizmoProperty *gz_prop,
140  void *value_p)
141 {
143  wmOperator *op = ggd->data.op;
144  float *value = value_p;
145  BLI_assert(gz_prop->type->array_length == 16);
146  UNUSED_VARS_NDEBUG(gz_prop);
147 
148  if (value_p != ggd->cage->matrix_offset) {
149  mul_m4_m4m4(value_p, ggd->cage->matrix_basis, ggd->cage->matrix_offset);
151  }
152 }
153 
155  wmGizmoProperty *gz_prop,
156  const void *value)
157 {
159  wmOperator *op = ggd->data.op;
160 
161  BLI_assert(gz_prop->type->array_length == 16);
162  UNUSED_VARS_NDEBUG(gz_prop);
163 
164  float mat[4][4];
165  mul_m4_m4m4(mat, ggd->cage->matrix_basis, value);
166 
167  if (is_negative_m4(mat)) {
168  negate_mat3_m4(mat);
169  }
170 
171  RNA_property_float_set_array(op->ptr, ggd->data.prop_matrix, &mat[0][0]);
172 
174 }
175 
177 {
179  C, gzgt, "MESH_OT_primitive_cube_add_gizmo");
180 }
181 
183 {
184  GizmoPlacementGroup *ggd = gzgroup->customdata;
185 
186  /* Initial size. */
187  {
188  wmGizmo *gz = ggd->cage;
189  zero_m4(gz->matrix_offset);
190 
191  /* TODO: support zero scaled matrix in 'GIZMO_GT_cage_3d'. */
192  gz->matrix_offset[0][0] = 0.01;
193  gz->matrix_offset[1][1] = 0.01;
194  gz->matrix_offset[2][2] = 0.01;
195  gz->matrix_offset[3][3] = 1.0f;
196  }
197 
198  /* Start off dragging. */
199  {
200  wmWindow *win = CTX_wm_window(C);
201  ARegion *region = CTX_wm_region(C);
202  wmGizmo *gz = ggd->cage;
203 
204  {
205  float mat3[3][3];
206  float location[3];
208  (float[2]){
209  win->eventstate->xy[0] - region->winrct.xmin,
210  win->eventstate->xy[1] - region->winrct.ymin,
211  },
212  location,
213  mat3);
214  copy_m4_m3(gz->matrix_basis, mat3);
215  copy_v3_v3(gz->matrix_basis[3], location);
216  }
217 
218  if (1) {
219  wmGizmoMap *gzmap = gzgroup->parent_gzmap;
221  (bContext *)C,
222  ggd->cage,
224  win->eventstate);
225  }
226  }
227 }
228 
229 static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *gzgroup)
230 {
232 
233  if (op == NULL || !STREQ(op->type->idname, "MESH_OT_primitive_cube_add_gizmo")) {
234  return;
235  }
236 
237  struct GizmoPlacementGroup *ggd = MEM_callocN(sizeof(GizmoPlacementGroup), __func__);
238  gzgroup->customdata = ggd;
239 
240  const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
241 
242  ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
243 
245 
246  RNA_enum_set(ggd->cage->ptr,
247  "transform",
250 
252 
253  ggd->data.context = (bContext *)C;
254  ggd->data.op = op;
255  ggd->data.prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
256 
258 
259  /* Setup property callbacks */
260  {
262  "matrix",
263  &(const struct wmGizmoPropertyFnParams){
264  .value_get_fn = gizmo_placement_prop_matrix_get,
265  .value_set_fn = gizmo_placement_prop_matrix_set,
266  .range_get_fn = NULL,
267  .user_data = NULL,
268  });
269  }
270 
272 }
273 
275 {
276  GizmoPlacementGroup *ggd = gzgroup->customdata;
277  if (ggd->data.op->next) {
279  }
281 }
282 
283 static void MESH_GGT_add_bounds(struct wmGizmoGroupType *gzgt)
284 {
285  gzgt->name = "Mesh Add Bounds";
286  gzgt->idname = "MESH_GGT_add_bounds";
287 
288  gzgt->flag = WM_GIZMOGROUPTYPE_3D;
289 
292 
296 }
297 
300 /* -------------------------------------------------------------------- */
309 {
310  Object *obedit = CTX_data_edit_object(C);
311  BMEditMesh *em = BKE_editmesh_from_object(obedit);
312  float matrix[4][4];
313 
314  /* Get the matrix that defines the cube bounds (as set by the gizmo cage). */
315  {
319  invert_m4_m4(obedit->imat, obedit->obmat);
320  mul_m4_m4m4(matrix, obedit->imat, matrix);
321  }
322  else {
323  /* For the first update the widget may not set the matrix. */
324  return OPERATOR_FINISHED;
325  }
326  }
327 
328  const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
329 
330  if (calc_uvs) {
331  ED_mesh_uv_ensure(obedit->data, NULL);
332  }
333 
334  if (!EDBM_op_call_and_selectf(em,
335  op,
336  "verts.out",
337  false,
338  "create_cube matrix=%m4 size=%f calc_uvs=%b",
339  matrix,
340  1.0f,
341  calc_uvs)) {
342  return OPERATOR_CANCELLED;
343  }
344 
346  EDBM_update(obedit->data,
347  &(const struct EDBMUpdate_Params){
348  .calc_looptri = true,
349  .calc_normals = false,
350  .is_destructive = true,
351  });
352 
353  return OPERATOR_FINISHED;
354 }
355 
357  wmOperator *op,
358  const wmEvent *UNUSED(event))
359 {
360  View3D *v3d = CTX_wm_view3d(C);
361 
363  if (ret & OPERATOR_FINISHED) {
364  /* Setup gizmos */
365  if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
366  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find("MESH_GGT_add_bounds", false);
367  if (!WM_gizmo_group_type_ensure_ptr(gzgt)) {
368  struct Main *bmain = CTX_data_main(C);
369  WM_gizmo_group_type_reinit_ptr(bmain, gzgt);
370  }
371  }
372  }
373 
374  return ret;
375 }
376 
378 {
379  /* identifiers */
380  ot->name = "Add Cube";
381  ot->description = "Construct a cube mesh";
382  ot->idname = "MESH_OT_primitive_cube_add_gizmo";
383 
384  /* api callbacks */
388 
389  /* flags */
391 
394 
395  /* hidden props */
397  ot->srna, "matrix", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
399 
401 }
402 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1370
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:58
void BKE_scene_cursor_to_mat4(const struct View3DCursor *cursor, float mat[4][4])
#define BLI_assert(a)
Definition: BLI_assert.h:46
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:209
MINLINE int axis_dominant_v3_single(const float vec[3])
bool is_negative_m3(const float mat[3][3])
Definition: math_matrix.c:2502
void zero_m4(float m[4][4])
Definition: math_matrix.c:28
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
bool is_negative_m4(const float mat[4][4])
Definition: math_matrix.c:2509
void negate_mat3_m4(float R[4][4])
Definition: math_matrix.c:1000
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void negate_v3(float r[3])
MINLINE void swap_v3_v3(float a[3], float b[3])
#define UNUSED_VARS(...)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define STREQ(a, b)
Object is a sort of wrapper for general info.
#define SCE_SELECT_VERTEX
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
@ V3D_GIZMO_HIDE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z
@ ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE
@ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED
@ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE
bool ED_gizmo_poll_or_unlink_delayed_from_operator(const struct bContext *C, struct wmGizmoGroupType *gzgt, const char *idname)
void ED_mesh_uv_ensure(struct Mesh *me, const char *name)
Definition: mesh_data.cc:310
void EDBM_update(struct Mesh *me, const struct EDBMUpdate_Params *params)
void EDBM_selectmode_flush_ex(struct BMEditMesh *em, short selectmode)
void ED_object_add_generic_props(struct wmOperatorType *ot, bool do_editmode)
Definition: object_add.cc:399
void ED_object_add_mesh_props(struct wmOperatorType *ot)
Definition: object_add.cc:452
bool ED_operator_editmesh_view3d(struct bContext *C)
Definition: screen_ops.c:442
int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op)
Definition: ed_undo.c:662
bool ED_view3d_win_to_3d_on_plane(const struct ARegion *region, const float plane[4], const float mval[2], bool do_clip, float r_out[3])
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
#define C
Definition: RandGen.cpp:25
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1165
@ TH_GIZMO_PRIMARY
Definition: UI_resources.h:305
@ WM_GIZMO_DRAW_VALUE
@ WM_GIZMOGROUPTYPE_3D
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
Scene scene
static int add_primitive_cube_gizmo_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
static void gizmo_placement_prop_matrix_set(const wmGizmo *gz, wmGizmoProperty *gz_prop, const void *value)
static void gizmo_mesh_placement_draw_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
void MESH_OT_primitive_cube_add_gizmo(wmOperatorType *ot)
static int add_primitive_cube_gizmo_exec(bContext *C, wmOperator *op)
static void gizmo_mesh_placement_update_from_op(GizmoPlacementGroup *ggd)
static void calc_initial_placement_point_from_view(bContext *C, const float mval[2], float r_location[3], float r_rotation[3][3])
static void gizmo_placement_exec(GizmoPlacementGroup *ggd)
static void gizmo_mesh_placement_modal_from_setup(const bContext *C, wmGizmoGroup *gzgroup)
static void gizmo_placement_prop_matrix_get(const wmGizmo *gz, wmGizmoProperty *gz_prop, void *value_p)
static void MESH_GGT_add_bounds(struct wmGizmoGroupType *gzgt)
static bool gizmo_mesh_placement_poll(const bContext *C, wmGizmoGroupType *gzgt)
static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *gzgroup)
struct GizmoPlacementGroup GizmoPlacementGroup
bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_slot_out, const bool select_extend, const char *fmt,...)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
return ret
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:2879
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
Definition: rna_access.c:2978
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
PropertyRNA * RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identifier, int rows, int columns, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3954
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void * regiondata
struct GizmoPlacementGroup::@448 data
struct wmGizmo * cage
Definition: BKE_main.h:121
float imat[4][4]
float obmat[4][4]
void * data
float viewinv[4][4]
View3DCursor cursor
char gizmo_flag
int ymin
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xy[2]
Definition: WM_types.h:682
wmGizmoGroupFnInit setup
const char * idname
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
struct wmGizmoMapType_Params gzmap_params
const char * name
wmGizmoGroupFnDrawPrepare draw_prepare
struct wmGizmoMap * parent_gzmap
const struct wmGizmoPropertyType * type
struct wmGizmoGroup * parent_gzgroup
float matrix_basis[4][4]
float matrix_offset[4][4]
float color[4]
struct PointerRNA * ptr
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct wmOperator * next
struct wmOperatorType * type
struct PointerRNA * ptr
struct wmEvent * eventstate
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_gizmo_modal_set_from_setup(struct wmGizmoMap *gzmap, struct bContext *C, struct wmGizmo *gz, int part_index, const wmEvent *event)
Definition: wm_gizmo.c:416
wmGizmo * WM_gizmo_new_ptr(const wmGizmoType *gzt, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition: wm_gizmo.c:81
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition: wm_gizmo.c:304
bool WM_gizmo_group_type_ensure_ptr(wmGizmoGroupType *gzgt)
void WM_gizmo_group_type_reinit_ptr(struct Main *bmain, wmGizmoGroupType *gzgt)
wmGizmoGroupType * WM_gizmogrouptype_find(const char *idname, bool quiet)
wmGizmoGroupType * WM_gizmogrouptype_append(void(*wtfunc)(struct wmGizmoGroupType *))
void WM_gizmo_target_property_def_func(wmGizmo *gz, const char *idname, const wmGizmoPropertyFnParams *params)
const wmGizmoType * WM_gizmotype_find(const char *idname, bool quiet)
Definition: wm_gizmo_type.c:45
wmOperator * WM_operator_last_redo(const bContext *C)