Blender  V2.93
editmesh_add_gizmo.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include "MEM_guardedalloc.h"
24 
25 #include "BLI_math.h"
26 
27 #include "DNA_object_types.h"
28 #include "DNA_scene_types.h"
29 
30 #include "BKE_context.h"
31 #include "BKE_editmesh.h"
32 #include "BKE_scene.h"
33 
34 #include "ED_gizmo_library.h"
35 #include "ED_gizmo_utils.h"
36 #include "ED_mesh.h"
37 #include "ED_object.h"
38 #include "ED_screen.h"
39 #include "ED_undo.h"
40 #include "ED_view3d.h"
41 
42 #include "RNA_access.h"
43 #include "RNA_define.h"
44 
45 #include "WM_api.h"
46 #include "WM_types.h"
47 
48 #include "UI_resources.h"
49 
50 #include "BLT_translation.h"
51 
52 #include "mesh_intern.h" /* own include */
53 
54 /* -------------------------------------------------------------------- */
66  const float mval[2],
67  float r_location[3],
68  float r_rotation[3][3])
69 {
70 
72  ARegion *region = CTX_wm_region(C);
73  RegionView3D *rv3d = region->regiondata;
74 
75  bool use_mouse_project = true; /* TODO: make optional */
76 
77  float cursor_matrix[4][4];
78  float orient_matrix[3][3];
79  BKE_scene_cursor_to_mat4(&scene->cursor, cursor_matrix);
80 
81  const float dots[3] = {
82  dot_v3v3(rv3d->viewinv[2], cursor_matrix[0]),
83  dot_v3v3(rv3d->viewinv[2], cursor_matrix[1]),
84  dot_v3v3(rv3d->viewinv[2], cursor_matrix[2]),
85  };
86  const int axis = axis_dominant_v3_single(dots);
87 
88  copy_v3_v3(orient_matrix[0], cursor_matrix[(axis + 1) % 3]);
89  copy_v3_v3(orient_matrix[1], cursor_matrix[(axis + 2) % 3]);
90  copy_v3_v3(orient_matrix[2], cursor_matrix[axis]);
91 
92  if (dot_v3v3(rv3d->viewinv[2], orient_matrix[2]) < 0.0f) {
93  negate_v3(orient_matrix[2]);
94  }
95  if (is_negative_m3(orient_matrix)) {
96  swap_v3_v3(orient_matrix[0], orient_matrix[1]);
97  }
98 
99  if (use_mouse_project) {
100  float plane[4];
101  plane_from_point_normal_v3(plane, cursor_matrix[3], orient_matrix[2]);
102  if (ED_view3d_win_to_3d_on_plane(region, plane, mval, true, r_location)) {
103  copy_m3_m3(r_rotation, orient_matrix);
104  return;
105  }
106  }
107 
108  /* fallback */
109  copy_v3_v3(r_location, cursor_matrix[3]);
110  copy_m3_m3(r_rotation, orient_matrix);
111 }
112 
115 /* -------------------------------------------------------------------- */
119 typedef struct GizmoPlacementGroup {
120  struct wmGizmo *cage;
121  struct {
125  } data;
127 
134 {
135  wmOperator *op = ggd->data.op;
136  if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
138  }
139 }
140 
142 {
143  wmOperator *op = ggd->data.op;
144  UNUSED_VARS(op);
145  /* For now don't read back from the operator. */
146 #if 0
148 #endif
149 }
150 
151 /* translate callbacks */
153  wmGizmoProperty *gz_prop,
154  void *value_p)
155 {
157  wmOperator *op = ggd->data.op;
158  float *value = value_p;
159  BLI_assert(gz_prop->type->array_length == 16);
160  UNUSED_VARS_NDEBUG(gz_prop);
161 
162  if (value_p != ggd->cage->matrix_offset) {
163  mul_m4_m4m4(value_p, ggd->cage->matrix_basis, ggd->cage->matrix_offset);
165  }
166 }
167 
169  wmGizmoProperty *gz_prop,
170  const void *value)
171 {
173  wmOperator *op = ggd->data.op;
174 
175  BLI_assert(gz_prop->type->array_length == 16);
176  UNUSED_VARS_NDEBUG(gz_prop);
177 
178  float mat[4][4];
179  mul_m4_m4m4(mat, ggd->cage->matrix_basis, value);
180 
181  if (is_negative_m4(mat)) {
182  negate_mat3_m4(mat);
183  }
184 
185  RNA_property_float_set_array(op->ptr, ggd->data.prop_matrix, &mat[0][0]);
186 
188 }
189 
191 {
193  C, gzgt, "MESH_OT_primitive_cube_add_gizmo");
194 }
195 
197 {
198  GizmoPlacementGroup *ggd = gzgroup->customdata;
199 
200  /* Initial size. */
201  {
202  wmGizmo *gz = ggd->cage;
203  zero_m4(gz->matrix_offset);
204 
205  /* TODO: support zero scaled matrix in 'GIZMO_GT_cage_3d'. */
206  gz->matrix_offset[0][0] = 0.01;
207  gz->matrix_offset[1][1] = 0.01;
208  gz->matrix_offset[2][2] = 0.01;
209  gz->matrix_offset[3][3] = 1.0f;
210  }
211 
212  /* Start off dragging. */
213  {
214  wmWindow *win = CTX_wm_window(C);
215  ARegion *region = CTX_wm_region(C);
216  wmGizmo *gz = ggd->cage;
217 
218  {
219  float mat3[3][3];
220  float location[3];
222  (float[2]){
223  win->eventstate->x - region->winrct.xmin,
224  win->eventstate->y - region->winrct.ymin,
225  },
226  location,
227  mat3);
228  copy_m4_m3(gz->matrix_basis, mat3);
229  copy_v3_v3(gz->matrix_basis[3], location);
230  }
231 
232  if (1) {
233  wmGizmoMap *gzmap = gzgroup->parent_gzmap;
235  (bContext *)C,
236  ggd->cage,
238  win->eventstate);
239  }
240  }
241 }
242 
243 static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *gzgroup)
244 {
246 
247  if (op == NULL || !STREQ(op->type->idname, "MESH_OT_primitive_cube_add_gizmo")) {
248  return;
249  }
250 
251  struct GizmoPlacementGroup *ggd = MEM_callocN(sizeof(GizmoPlacementGroup), __func__);
252  gzgroup->customdata = ggd;
253 
254  const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
255 
256  ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
257 
259 
260  RNA_enum_set(ggd->cage->ptr,
261  "transform",
264 
266 
267  ggd->data.context = (bContext *)C;
268  ggd->data.op = op;
269  ggd->data.prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
270 
272 
273  /* Setup property callbacks */
274  {
276  "matrix",
277  &(const struct wmGizmoPropertyFnParams){
278  .value_get_fn = gizmo_placement_prop_matrix_get,
279  .value_set_fn = gizmo_placement_prop_matrix_set,
280  .range_get_fn = NULL,
281  .user_data = NULL,
282  });
283  }
284 
286 }
287 
289 {
290  GizmoPlacementGroup *ggd = gzgroup->customdata;
291  if (ggd->data.op->next) {
293  }
295 }
296 
297 static void MESH_GGT_add_bounds(struct wmGizmoGroupType *gzgt)
298 {
299  gzgt->name = "Mesh Add Bounds";
300  gzgt->idname = "MESH_GGT_add_bounds";
301 
302  gzgt->flag = WM_GIZMOGROUPTYPE_3D;
303 
306 
310 }
311 
314 /* -------------------------------------------------------------------- */
323 {
324  Object *obedit = CTX_data_edit_object(C);
325  BMEditMesh *em = BKE_editmesh_from_object(obedit);
326  float matrix[4][4];
327 
328  /* Get the matrix that defines the cube bounds (as set by the gizmo cage). */
329  {
333  invert_m4_m4(obedit->imat, obedit->obmat);
334  mul_m4_m4m4(matrix, obedit->imat, matrix);
335  }
336  else {
337  /* For the first update the widget may not set the matrix. */
338  return OPERATOR_FINISHED;
339  }
340  }
341 
342  const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
343 
344  if (calc_uvs) {
346  }
347 
348  if (!EDBM_op_call_and_selectf(em,
349  op,
350  "verts.out",
351  false,
352  "create_cube matrix=%m4 size=%f calc_uvs=%b",
353  matrix,
354  1.0f,
355  calc_uvs)) {
356  return OPERATOR_CANCELLED;
357  }
358 
360  EDBM_update_generic(obedit->data, true, true);
361 
362  return OPERATOR_FINISHED;
363 }
364 
366  wmOperator *op,
367  const wmEvent *UNUSED(event))
368 {
369  View3D *v3d = CTX_wm_view3d(C);
370 
372  if (ret & OPERATOR_FINISHED) {
373  /* Setup gizmos */
374  if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
375  wmGizmoGroupType *gzgt = WM_gizmogrouptype_find("MESH_GGT_add_bounds", false);
376  if (!WM_gizmo_group_type_ensure_ptr(gzgt)) {
377  struct Main *bmain = CTX_data_main(C);
378  WM_gizmo_group_type_reinit_ptr(bmain, gzgt);
379  }
380  }
381  }
382 
383  return ret;
384 }
385 
387 {
388  /* identifiers */
389  ot->name = "Add Cube";
390  ot->description = "Construct a cube mesh";
391  ot->idname = "MESH_OT_primitive_cube_add_gizmo";
392 
393  /* api callbacks */
397 
398  /* flags */
400 
403 
404  /* hidden props */
406  ot->srna, "matrix", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
408 
410 }
411 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:85
void BKE_scene_cursor_to_mat4(const struct View3DCursor *cursor, float mat[4][4])
#define BLI_assert(a)
Definition: BLI_assert.h:58
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:243
MINLINE int axis_dominant_v3_single(const float vec[3])
bool is_negative_m3(const float mat[3][3])
Definition: math_matrix.c:2583
void zero_m4(float m[4][4])
Definition: math_matrix.c:46
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:89
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:120
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
bool is_negative_m4(const float mat[4][4])
Definition: math_matrix.c:2590
void negate_mat3_m4(float R[4][4])
Definition: math_matrix.c:1004
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_CAGE2D_XFORM_FLAG_TRANSLATE
@ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED
@ ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE
@ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z
bool ED_gizmo_poll_or_unlink_delayed_from_operator(const struct bContext *C, struct wmGizmoGroupType *gzgt, const char *idname)
void EDBM_selectmode_flush_ex(struct BMEditMesh *em, const short selectmode)
void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name)
Definition: mesh_data.c:318
void EDBM_update_generic(struct Mesh *me, const bool do_tessellation, const bool is_destructive)
void ED_object_add_generic_props(struct wmOperatorType *ot, bool do_editmode)
Definition: object_add.c:397
void ED_object_add_mesh_props(struct wmOperatorType *ot)
Definition: object_add.c:450
bool ED_operator_editmesh_view3d(struct bContext *C)
Definition: screen_ops.c:413
int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op)
Definition: ed_undo.c:678
bool ED_view3d_win_to_3d_on_plane(const struct ARegion *region, const float plane[4], const float mval[2], const bool do_clip, float r_out[3])
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
#define C
Definition: RandGen.cpp:39
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1191
@ TH_GIZMO_PRIMARY
Definition: UI_resources.h:321
@ WM_GIZMO_DRAW_VALUE
@ WM_GIZMOGROUPTYPE_3D
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
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:45
return ret
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:3033
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:6655
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
Definition: rna_access.c:3132
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
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:3943
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
void * regiondata
struct wmGizmo * cage
struct GizmoPlacementGroup::@428 data
Definition: BKE_main.h:116
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:80
int xmin
Definition: DNA_vec_types.h:79
int y
Definition: WM_types.h:581
int x
Definition: WM_types.h:581
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:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct wmOperator * next
struct wmOperatorType * type
struct PointerRNA * ptr
struct wmEvent * eventstate
wmOperatorType * ot
Definition: wm_files.c:3156
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:463
wmGizmo * WM_gizmo_new_ptr(const wmGizmoType *gzt, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition: wm_gizmo.c:96
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition: wm_gizmo.c:339
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:58
wmOperator * WM_operator_last_redo(const bContext *C)