Blender V4.3
editmesh_add_gizmo.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include "MEM_guardedalloc.h"
12
13#include "DNA_object_types.h"
14#include "DNA_scene_types.h"
15
16#include "BKE_context.hh"
17#include "BKE_editmesh.hh"
18#include "BKE_object_types.hh"
19#include "BKE_scene.hh"
20
21#include "BLI_math_geom.h"
22#include "BLI_math_matrix.h"
23#include "BLI_math_vector.h"
24
25#include "ED_gizmo_library.hh"
26#include "ED_gizmo_utils.hh"
27#include "ED_mesh.hh"
28#include "ED_object.hh"
29#include "ED_screen.hh"
30#include "ED_undo.hh"
31#include "ED_view3d.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 "UI_resources.hh"
40
41#include "mesh_intern.hh" /* own include */
42
43/* -------------------------------------------------------------------- */
55 const float mval[2],
56 float r_location[3],
57 float r_rotation[3][3])
58{
59
60 Scene *scene = CTX_data_scene(C);
61 ARegion *region = CTX_wm_region(C);
62 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
63
64 bool use_mouse_project = true; /* TODO: make optional */
65
66 const blender::float4x4 cursor_matrix = scene->cursor.matrix<blender::float4x4>();
67 float orient_matrix[3][3];
68
69 const float dots[3] = {
70 dot_v3v3(rv3d->viewinv[2], cursor_matrix[0]),
71 dot_v3v3(rv3d->viewinv[2], cursor_matrix[1]),
72 dot_v3v3(rv3d->viewinv[2], cursor_matrix[2]),
73 };
74 const int axis = axis_dominant_v3_single(dots);
75
76 copy_v3_v3(orient_matrix[0], cursor_matrix[(axis + 1) % 3]);
77 copy_v3_v3(orient_matrix[1], cursor_matrix[(axis + 2) % 3]);
78 copy_v3_v3(orient_matrix[2], cursor_matrix[axis]);
79
80 if (dot_v3v3(rv3d->viewinv[2], orient_matrix[2]) < 0.0f) {
81 negate_v3(orient_matrix[2]);
82 }
83 if (is_negative_m3(orient_matrix)) {
84 swap_v3_v3(orient_matrix[0], orient_matrix[1]);
85 }
86
87 if (use_mouse_project) {
88 float plane[4];
89 plane_from_point_normal_v3(plane, cursor_matrix[3], orient_matrix[2]);
90 if (ED_view3d_win_to_3d_on_plane(region, plane, mval, true, r_location)) {
91 copy_m3_m3(r_rotation, orient_matrix);
92 return;
93 }
94 }
95
96 /* fallback */
97 copy_v3_v3(r_location, cursor_matrix[3]);
98 copy_m3_m3(r_rotation, orient_matrix);
99}
100
103/* -------------------------------------------------------------------- */
115
122{
123 wmOperator *op = ggd->data.op;
124 if (op == WM_operator_last_redo((bContext *)ggd->data.context)) {
126 }
127}
128
130{
131 wmOperator *op = ggd->data.op;
132 UNUSED_VARS(op);
133/* For now don't read back from the operator. */
134#if 0
136#endif
137}
138
139/* translate callbacks */
141 wmGizmoProperty *gz_prop,
142 void *value_p)
143{
145 wmOperator *op = ggd->data.op;
146 float *value = static_cast<float *>(value_p);
147 BLI_assert(gz_prop->type->array_length == 16);
148 UNUSED_VARS_NDEBUG(gz_prop);
149
150 if (value_p != ggd->cage->matrix_offset) {
152 static_cast<float(*)[4]>(value_p), ggd->cage->matrix_basis, ggd->cage->matrix_offset);
154 }
155}
156
158 wmGizmoProperty *gz_prop,
159 const void *value)
160{
162 wmOperator *op = ggd->data.op;
163
164 BLI_assert(gz_prop->type->array_length == 16);
165 UNUSED_VARS_NDEBUG(gz_prop);
166
167 float mat[4][4];
168 mul_m4_m4m4(mat, ggd->cage->matrix_basis, static_cast<const float(*)[4]>(value));
169
170 if (is_negative_m4(mat)) {
171 negate_mat3_m4(mat);
172 }
173
174 RNA_property_float_set_array(op->ptr, ggd->data.prop_matrix, &mat[0][0]);
175
177}
178
180{
182 C, gzgt, "MESH_OT_primitive_cube_add_gizmo");
183}
184
186{
187 GizmoPlacementGroup *ggd = static_cast<GizmoPlacementGroup *>(gzgroup->customdata);
188
189 /* Initial size. */
190 {
191 wmGizmo *gz = ggd->cage;
193
194 /* TODO: support zero scaled matrix in 'GIZMO_GT_cage_3d'. */
195 gz->matrix_offset[0][0] = 0.01;
196 gz->matrix_offset[1][1] = 0.01;
197 gz->matrix_offset[2][2] = 0.01;
198 gz->matrix_offset[3][3] = 1.0f;
199 }
200
201 /* Start off dragging. */
202 {
203 wmWindow *win = CTX_wm_window(C);
204 ARegion *region = CTX_wm_region(C);
205 wmGizmo *gz = ggd->cage;
206
207 {
208 float mat3[3][3];
209 float location[3];
210 float mval[2] = {
211 float(win->eventstate->xy[0] - region->winrct.xmin),
212 float(win->eventstate->xy[1] - region->winrct.ymin),
213 };
214 calc_initial_placement_point_from_view((bContext *)C, mval, location, mat3);
215 copy_m4_m3(gz->matrix_basis, mat3);
216 copy_v3_v3(gz->matrix_basis[3], location);
217 }
218
219 if (true) {
220 wmGizmoMap *gzmap = gzgroup->parent_gzmap;
222 (bContext *)C,
223 ggd->cage,
225 win->eventstate);
226 }
227 }
228}
229
230static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *gzgroup)
231{
233
234 if (op == nullptr || !STREQ(op->type->idname, "MESH_OT_primitive_cube_add_gizmo")) {
235 return;
236 }
237
238 GizmoPlacementGroup *ggd = static_cast<GizmoPlacementGroup *>(
239 MEM_callocN(sizeof(GizmoPlacementGroup), __func__));
240 gzgroup->customdata = ggd;
241
242 const wmGizmoType *gzt_cage = WM_gizmotype_find("GIZMO_GT_cage_3d", true);
243
244 ggd->cage = WM_gizmo_new_ptr(gzt_cage, gzgroup, nullptr);
245
247
248 RNA_enum_set(ggd->cage->ptr,
249 "transform",
252
254
255 ggd->data.context = (bContext *)C;
256 ggd->data.op = op;
257 ggd->data.prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
258
260
261 /* Setup property callbacks */
262 {
266 params.range_get_fn = nullptr;
267 params.user_data = nullptr;
269 }
270
272}
273
274static void gizmo_mesh_placement_draw_prepare(const bContext * /*C*/, wmGizmoGroup *gzgroup)
275{
276 GizmoPlacementGroup *ggd = static_cast<GizmoPlacementGroup *>(gzgroup->customdata);
277 if (ggd->data.op->next) {
279 }
281}
282
284{
285 gzgt->name = "Mesh Add Bounds";
286 gzgt->idname = "MESH_GGT_add_bounds";
287
289
292
296}
297
300/* -------------------------------------------------------------------- */
309{
310 Object *obedit = CTX_data_edit_object(C);
312 float matrix[4][4];
313
314 /* Get the matrix that defines the cube bounds (as set by the gizmo cage). */
315 {
316 PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
317 if (RNA_property_is_set(op->ptr, prop_matrix)) {
318 RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]);
319 invert_m4_m4(obedit->runtime->world_to_object.ptr(), obedit->object_to_world().ptr());
320 mul_m4_m4m4(matrix, obedit->world_to_object().ptr(), 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(static_cast<Mesh *>(obedit->data), nullptr);
332 }
333
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 {
343 return OPERATOR_CANCELLED;
344 }
345
348 params.calc_looptris = true;
349 params.calc_normals = false;
350 params.is_destructive = true;
351 EDBM_update(static_cast<Mesh *>(obedit->data), &params);
352
353 return OPERATOR_FINISHED;
354}
355
356static int add_primitive_cube_gizmo_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
357{
358 View3D *v3d = CTX_wm_view3d(C);
359
361 if (ret & OPERATOR_FINISHED) {
362 /* Setup gizmos */
363 if (v3d && ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0)) {
364 wmGizmoGroupType *gzgt = WM_gizmogrouptype_find("MESH_GGT_add_bounds", false);
366 Main *bmain = CTX_data_main(C);
368 }
369 }
370 }
371
372 return ret;
373}
374
376{
377 /* identifiers */
378 ot->name = "Add Cube";
379 ot->description = "Construct a cube mesh";
380 ot->idname = "MESH_OT_primitive_cube_add_gizmo";
381
382 /* api callbacks */
386
387 /* flags */
389
392
393 /* hidden props */
395 ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
397
399}
400
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:63
#define BLI_assert(a)
Definition BLI_assert.h:50
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:215
MINLINE int axis_dominant_v3_single(const float vec[3])
bool is_negative_m3(const float mat[3][3])
void zero_m4(float m[4][4])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
bool is_negative_m4(const float mat[4][4])
void negate_mat3_m4(float R[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
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 STREQ(a, b)
Object is a sort of wrapper for general info.
@ SCE_SELECT_VERTEX
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
@ V3D_GIZMO_HIDE
@ ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z
@ ED_GIZMO_CAGE_XFORM_FLAG_SCALE
@ ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE
@ ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED
bool ED_gizmo_poll_or_unlink_delayed_from_operator(const bContext *C, wmGizmoGroupType *gzgt, const char *idname)
void ED_mesh_uv_ensure(Mesh *mesh, const char *name)
Definition mesh_data.cc:363
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params)
void EDBM_selectmode_flush_ex(BMEditMesh *em, short selectmode)
bool ED_operator_editmesh_view3d(bContext *C)
int ED_undo_operator_repeat(bContext *C, wmOperator *op)
Definition ed_undo.cc:644
bool ED_view3d_win_to_3d_on_plane(const 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.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
void UI_GetThemeColor3fv(int colorid, float col[3])
@ TH_GIZMO_PRIMARY
@ WM_GIZMO_DRAW_VALUE
@ WM_GIZMOGROUPTYPE_3D
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
static int add_primitive_cube_gizmo_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void gizmo_placement_prop_matrix_set(const wmGizmo *gz, wmGizmoProperty *gz_prop, const void *value)
void MESH_OT_primitive_cube_add_gizmo(wmOperatorType *ot)
static void MESH_GGT_add_bounds(wmGizmoGroupType *gzgt)
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 bool gizmo_mesh_placement_poll(const bContext *C, wmGizmoGroupType *gzgt)
static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *gzgroup)
static void gizmo_mesh_placement_draw_prepare(const bContext *, wmGizmoGroup *gzgroup)
bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_slot_out, const bool select_extend, const char *fmt,...)
draw_view in_light_buf[] float
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void add_generic_props(wmOperatorType *ot, bool do_editmode)
void add_mesh_props(wmOperatorType *ot)
return ret
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PropertyRNA * RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identifier, const int rows, const int columns, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
struct GizmoPlacementGroup::@410 data
ObjectRuntimeHandle * runtime
float viewinv[4][4]
int xy[2]
Definition WM_types.hh:726
wmGizmoGroupFnInit setup
const char * idname
wmGizmoMapType_Params gzmap_params
eWM_GizmoFlagGroupTypeFlag flag
wmGizmoGroupFnPoll poll
wmGizmoGroupFnDrawPrepare draw_prepare
wmGizmoMap * parent_gzmap
const wmGizmoPropertyType * type
wmGizmoGroup * parent_gzgroup
float matrix_basis[4][4]
float matrix_offset[4][4]
float color[4]
PointerRNA * ptr
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
StructRNA * srna
Definition WM_types.hh:1080
struct wmOperator * next
struct wmOperatorType * type
struct PointerRNA * ptr
struct wmEvent * eventstate
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_gizmo_modal_set_from_setup(wmGizmoMap *gzmap, bContext *C, wmGizmo *gz, int part_index, const wmEvent *event)
Definition wm_gizmo.cc:415
wmGizmo * WM_gizmo_new_ptr(const wmGizmoType *gzt, wmGizmoGroup *gzgroup, PointerRNA *properties)
Definition wm_gizmo.cc:81
void WM_gizmo_set_flag(wmGizmo *gz, const int flag, const bool enable)
Definition wm_gizmo.cc:303
bool WM_gizmo_group_type_ensure_ptr(wmGizmoGroupType *gzgt)
void WM_gizmo_group_type_reinit_ptr(Main *bmain, wmGizmoGroupType *gzgt)
wmGizmoGroupType * WM_gizmogrouptype_append(void(*wtfunc)(wmGizmoGroupType *))
wmGizmoGroupType * WM_gizmogrouptype_find(const char *idname, bool quiet)
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)
wmOperator * WM_operator_last_redo(const bContext *C)