Blender  V3.3
object_modes.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
10 #include "DNA_gpencil_types.h"
11 #include "DNA_object_types.h"
12 #include "DNA_scene_types.h"
13 #include "DNA_workspace_types.h"
14 
15 #include "BLI_kdopbvh.h"
16 #include "BLI_math.h"
17 #include "BLI_utildefines.h"
18 
19 #include "PIL_time.h"
20 
21 #include "BLT_translation.h"
22 
23 #include "BKE_context.h"
24 #include "BKE_gpencil_modifier.h"
25 #include "BKE_layer.h"
26 #include "BKE_main.h"
27 #include "BKE_modifier.h"
28 #include "BKE_object.h"
29 #include "BKE_paint.h"
30 #include "BKE_report.h"
31 #include "BKE_scene.h"
32 #include "BKE_screen.h"
33 
34 #include "WM_api.h"
35 #include "WM_types.h"
36 
37 #include "RNA_access.h"
38 #include "RNA_define.h"
39 
40 #include "DEG_depsgraph.h"
41 #include "DEG_depsgraph_query.h"
42 
43 #include "ED_armature.h"
44 #include "ED_gpencil.h"
45 #include "ED_outliner.h"
46 #include "ED_screen.h"
48 #include "ED_undo.h"
49 #include "ED_view3d.h"
50 
51 #include "WM_toolsystem.h"
52 
53 #include "ED_object.h" /* own include */
54 #include "object_intern.h"
55 
56 /* -------------------------------------------------------------------- */
60 static const char *object_mode_op_string(eObjectMode mode)
61 {
62  if (mode & OB_MODE_EDIT) {
63  return "OBJECT_OT_editmode_toggle";
64  }
65  if (mode == OB_MODE_SCULPT) {
66  return "SCULPT_OT_sculptmode_toggle";
67  }
68  if (mode == OB_MODE_VERTEX_PAINT) {
69  return "PAINT_OT_vertex_paint_toggle";
70  }
71  if (mode == OB_MODE_WEIGHT_PAINT) {
72  return "PAINT_OT_weight_paint_toggle";
73  }
74  if (mode == OB_MODE_TEXTURE_PAINT) {
75  return "PAINT_OT_texture_paint_toggle";
76  }
77  if (mode == OB_MODE_PARTICLE_EDIT) {
78  return "PARTICLE_OT_particle_edit_toggle";
79  }
80  if (mode == OB_MODE_POSE) {
81  return "OBJECT_OT_posemode_toggle";
82  }
83  if (mode == OB_MODE_EDIT_GPENCIL) {
84  return "GPENCIL_OT_editmode_toggle";
85  }
86  if (mode == OB_MODE_PAINT_GPENCIL) {
87  return "GPENCIL_OT_paintmode_toggle";
88  }
89  if (mode == OB_MODE_SCULPT_GPENCIL) {
90  return "GPENCIL_OT_sculptmode_toggle";
91  }
92  if (mode == OB_MODE_WEIGHT_GPENCIL) {
93  return "GPENCIL_OT_weightmode_toggle";
94  }
95  if (mode == OB_MODE_VERTEX_GPENCIL) {
96  return "GPENCIL_OT_vertexmode_toggle";
97  }
98  if (mode == OB_MODE_SCULPT_CURVES) {
99  return "CURVES_OT_sculptmode_toggle";
100  }
101  return NULL;
102 }
103 
105 {
106  if (mode == OB_MODE_OBJECT) {
107  return true;
108  }
109 
110  switch (ob->type) {
111  case OB_MESH:
114  return true;
115  }
116  if (mode & OB_MODE_PARTICLE_EDIT) {
118  return true;
119  }
120  }
121  break;
122  case OB_CURVES_LEGACY:
123  case OB_SURF:
124  case OB_FONT:
125  case OB_MBALL:
126  if (mode & OB_MODE_EDIT) {
127  return true;
128  }
129  break;
130  case OB_LATTICE:
131  if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT)) {
132  return true;
133  }
134  break;
135  case OB_ARMATURE:
136  if (mode & (OB_MODE_EDIT | OB_MODE_POSE)) {
137  return true;
138  }
139  break;
140  case OB_GPENCIL:
143  return true;
144  }
145  break;
146  case OB_CURVES:
147  if (U.experimental.use_new_curves_tools) {
148  if (mode & OB_MODE_EDIT) {
149  return true;
150  }
151  }
152  if (mode & OB_MODE_SCULPT_CURVES) {
153  return true;
154  }
155  break;
156  }
157 
158  return false;
159 }
160 
162 {
163  bool ok;
164  if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
165  const char *opstring = object_mode_op_string(ob->mode);
166 
168  ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
169  if (!ok) {
170  wmOperatorType *ot = WM_operatortype_find(opstring, false);
171  BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
172  }
173  }
174  else {
175  ok = true;
176  }
177 
178  return ok;
179 }
180 
183 /* -------------------------------------------------------------------- */
191 bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports)
192 {
194  ViewLayer *view_layer = CTX_data_view_layer(C);
195  Object *ob = OBACT(view_layer);
196  if (ob == NULL) {
197  return (mode == OB_MODE_OBJECT);
198  }
199 
200  if ((ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
201  mode = OB_MODE_EDIT_GPENCIL;
202  }
203 
204  if (ob->mode == mode) {
205  return true;
206  }
207 
208  if (!ED_object_mode_compat_test(ob, mode)) {
209  return false;
210  }
211 
212  const char *opstring = object_mode_op_string((mode == OB_MODE_OBJECT) ? ob->mode : mode);
213  wmOperatorType *ot = WM_operatortype_find(opstring, false);
214 
215  if (!use_undo) {
216  wm->op_undo_depth++;
217  }
219  if (!use_undo) {
220  wm->op_undo_depth--;
221  }
222 
223  if (ob->mode != mode) {
224  BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
225  return false;
226  }
227 
228  return true;
229 }
230 
232 {
233  /* Don't do undo push by default, since this may be called by lower level code. */
234  return ED_object_mode_set_ex(C, mode, true, NULL);
235 }
236 
241 static bool ed_object_mode_generic_exit_ex(struct Main *bmain,
242  struct Depsgraph *depsgraph,
243  struct Scene *scene,
244  struct Object *ob,
245  bool only_test)
246 {
247  BLI_assert((bmain == NULL) == only_test);
248  if (ob->mode & OB_MODE_EDIT) {
249  if (BKE_object_is_in_editmode(ob)) {
250  if (only_test) {
251  return true;
252  }
254  }
255  }
256  else if (ob->mode & OB_MODE_VERTEX_PAINT) {
257  if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
258  if (only_test) {
259  return true;
260  }
262  }
263  }
264  else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
265  if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
266  if (only_test) {
267  return true;
268  }
270  }
271  }
272  else if (ob->mode & OB_MODE_SCULPT) {
273  if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
274  if (only_test) {
275  return true;
276  }
278  }
279  }
280  else if (ob->mode & OB_MODE_POSE) {
281  if (ob->pose != NULL) {
282  if (only_test) {
283  return true;
284  }
285  ED_object_posemode_exit_ex(bmain, ob);
286  }
287  }
288  else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
289  if (only_test) {
290  return true;
291  }
293  }
294  else if (ob->mode & OB_MODE_PARTICLE_EDIT) {
295  if (only_test) {
296  return true;
297  }
299  }
300  else if (ob->type == OB_GPENCIL) {
301  /* Accounted for above. */
302  BLI_assert((ob->mode & OB_MODE_OBJECT) == 0);
303  if (only_test) {
304  return true;
305  }
306  ED_object_gpencil_exit(bmain, ob);
307  }
308  else {
309  if (only_test) {
310  return false;
311  }
312  BLI_assert((ob->mode & OB_MODE_ALL_MODE_DATA) == 0);
313  }
314 
315  return false;
316 }
317 
318 /* When locked, it's almost impossible to select the pose-object
319  * then the mesh-object to enter weight paint mode.
320  * Even when the object mode is not locked this is inconvenient - so allow in either case.
321  *
322  * In this case move our pose object in/out of pose mode.
323  * This is in fits with the convention of selecting multiple objects and entering a mode.
324  */
326  Main *bmain,
327  Object *ob_arm,
328  const bool is_mode_set)
329 {
330  View3D *v3d = CTX_wm_view3d(C);
331  ViewLayer *view_layer = CTX_data_view_layer(C);
332 
333  if (ob_arm != NULL) {
334  const Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm);
335  if (base_arm && BASE_VISIBLE(v3d, base_arm)) {
336  if (is_mode_set) {
337  if ((ob_arm->mode & OB_MODE_POSE) != 0) {
338  ED_object_posemode_exit_ex(bmain, ob_arm);
339  }
340  }
341  else {
342  /* Only check selected status when entering weight-paint mode
343  * because we may have multiple armature objects.
344  * Selecting one will de-select the other, which would leave it in pose-mode
345  * when exiting weight paint mode. While usable, this looks like inconsistent
346  * behavior from a user perspective. */
347  if (base_arm->flag & BASE_SELECTED) {
348  if ((ob_arm->mode & OB_MODE_POSE) == 0) {
349  ED_object_posemode_enter_ex(bmain, ob_arm);
350  }
351  }
352  }
353  }
354  }
355 }
356 
358  Main *bmain,
359  Object *ob,
360  const bool is_mode_set)
361 {
362  if (ob->type == OB_GPENCIL) {
363  GpencilVirtualModifierData virtualModifierData;
365  &virtualModifierData);
366  for (; md; md = md->next) {
367  if (md->type == eGpencilModifierType_Armature) {
369  Object *ob_arm = amd->object;
370  ed_object_posemode_set_for_weight_paint_ex(C, bmain, ob_arm, is_mode_set);
371  }
372  }
373  }
374  else {
375  VirtualModifierData virtualModifierData;
376  ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
377  for (; md; md = md->next) {
378  if (md->type == eModifierType_Armature) {
380  Object *ob_arm = amd->object;
381  ed_object_posemode_set_for_weight_paint_ex(C, bmain, ob_arm, is_mode_set);
382  }
383  }
384  }
385 }
386 
388  struct Depsgraph *depsgraph,
389  struct Scene *scene,
390  struct Object *ob)
391 {
392  ed_object_mode_generic_exit_ex(bmain, depsgraph, scene, ob, false);
393 }
394 
396 {
398 }
399 
402 /* -------------------------------------------------------------------- */
410 {
411  if (!CTX_wm_region_view3d(C)) {
412  return false;
413  }
414  const Object *ob = CTX_data_active_object(C);
415  return ob && (ob->mode != OB_MODE_OBJECT);
416 }
417 
418 /* Update the viewport rotation origin to the mouse cursor. */
419 static void object_transfer_mode_reposition_view_pivot(bContext *C, const int mval[2])
420 {
421  ARegion *region = CTX_wm_region(C);
423 
424  float global_loc[3];
425  if (!ED_view3d_autodist_simple(region, mval, global_loc, 0, NULL)) {
426  return;
427  }
429  copy_v3_v3(ups->average_stroke_accum, global_loc);
430  ups->average_stroke_counter = 1;
431  ups->last_stroke_valid = true;
432 }
433 
435 {
437  Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst);
439 }
440 
442 {
444  ViewLayer *view_layer = CTX_data_view_layer(C);
445 
446  if (base_dst == NULL) {
447  return false;
448  }
449 
450  Object *ob_dst = base_dst->object;
451  Object *ob_src = CTX_data_active_object(C);
452 
453  if (ob_dst == ob_src) {
454  return false;
455  }
456 
457  const eObjectMode last_mode = (eObjectMode)ob_src->mode;
458  if (!ED_object_mode_compat_test(ob_dst, last_mode)) {
459  return false;
460  }
461 
462  bool mode_transferred = false;
463 
465 
466  if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) {
467  Object *ob_dst_orig = DEG_get_original_object(ob_dst);
468  Base *base = BKE_view_layer_base_find(view_layer, ob_dst_orig);
472 
473  ED_undo_push(C, "Change Active");
474 
475  ob_dst_orig = DEG_get_original_object(ob_dst);
476  ED_object_mode_set_ex(C, last_mode, true, op->reports);
477 
478  if (RNA_boolean_get(op->ptr, "use_flash_on_transfer")) {
480  }
481 
484 
486  mode_transferred = true;
487  }
488 
490  return mode_transferred;
491 }
492 
493 static int object_transfer_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event)
494 {
495  Object *ob_src = CTX_data_active_object(C);
496  const eObjectMode src_mode = (eObjectMode)ob_src->mode;
497 
498  Base *base_dst = ED_view3d_give_base_under_cursor(C, event->mval);
499  const bool mode_transferred = object_transfer_mode_to_base(C, op, base_dst);
500  if (!mode_transferred) {
501  return OPERATOR_CANCELLED;
502  }
503 
504  if (src_mode & OB_MODE_ALL_PAINT) {
506  }
507 
508  return OPERATOR_FINISHED;
509 }
510 
512 {
513  /* identifiers */
514  ot->name = "Transfer Mode";
515  ot->idname = "OBJECT_OT_transfer_mode";
516  ot->description =
517  "Switches the active object and assigns the same mode to a new one under the mouse cursor, "
518  "leaving the active mode in the current one";
519 
520  /* api callbacks */
523 
524  /* Undo push is handled by the operator. */
526 
528 
530  "use_flash_on_transfer",
531  true,
532  "Flash On Transfer",
533  "Flash the target object when transferring the mode");
534 }
535 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
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 Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:793
struct GpencilModifierData * BKE_gpencil_modifiers_get_virtual_modifierlist(const struct Object *ob, struct GpencilVirtualModifierData *data)
void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer)
Definition: layer.c:388
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, struct Base *selbase)
Definition: layer.c:397
struct ModifierData * BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, struct VirtualModifierData *data)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const struct Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_original_object(struct Object *object)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_SELECT
Definition: DNA_ID.h:818
@ eGpencilModifierType_Armature
@ BASE_SELECTED
@ eModifierType_Armature
#define OB_MODE_ALL_PAINT
#define OB_MODE_ALL_MODE_DATA
eObjectMode
@ OB_MODE_VERTEX_GPENCIL
@ OB_MODE_EDIT_GPENCIL
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_WEIGHT_GPENCIL
@ OB_MODE_SCULPT
@ OB_MODE_SCULPT_CURVES
@ OB_MODE_SCULPT_GPENCIL
@ OB_MODE_POSE
@ OB_MODE_TEXTURE_PAINT
@ OB_MODE_OBJECT
@ OB_MODE_VERTEX_PAINT
@ OB_MODE_PAINT_GPENCIL
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_GPENCIL
#define OBACT(_view_layer)
#define BASE_VISIBLE(v3d, base)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
bool ED_object_particle_edit_mode_supported(const Object *ob)
void ED_object_vpaintmode_exit_ex(struct Object *ob)
@ EM_FREEDATA
Definition: ED_object.h:242
void ED_object_wpaintmode_exit_ex(struct Object *ob)
bool ED_object_editmode_exit_ex(struct Main *bmain, struct Scene *scene, struct Object *obedit, int flag)
Definition: object_edit.c:653
void ED_object_texture_paint_mode_exit_ex(struct Main *bmain, struct Scene *scene, Object *ob)
Definition: paint_image.cc:823
void ED_object_particle_edit_mode_exit_ex(struct Scene *scene, Object *ob)
void ED_object_sculptmode_exit_ex(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: sculpt_ops.c:423
void ED_outliner_select_sync_from_object_tag(struct bContext *C)
void ED_undo_group_begin(struct bContext *C)
Definition: ed_undo.c:88
void ED_undo_push(struct bContext *C, const char *str)
Definition: ed_undo.c:100
void ED_undo_group_end(struct bContext *C)
Definition: ed_undo.c:94
struct Base * ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2])
bool ED_view3d_autodist_simple(struct ARegion *region, const int mval[2], float mouse_worldloc[3], int margin, const float *force_depth)
Platform independent time functions.
#define C
Definition: RandGen.cpp:25
@ OPTYPE_DEPENDS_ON_CURSOR
Definition: WM_types.h:184
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_OB_SELECT
Definition: WM_types.h:390
#define NC_SCENE
Definition: WM_types.h:328
@ WM_OP_EXEC_REGION_WIN
Definition: WM_types.h:209
unsigned int U
Definition: btGjkEpa3.h:78
Scene scene
const Depsgraph * depsgraph
bool ED_object_gpencil_exit(struct Main *bmain, Object *ob)
void ED_object_posemode_set_for_weight_paint(bContext *C, Main *bmain, Object *ob, const bool is_mode_set)
Definition: object_modes.c:357
bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
Definition: object_modes.c:104
bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, ReportList *reports)
Definition: object_modes.c:161
static bool object_transfer_mode_poll(bContext *C)
Definition: object_modes.c:409
static bool ed_object_mode_generic_exit_ex(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, bool only_test)
Definition: object_modes.c:241
static int object_transfer_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: object_modes.c:493
void ED_object_mode_generic_exit(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: object_modes.c:387
static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base_dst)
Definition: object_modes.c:441
bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, const struct Object *ob)
Definition: object_modes.c:395
static void ed_object_posemode_set_for_weight_paint_ex(bContext *C, Main *bmain, Object *ob_arm, const bool is_mode_set)
Definition: object_modes.c:325
static void object_transfer_mode_reposition_view_pivot(bContext *C, const int mval[2])
Definition: object_modes.c:419
void OBJECT_OT_transfer_mode(wmOperatorType *ot)
Definition: object_modes.c:511
static void object_overlay_mode_transfer_animation_start(bContext *C, Object *ob_dst)
Definition: object_modes.c:434
static const char * object_mode_op_string(eObjectMode mode)
Definition: object_modes.c:60
bool ED_object_mode_set(bContext *C, eObjectMode mode)
Definition: object_modes.c:231
bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports)
Definition: object_modes.c:191
bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob)
Definition: pose_edit.c:80
bool ED_object_posemode_exit_ex(struct Main *bmain, Object *ob)
Definition: pose_edit.c:115
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
short flag
struct Object * object
struct GpencilModifierData * next
Definition: BKE_main.h:121
struct ModifierData * next
double overlay_mode_transfer_start_time
struct bPose * pose
Object_Runtime runtime
struct SculptSession * sculpt
struct ToolSettings * toolsettings
eObjectMode mode_type
Definition: BKE_paint.h:642
struct UnifiedPaintSettings unified_paint_settings
int mval[2]
Definition: WM_types.h:684
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
int cursor_pending
Definition: WM_types.h:996
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
struct ReportList * reports
struct PointerRNA * ptr
double PIL_check_seconds_timer(void)
Definition: time.c:64
@ WM_CURSOR_EYEDROPPER
Definition: wm_cursors.h:35
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
int WM_operator_name_call(bContext *C, const char *opstring, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
wmOperatorType * ot
Definition: wm_files.c:3479
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
void WM_toolsystem_update_from_context_view3d(bContext *C)