GPencil: Change trace tooltip for Threshold
[blender.git] / source / blender / editors / object / object_edit.c
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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edobj
22  */
23
24 #include <ctype.h>
25 #include <float.h>
26 #include <math.h>
27 #include <stddef.h> /* for offsetof */
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_blenlib.h"
35 #include "BLI_ghash.h"
36 #include "BLI_utildefines.h"
37
38 #include "BLT_translation.h"
39
40 #include "DNA_armature_types.h"
41 #include "DNA_collection_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_gpencil_types.h"
44 #include "DNA_lattice_types.h"
45 #include "DNA_material_types.h"
46 #include "DNA_mesh_types.h"
47 #include "DNA_meshdata_types.h"
48 #include "DNA_meta_types.h"
49 #include "DNA_object_force_types.h"
50 #include "DNA_object_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_vfont_types.h"
53 #include "DNA_workspace_types.h"
54
55 #include "IMB_imbuf_types.h"
56
57 #include "BKE_anim_visualization.h"
58 #include "BKE_collection.h"
59 #include "BKE_constraint.h"
60 #include "BKE_context.h"
61 #include "BKE_curve.h"
62 #include "BKE_editlattice.h"
63 #include "BKE_editmesh.h"
64 #include "BKE_effect.h"
65 #include "BKE_global.h"
66 #include "BKE_image.h"
67 #include "BKE_lattice.h"
68 #include "BKE_layer.h"
69 #include "BKE_main.h"
70 #include "BKE_material.h"
71 #include "BKE_mball.h"
72 #include "BKE_mesh.h"
73 #include "BKE_modifier.h"
74 #include "BKE_object.h"
75 #include "BKE_paint.h"
76 #include "BKE_particle.h"
77 #include "BKE_pointcache.h"
78 #include "BKE_report.h"
79 #include "BKE_scene.h"
80 #include "BKE_softbody.h"
81 #include "BKE_workspace.h"
82
83 #include "DEG_depsgraph.h"
84 #include "DEG_depsgraph_build.h"
85
86 #include "ED_anim_api.h"
87 #include "ED_armature.h"
88 #include "ED_curve.h"
89 #include "ED_gpencil.h"
90 #include "ED_image.h"
91 #include "ED_lattice.h"
92 #include "ED_mball.h"
93 #include "ED_mesh.h"
94 #include "ED_object.h"
95 #include "ED_outliner.h"
96 #include "ED_screen.h"
97 #include "ED_undo.h"
98
99 #include "RNA_access.h"
100 #include "RNA_define.h"
101 #include "RNA_enum_types.h"
102
103 #include "UI_interface_icons.h"
104
105 #include "CLG_log.h"
106
107 /* for menu/popup icons etc etc*/
108
109 #include "UI_interface.h"
110 #include "UI_resources.h"
111
112 #include "WM_api.h"
113 #include "WM_message.h"
114 #include "WM_toolsystem.h"
115 #include "WM_types.h"
116
117 #include "object_intern.h" /* own include */
118
119 static CLG_LogRef LOG = {"ed.object.edit"};
120
121 /* prototypes */
122 typedef struct MoveToCollectionData MoveToCollectionData;
123 static void move_to_collection_menus_items(struct uiLayout *layout,
124                                            struct MoveToCollectionData *menu);
125 static ListBase selected_objects_get(bContext *C);
126
127 /* -------------------------------------------------------------------- */
128 /** \name Internal Utilities
129  * \{ */
130
131 Object *ED_object_context(const bContext *C)
132 {
133   return CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
134 }
135
136 /* find the correct active object per context
137  * note: context can be NULL when called from a enum with PROP_ENUM_NO_CONTEXT */
138 Object *ED_object_active_context(const bContext *C)
139 {
140   Object *ob = NULL;
141   if (C) {
142     ob = ED_object_context(C);
143     if (!ob) {
144       ob = CTX_data_active_object(C);
145     }
146   }
147   return ob;
148 }
149
150 /**
151  * Return an array of objects:
152  * - When in the property space, return the pinned or active object.
153  * - When in edit-mode/pose-mode, return an array of objects in the mode.
154  * - Otherwise return selected objects,
155  *   the callers \a filter_fn needs to check of they are editable
156  *   (assuming they need to be modified).
157  */
158 Object **ED_object_array_in_mode_or_selected(bContext *C,
159                                              bool (*filter_fn)(Object *ob, void *user_data),
160                                              void *filter_user_data,
161                                              uint *r_objects_len)
162 {
163   ScrArea *area = CTX_wm_area(C);
164   ViewLayer *view_layer = CTX_data_view_layer(C);
165   Object *ob_active = OBACT(view_layer);
166   ID *id_pin = NULL;
167   const bool use_objects_in_mode = (ob_active != NULL) &&
168                                    (ob_active->mode & (OB_MODE_EDIT | OB_MODE_POSE));
169   const char space_type = area ? area->spacetype : SPACE_EMPTY;
170   Object **objects;
171
172   Object *ob = NULL;
173   bool use_ob = true;
174
175   if (space_type == SPACE_PROPERTIES) {
176     SpaceProperties *sbuts = area->spacedata.first;
177     id_pin = sbuts->pinid;
178   }
179
180   if (id_pin && (GS(id_pin->name) == ID_OB)) {
181     /* Pinned data takes priority, in this case ignore selection & other objects in the mode. */
182     ob = (Object *)id_pin;
183   }
184   else if ((space_type == SPACE_PROPERTIES) && (use_objects_in_mode == false)) {
185     /* When using the space-properties, we don't want to use the entire selection
186      * as the current active object may not be selected.
187      *
188      * This is not the case when we're in a mode that supports multi-mode editing,
189      * since the active object and all other objects in the mode will be included
190      * irrespective of selection. */
191     ob = ob_active;
192   }
193   else if (ob_active && (ob_active->mode &
194                          (OB_MODE_ALL_PAINT | OB_MODE_ALL_SCULPT | OB_MODE_ALL_PAINT_GPENCIL))) {
195     /* When painting, limit to active. */
196     ob = ob_active;
197   }
198   else {
199     /* Otherwise use full selection. */
200     use_ob = false;
201   }
202
203   if (use_ob) {
204     if ((ob != NULL) && !filter_fn(ob, filter_user_data)) {
205       ob = NULL;
206     }
207     *r_objects_len = (ob != NULL) ? 1 : 0;
208     objects = MEM_mallocN(sizeof(*objects) * *r_objects_len, __func__);
209     if (ob != NULL) {
210       objects[0] = ob;
211     }
212   }
213   else {
214     const View3D *v3d = (space_type == SPACE_VIEW3D) ? area->spacedata.first : NULL;
215     /* When in a mode that supports multiple active objects, use "objects in mode"
216      * instead of the object's selection. */
217     if (use_objects_in_mode) {
218       objects = BKE_view_layer_array_from_objects_in_mode(view_layer,
219                                                           v3d,
220                                                           r_objects_len,
221                                                           {.object_mode = ob_active->mode,
222                                                            .no_dup_data = true,
223                                                            .filter_fn = filter_fn,
224                                                            .filter_userdata = filter_user_data});
225     }
226     else {
227       objects = BKE_view_layer_array_selected_objects(
228           view_layer,
229           v3d,
230           r_objects_len,
231           {.no_dup_data = true, .filter_fn = filter_fn, .filter_userdata = filter_user_data});
232     }
233   }
234   return objects;
235 }
236
237 /** \} */
238
239 /* -------------------------------------------------------------------- */
240 /** \name Hide Operator
241  * \{ */
242
243 static bool object_hide_poll(bContext *C)
244 {
245   if (CTX_wm_space_outliner(C) != NULL) {
246     return ED_outliner_collections_editor_poll(C);
247   }
248   return ED_operator_view3d_active(C);
249 }
250
251 static int object_hide_view_clear_exec(bContext *C, wmOperator *op)
252 {
253   Scene *scene = CTX_data_scene(C);
254   ViewLayer *view_layer = CTX_data_view_layer(C);
255   const bool select = RNA_boolean_get(op->ptr, "select");
256   bool changed = false;
257
258   LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
259     if (base->flag & BASE_HIDDEN) {
260       base->flag &= ~BASE_HIDDEN;
261       changed = true;
262
263       if (select) {
264         /* We cannot call `ED_object_base_select` because
265          * base is not selectable while it is hidden. */
266         base->flag |= BASE_SELECTED;
267         BKE_scene_object_base_flag_sync_from_base(base);
268       }
269     }
270   }
271
272   if (!changed) {
273     return OPERATOR_CANCELLED;
274   }
275
276   BKE_layer_collection_sync(scene, view_layer);
277   DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
278   WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
279   WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
280
281   return OPERATOR_FINISHED;
282 }
283
284 void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
285 {
286   /* identifiers */
287   ot->name = "Show Hidden Objects";
288   ot->description = "Reveal temporarily hidden objects";
289   ot->idname = "OBJECT_OT_hide_view_clear";
290
291   /* api callbacks */
292   ot->exec = object_hide_view_clear_exec;
293   ot->poll = object_hide_poll;
294
295   /* flags */
296   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
297
298   PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", true, "Select", "");
299   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
300 }
301
302 static int object_hide_view_set_exec(bContext *C, wmOperator *op)
303 {
304   Scene *scene = CTX_data_scene(C);
305   ViewLayer *view_layer = CTX_data_view_layer(C);
306   const bool unselected = RNA_boolean_get(op->ptr, "unselected");
307   bool changed = false;
308
309   /* Hide selected or unselected objects. */
310   LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
311     if (!(base->flag & BASE_VISIBLE_VIEWLAYER)) {
312       continue;
313     }
314
315     if (!unselected) {
316       if (base->flag & BASE_SELECTED) {
317         ED_object_base_select(base, BA_DESELECT);
318         base->flag |= BASE_HIDDEN;
319         changed = true;
320       }
321     }
322     else {
323       if (!(base->flag & BASE_SELECTED)) {
324         ED_object_base_select(base, BA_DESELECT);
325         base->flag |= BASE_HIDDEN;
326         changed = true;
327       }
328     }
329   }
330   if (!changed) {
331     return OPERATOR_CANCELLED;
332   }
333
334   BKE_layer_collection_sync(scene, view_layer);
335   DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
336   WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
337   WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
338
339   return OPERATOR_FINISHED;
340 }
341
342 void OBJECT_OT_hide_view_set(wmOperatorType *ot)
343 {
344   /* identifiers */
345   ot->name = "Hide Objects";
346   ot->description = "Temporarily hide objects from the viewport";
347   ot->idname = "OBJECT_OT_hide_view_set";
348
349   /* api callbacks */
350   ot->exec = object_hide_view_set_exec;
351   ot->poll = object_hide_poll;
352
353   /* flags */
354   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
355
356   PropertyRNA *prop;
357   prop = RNA_def_boolean(
358       ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
359   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
360 }
361
362 static int object_hide_collection_exec(bContext *C, wmOperator *op)
363 {
364   wmWindow *win = CTX_wm_window(C);
365   View3D *v3d = CTX_wm_view3d(C);
366
367   int index = RNA_int_get(op->ptr, "collection_index");
368   const bool extend = (win->eventstate->shift != 0);
369   const bool toggle = RNA_boolean_get(op->ptr, "toggle");
370
371   if (win->eventstate->alt != 0) {
372     index += 10;
373   }
374
375   Scene *scene = CTX_data_scene(C);
376   ViewLayer *view_layer = CTX_data_view_layer(C);
377   LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
378
379   if (!lc) {
380     return OPERATOR_CANCELLED;
381   }
382
383   DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
384
385   if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
386     if (lc->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) {
387       return OPERATOR_CANCELLED;
388     }
389     if (toggle) {
390       lc->local_collections_bits ^= v3d->local_collections_uuid;
391       BKE_layer_collection_local_sync(view_layer, v3d);
392     }
393     else {
394       BKE_layer_collection_isolate_local(view_layer, v3d, lc, extend);
395     }
396   }
397   else {
398     BKE_layer_collection_isolate_global(scene, view_layer, lc, extend);
399   }
400
401   WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
402
403   return OPERATOR_FINISHED;
404 }
405
406 #define COLLECTION_INVALID_INDEX -1
407
408 void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout)
409 {
410   ViewLayer *view_layer = CTX_data_view_layer(C);
411   LayerCollection *lc_scene = view_layer->layer_collections.first;
412
413   uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
414
415   LISTBASE_FOREACH (LayerCollection *, lc, &lc_scene->layer_collections) {
416     int index = BKE_layer_collection_findindex(view_layer, lc);
417     uiLayout *row = uiLayoutRow(layout, false);
418
419     if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
420       continue;
421     }
422
423     if (lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) {
424       continue;
425     }
426
427     int icon = ICON_NONE;
428     if (BKE_layer_collection_has_selected_objects(view_layer, lc)) {
429       icon = ICON_LAYER_ACTIVE;
430     }
431     else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) {
432       icon = ICON_LAYER_USED;
433     }
434
435     uiItemIntO(row,
436                lc->collection->id.name + 2,
437                icon,
438                "OBJECT_OT_hide_collection",
439                "collection_index",
440                index);
441   }
442 }
443
444 static int object_hide_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
445 {
446   /* Immediately execute if collection index was specified. */
447   int index = RNA_int_get(op->ptr, "collection_index");
448   if (index != COLLECTION_INVALID_INDEX) {
449     return object_hide_collection_exec(C, op);
450   }
451
452   /* Open popup menu. */
453   const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
454   uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_GROUP);
455   uiLayout *layout = UI_popup_menu_layout(pup);
456
457   ED_collection_hide_menu_draw(C, layout);
458
459   UI_popup_menu_end(C, pup);
460
461   return OPERATOR_INTERFACE;
462 }
463
464 void OBJECT_OT_hide_collection(wmOperatorType *ot)
465 {
466   /* identifiers */
467   ot->name = "Hide Collection";
468   ot->description = "Show only objects in collection (Shift to extend)";
469   ot->idname = "OBJECT_OT_hide_collection";
470
471   /* api callbacks */
472   ot->exec = object_hide_collection_exec;
473   ot->invoke = object_hide_collection_invoke;
474   ot->poll = ED_operator_view3d_active;
475
476   /* flags */
477   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
478
479   /* Properties. */
480   PropertyRNA *prop;
481   prop = RNA_def_int(ot->srna,
482                      "collection_index",
483                      COLLECTION_INVALID_INDEX,
484                      COLLECTION_INVALID_INDEX,
485                      INT_MAX,
486                      "Collection Index",
487                      "Index of the collection to change visibility",
488                      0,
489                      INT_MAX);
490   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
491   prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle visibility");
492   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
493 }
494
495 /** \} */
496
497 /* -------------------------------------------------------------------- */
498 /** \name Toggle Edit-Mode Operator
499  * \{ */
500
501 static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
502 {
503   if (me->key) {
504     return false; /* will be added */
505   }
506
507   for (const Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
508     if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
509       return true;
510     }
511     if (ob->data == me) {
512       LISTBASE_FOREACH (const ModifierData *, md, &ob->modifiers) {
513         if (md->type == eModifierType_Hook) {
514           return true;
515         }
516       }
517     }
518   }
519   return false;
520 }
521
522 /**
523  * Load EditMode data back into the object,
524  * optionally freeing the editmode data.
525  */
526 static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool freedata)
527 {
528   if (obedit == NULL) {
529     return false;
530   }
531
532   if (obedit->type == OB_MESH) {
533     Mesh *me = obedit->data;
534     if (me->edit_mesh == NULL) {
535       return false;
536     }
537
538     if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
539       /* This used to be warned int the UI, we could warn again although it's quite rare. */
540       CLOG_WARN(&LOG,
541                 "Too many vertices for mesh '%s' (%d)",
542                 me->id.name + 2,
543                 me->edit_mesh->bm->totvert);
544       return false;
545     }
546
547     EDBM_mesh_load_ex(bmain, obedit, freedata);
548
549     if (freedata) {
550       EDBM_mesh_free(me->edit_mesh);
551       MEM_freeN(me->edit_mesh);
552       me->edit_mesh = NULL;
553     }
554     /* will be recalculated as needed. */
555     {
556       ED_mesh_mirror_spatial_table_end(obedit);
557       ED_mesh_mirror_topo_table_end(obedit);
558     }
559   }
560   else if (obedit->type == OB_ARMATURE) {
561     const bArmature *arm = obedit->data;
562     if (arm->edbo == NULL) {
563       return false;
564     }
565     ED_armature_from_edit(bmain, obedit->data);
566     if (freedata) {
567       ED_armature_edit_free(obedit->data);
568     }
569     /* TODO(sergey): Pose channels might have been changed, so need
570      * to inform dependency graph about this. But is it really the
571      * best place to do this?
572      */
573     DEG_relations_tag_update(bmain);
574   }
575   else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
576     const Curve *cu = obedit->data;
577     if (cu->editnurb == NULL) {
578       return false;
579     }
580     ED_curve_editnurb_load(bmain, obedit);
581     if (freedata) {
582       ED_curve_editnurb_free(obedit);
583     }
584   }
585   else if (obedit->type == OB_FONT) {
586     const Curve *cu = obedit->data;
587     if (cu->editfont == NULL) {
588       return false;
589     }
590     ED_curve_editfont_load(obedit);
591     if (freedata) {
592       ED_curve_editfont_free(obedit);
593     }
594   }
595   else if (obedit->type == OB_LATTICE) {
596     const Lattice *lt = obedit->data;
597     if (lt->editlatt == NULL) {
598       return false;
599     }
600     BKE_editlattice_load(obedit);
601     if (freedata) {
602       BKE_editlattice_free(obedit);
603     }
604   }
605   else if (obedit->type == OB_MBALL) {
606     const MetaBall *mb = obedit->data;
607     if (mb->editelems == NULL) {
608       return false;
609     }
610     ED_mball_editmball_load(obedit);
611     if (freedata) {
612       ED_mball_editmball_free(obedit);
613     }
614   }
615   else {
616     return false;
617   }
618
619   char *needs_flush_ptr = BKE_object_data_editmode_flush_ptr_get(obedit->data);
620   if (needs_flush_ptr) {
621     *needs_flush_ptr = false;
622   }
623
624   return true;
625 }
626
627 bool ED_object_editmode_load(Main *bmain, Object *obedit)
628 {
629   return ED_object_editmode_load_ex(bmain, obedit, false);
630 }
631
632 /**
633  * \param flag:
634  * - If #EM_FREEDATA isn't in the flag, use ED_object_editmode_load directly.
635  */
636 bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag)
637 {
638   const bool freedata = (flag & EM_FREEDATA) != 0;
639
640   if (ED_object_editmode_load_ex(bmain, obedit, freedata) == false) {
641     /* in rare cases (background mode) its possible active object
642      * is flagged for editmode, without 'obedit' being set T35489. */
643     if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
644       obedit->mode &= ~OB_MODE_EDIT;
645       /* Also happens when mesh is shared across multiple objects. [#T69834] */
646       DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
647     }
648     return true;
649   }
650
651   /* freedata only 0 now on file saves and render */
652   if (freedata) {
653     ListBase pidlist;
654     PTCacheID *pid;
655
656     /* flag object caches as outdated */
657     BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
658     for (pid = pidlist.first; pid; pid = pid->next) {
659       /* particles don't need reset on geometry change */
660       if (pid->type != PTCACHE_TYPE_PARTICLES) {
661         pid->cache->flag |= PTCACHE_OUTDATED;
662       }
663     }
664     BLI_freelistN(&pidlist);
665
666     BKE_particlesystem_reset_all(obedit);
667     BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
668
669     /* also flush ob recalc, doesn't take much overhead, but used for particles */
670     DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
671
672     WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
673
674     obedit->mode &= ~OB_MODE_EDIT;
675   }
676
677   return (obedit->mode & OB_MODE_EDIT) == 0;
678 }
679
680 bool ED_object_editmode_exit(bContext *C, int flag)
681 {
682   Main *bmain = CTX_data_main(C);
683   Scene *scene = CTX_data_scene(C);
684   Object *obedit = CTX_data_edit_object(C);
685   return ED_object_editmode_exit_ex(bmain, scene, obedit, flag);
686 }
687
688 bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
689 {
690   bool ok = false;
691
692   if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) ||
693       ID_IS_OVERRIDE_LIBRARY(ob->data)) {
694     return false;
695   }
696
697   /* this checks actual object->data, for cases when other scenes have it in editmode context */
698   if (BKE_object_is_in_editmode(ob)) {
699     return true;
700   }
701
702   if (BKE_object_obdata_is_libdata(ob)) {
703     /* Ideally the caller should check this. */
704     CLOG_WARN(&LOG, "Unable to enter edit-mode on library data for object '%s'", ob->id.name + 2);
705     return false;
706   }
707
708   ob->restore_mode = ob->mode;
709
710   ob->mode = OB_MODE_EDIT;
711
712   if (ob->type == OB_MESH) {
713     BMEditMesh *em;
714     ok = 1;
715
716     const bool use_key_index = mesh_needs_keyindex(bmain, ob->data);
717
718     EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
719
720     em = BKE_editmesh_from_object(ob);
721     if (LIKELY(em)) {
722       /* order doesn't matter */
723       EDBM_mesh_normals_update(em);
724       BKE_editmesh_looptri_calc(em);
725     }
726
727     WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
728   }
729   else if (ob->type == OB_ARMATURE) {
730     bArmature *arm = ob->data;
731     ok = 1;
732     ED_armature_to_edit(arm);
733     /* To ensure all goes in rest-position and without striding. */
734
735     arm->needs_flush_to_id = 0;
736
737     /* XXX: should this be ID_RECALC_GEOMETRY? */
738     DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
739
740     WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
741   }
742   else if (ob->type == OB_FONT) {
743     ok = 1;
744     ED_curve_editfont_make(ob);
745
746     WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
747   }
748   else if (ob->type == OB_MBALL) {
749     MetaBall *mb = ob->data;
750
751     ok = 1;
752     ED_mball_editmball_make(ob);
753
754     mb->needs_flush_to_id = 0;
755
756     WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
757   }
758   else if (ob->type == OB_LATTICE) {
759     ok = 1;
760     BKE_editlattice_make(ob);
761
762     WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
763   }
764   else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
765     ok = 1;
766     ED_curve_editnurb_make(ob);
767
768     WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
769   }
770
771   if (ok) {
772     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
773   }
774   else {
775     if ((flag & EM_NO_CONTEXT) == 0) {
776       ob->mode &= ~OB_MODE_EDIT;
777     }
778     WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
779   }
780
781   return (ob->mode & OB_MODE_EDIT) != 0;
782 }
783
784 bool ED_object_editmode_enter(bContext *C, int flag)
785 {
786   Main *bmain = CTX_data_main(C);
787   Scene *scene = CTX_data_scene(C);
788
789   /* Active layer checked here for view3d,
790    * callers that don't want view context can call the extended version. */
791   Object *ob = CTX_data_active_object(C);
792   return ED_object_editmode_enter_ex(bmain, scene, ob, flag);
793 }
794
795 static int editmode_toggle_exec(bContext *C, wmOperator *op)
796 {
797   Main *bmain = CTX_data_main(C);
798   Scene *scene = CTX_data_scene(C);
799   View3D *v3d = CTX_wm_view3d(C);
800   ViewLayer *view_layer = CTX_data_view_layer(C);
801   Object *obact = OBACT(view_layer);
802   const int mode_flag = OB_MODE_EDIT;
803   const bool is_mode_set = (obact->mode & mode_flag) != 0;
804   struct wmMsgBus *mbus = CTX_wm_message_bus(C);
805
806   if (!is_mode_set) {
807     if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
808       return OPERATOR_CANCELLED;
809     }
810   }
811
812   if (!is_mode_set) {
813     ED_object_editmode_enter_ex(bmain, scene, obact, 0);
814     if (obact->mode & mode_flag) {
815       FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
816         if ((ob != obact) && (ob->type == obact->type)) {
817           ED_object_editmode_enter_ex(bmain, scene, ob, EM_NO_CONTEXT);
818         }
819       }
820       FOREACH_SELECTED_OBJECT_END;
821     }
822   }
823   else {
824     ED_object_editmode_exit_ex(bmain, scene, obact, EM_FREEDATA);
825
826     if ((obact->mode & mode_flag) == 0) {
827       FOREACH_OBJECT_BEGIN (view_layer, ob) {
828         if ((ob != obact) && (ob->type == obact->type)) {
829           ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
830         }
831       }
832       FOREACH_OBJECT_END;
833     }
834   }
835
836   WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
837
838   if (G.background == false) {
839     WM_toolsystem_update_from_context_view3d(C);
840   }
841
842   return OPERATOR_FINISHED;
843 }
844
845 static bool editmode_toggle_poll(bContext *C)
846 {
847   Object *ob = CTX_data_active_object(C);
848
849   /* covers proxies too */
850   if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob) ||
851       ID_IS_OVERRIDE_LIBRARY(ob->data)) {
852     return 0;
853   }
854
855   /* if hidden but in edit mode, we still display */
856   if ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) {
857     return 0;
858   }
859
860   return OB_TYPE_SUPPORT_EDITMODE(ob->type);
861 }
862
863 void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
864 {
865
866   /* identifiers */
867   ot->name = "Toggle Editmode";
868   ot->description = "Toggle object's editmode";
869   ot->idname = "OBJECT_OT_editmode_toggle";
870
871   /* api callbacks */
872   ot->exec = editmode_toggle_exec;
873   ot->poll = editmode_toggle_poll;
874
875   /* flags */
876   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
877 }
878
879 /** \} */
880
881 /* -------------------------------------------------------------------- */
882 /** \name Toggle Pose-Mode Operator
883  * \{ */
884
885 static int posemode_exec(bContext *C, wmOperator *op)
886 {
887   struct wmMsgBus *mbus = CTX_wm_message_bus(C);
888   struct Main *bmain = CTX_data_main(C);
889   Scene *scene = CTX_data_scene(C);
890   ViewLayer *view_layer = CTX_data_view_layer(C);
891   Base *base = CTX_data_active_base(C);
892
893   /* If the base is NULL it means we have an active object, but the object itself is hidden. */
894   if (base == NULL) {
895     return OPERATOR_CANCELLED;
896   }
897
898   Object *obact = base->object;
899   const int mode_flag = OB_MODE_POSE;
900   bool is_mode_set = (obact->mode & mode_flag) != 0;
901
902   if (!is_mode_set) {
903     if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
904       return OPERATOR_CANCELLED;
905     }
906   }
907
908   if (obact->type != OB_ARMATURE) {
909     return OPERATOR_PASS_THROUGH;
910   }
911
912   {
913     Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
914     if (obact == obedit) {
915       ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
916       is_mode_set = false;
917     }
918   }
919
920   if (is_mode_set) {
921     bool ok = ED_object_posemode_exit(C, obact);
922     if (ok) {
923       FOREACH_OBJECT_BEGIN (view_layer, ob) {
924         if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) {
925           ED_object_posemode_exit_ex(bmain, ob);
926         }
927       }
928       FOREACH_OBJECT_END;
929     }
930   }
931   else {
932     bool ok = ED_object_posemode_enter(C, obact);
933     if (ok) {
934       const View3D *v3d = CTX_wm_view3d(C);
935       FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
936         if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) &&
937             (!ID_IS_LINKED(ob))) {
938           ED_object_posemode_enter_ex(bmain, ob);
939         }
940       }
941       FOREACH_SELECTED_OBJECT_END;
942     }
943   }
944
945   WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
946
947   if (G.background == false) {
948     WM_toolsystem_update_from_context_view3d(C);
949   }
950
951   return OPERATOR_FINISHED;
952 }
953
954 void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
955 {
956   /* identifiers */
957   ot->name = "Toggle Pose Mode";
958   ot->idname = "OBJECT_OT_posemode_toggle";
959   ot->description = "Enable or disable posing/selecting bones";
960
961   /* api callbacks */
962   ot->exec = posemode_exec;
963   ot->poll = ED_operator_object_active_editable;
964
965   /* flag */
966   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
967 }
968
969 /** \} */
970
971 /* -------------------------------------------------------------------- */
972 /** \name Force Field Toggle Operator
973  * \{ */
974
975 void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object)
976 {
977   PartDeflect *pd = object->pd;
978   ModifierData *md = BKE_modifiers_findby_type(object, eModifierType_Surface);
979
980   /* add/remove modifier as needed */
981   if (!md) {
982     if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) &&
983         !ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
984       if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
985         ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface);
986       }
987     }
988   }
989   else {
990     if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) ||
991         ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
992       ED_object_modifier_remove(NULL, bmain, scene, object, md);
993     }
994   }
995 }
996
997 static int forcefield_toggle_exec(bContext *C, wmOperator *UNUSED(op))
998 {
999   Object *ob = CTX_data_active_object(C);
1000
1001   if (ob->pd == NULL) {
1002     ob->pd = BKE_partdeflect_new(PFIELD_FORCE);
1003   }
1004   else if (ob->pd->forcefield == 0) {
1005     ob->pd->forcefield = PFIELD_FORCE;
1006   }
1007   else {
1008     ob->pd->forcefield = 0;
1009   }
1010
1011   ED_object_check_force_modifiers(CTX_data_main(C), CTX_data_scene(C), ob);
1012   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
1013   WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1014
1015   DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
1016
1017   return OPERATOR_FINISHED;
1018 }
1019
1020 void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
1021 {
1022
1023   /* identifiers */
1024   ot->name = "Toggle Force Field";
1025   ot->description = "Toggle object's force field";
1026   ot->idname = "OBJECT_OT_forcefield_toggle";
1027
1028   /* api callbacks */
1029   ot->exec = forcefield_toggle_exec;
1030   ot->poll = ED_operator_object_active_editable;
1031
1032   /* flags */
1033   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1034 }
1035
1036 /** \} */
1037
1038 /* -------------------------------------------------------------------- */
1039 /** \name Calculate Motion Paths Operator
1040  * \{ */
1041
1042 static eAnimvizCalcRange object_path_convert_range(eObjectPathCalcRange range)
1043 {
1044   switch (range) {
1045     case OBJECT_PATH_CALC_RANGE_CURRENT_FRAME:
1046       return ANIMVIZ_CALC_RANGE_CURRENT_FRAME;
1047     case OBJECT_PATH_CALC_RANGE_CHANGED:
1048       return ANIMVIZ_CALC_RANGE_CHANGED;
1049     case OBJECT_PATH_CALC_RANGE_FULL:
1050       return ANIMVIZ_CALC_RANGE_FULL;
1051   }
1052   return ANIMVIZ_CALC_RANGE_FULL;
1053 }
1054
1055 /* For the objects with animation: update paths for those that have got them
1056  * This should selectively update paths that exist...
1057  *
1058  * To be called from various tools that do incremental updates
1059  */
1060 void ED_objects_recalculate_paths(bContext *C, Scene *scene, eObjectPathCalcRange range)
1061 {
1062   /* Transform doesn't always have context available to do update. */
1063   if (C == NULL) {
1064     return;
1065   }
1066
1067   Main *bmain = CTX_data_main(C);
1068   ViewLayer *view_layer = CTX_data_view_layer(C);
1069
1070   ListBase targets = {NULL, NULL};
1071   /* loop over objects in scene */
1072   CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1073     /* set flag to force recalc, then grab path(s) from object */
1074     ob->avs.recalc |= ANIMVIZ_RECALC_PATHS;
1075     animviz_get_object_motionpaths(ob, &targets);
1076   }
1077   CTX_DATA_END;
1078
1079   Depsgraph *depsgraph;
1080   bool free_depsgraph = false;
1081   /* For a single frame update it's faster to re-use existing dependency graph and avoid overhead
1082    * of building all the relations and so on for a temporary one.  */
1083   if (range == OBJECT_PATH_CALC_RANGE_CURRENT_FRAME) {
1084     /* NOTE: Dependency graph will be evaluated at all the frames, but we first need to access some
1085      * nested pointers, like animation data. */
1086     depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
1087     free_depsgraph = false;
1088   }
1089   else {
1090     depsgraph = animviz_depsgraph_build(bmain, scene, view_layer, &targets);
1091     free_depsgraph = true;
1092   }
1093
1094   /* recalculate paths, then free */
1095   animviz_calc_motionpaths(
1096       depsgraph, bmain, scene, &targets, object_path_convert_range(range), true);
1097   BLI_freelistN(&targets);
1098
1099   if (range != OBJECT_PATH_CALC_RANGE_CURRENT_FRAME) {
1100     /* Tag objects for copy on write - so paths will draw/redraw
1101      * For currently frame only we update evaluated object directly. */
1102     CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1103       if (ob->mpath) {
1104         DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
1105       }
1106     }
1107     CTX_DATA_END;
1108   }
1109
1110   /* Free temporary depsgraph. */
1111   if (free_depsgraph) {
1112     DEG_graph_free(depsgraph);
1113   }
1114 }
1115
1116 /* show popup to determine settings */
1117 static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1118 {
1119   Object *ob = CTX_data_active_object(C);
1120
1121   if (ob == NULL) {
1122     return OPERATOR_CANCELLED;
1123   }
1124
1125   /* set default settings from existing/stored settings */
1126   {
1127     bAnimVizSettings *avs = &ob->avs;
1128
1129     RNA_int_set(op->ptr, "start_frame", avs->path_sf);
1130     RNA_int_set(op->ptr, "end_frame", avs->path_ef);
1131   }
1132
1133   /* show popup dialog to allow editing of range... */
1134   /* FIXME: hard-coded dimensions here are just arbitrary. */
1135   return WM_operator_props_dialog_popup(C, op, 200);
1136 }
1137
1138 /* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */
1139 static int object_calculate_paths_exec(bContext *C, wmOperator *op)
1140 {
1141   Scene *scene = CTX_data_scene(C);
1142   int start = RNA_int_get(op->ptr, "start_frame");
1143   int end = RNA_int_get(op->ptr, "end_frame");
1144
1145   /* set up path data for bones being calculated */
1146   CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1147     bAnimVizSettings *avs = &ob->avs;
1148
1149     /* grab baking settings from operator settings */
1150     avs->path_sf = start;
1151     avs->path_ef = end;
1152
1153     /* verify that the selected object has the appropriate settings */
1154     animviz_verify_motionpaths(op->reports, scene, ob, NULL);
1155   }
1156   CTX_DATA_END;
1157
1158   /* calculate the paths for objects that have them (and are tagged to get refreshed) */
1159   ED_objects_recalculate_paths(C, scene, OBJECT_PATH_CALC_RANGE_FULL);
1160
1161   /* notifiers for updates */
1162   WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
1163
1164   return OPERATOR_FINISHED;
1165 }
1166
1167 void OBJECT_OT_paths_calculate(wmOperatorType *ot)
1168 {
1169   /* identifiers */
1170   ot->name = "Calculate Object Paths";
1171   ot->idname = "OBJECT_OT_paths_calculate";
1172   ot->description = "Calculate motion paths for the selected objects";
1173
1174   /* api callbacks */
1175   ot->invoke = object_calculate_paths_invoke;
1176   ot->exec = object_calculate_paths_exec;
1177   ot->poll = ED_operator_object_active_editable;
1178
1179   /* flags */
1180   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1181
1182   /* properties */
1183   RNA_def_int(ot->srna,
1184               "start_frame",
1185               1,
1186               MINAFRAME,
1187               MAXFRAME,
1188               "Start",
1189               "First frame to calculate object paths on",
1190               MINFRAME,
1191               MAXFRAME / 2.0);
1192   RNA_def_int(ot->srna,
1193               "end_frame",
1194               250,
1195               MINAFRAME,
1196               MAXFRAME,
1197               "End",
1198               "Last frame to calculate object paths on",
1199               MINFRAME,
1200               MAXFRAME / 2.0);
1201 }
1202
1203 /** \} */
1204
1205 /* -------------------------------------------------------------------- */
1206 /** \name Update Motion Paths Operator
1207  * \{ */
1208
1209 static bool object_update_paths_poll(bContext *C)
1210 {
1211   if (ED_operator_object_active_editable(C)) {
1212     Object *ob = ED_object_active_context(C);
1213     return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1214   }
1215
1216   return false;
1217 }
1218
1219 static int object_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
1220 {
1221   Scene *scene = CTX_data_scene(C);
1222
1223   if (scene == NULL) {
1224     return OPERATOR_CANCELLED;
1225   }
1226
1227   /* calculate the paths for objects that have them (and are tagged to get refreshed) */
1228   ED_objects_recalculate_paths(C, scene, OBJECT_PATH_CALC_RANGE_FULL);
1229
1230   /* notifiers for updates */
1231   WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
1232
1233   return OPERATOR_FINISHED;
1234 }
1235
1236 void OBJECT_OT_paths_update(wmOperatorType *ot)
1237 {
1238   /* identifiers */
1239   ot->name = "Update Object Paths";
1240   ot->idname = "OBJECT_OT_paths_update";
1241   ot->description = "Recalculate paths for selected objects";
1242
1243   /* api callbacks */
1244   ot->exec = object_update_paths_exec;
1245   ot->poll = object_update_paths_poll;
1246
1247   /* flags */
1248   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1249 }
1250
1251 /** \} */
1252
1253 /* -------------------------------------------------------------------- */
1254 /** \name Clear Motion Paths Operator
1255  * \{ */
1256
1257 /* Helper for ED_objects_clear_paths() */
1258 static void object_clear_mpath(Object *ob)
1259 {
1260   if (ob->mpath) {
1261     animviz_free_motionpath(ob->mpath);
1262     ob->mpath = NULL;
1263     ob->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
1264
1265     /* tag object for copy on write - so removed paths don't still show */
1266     DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
1267   }
1268 }
1269
1270 /* Clear motion paths for all objects */
1271 void ED_objects_clear_paths(bContext *C, bool only_selected)
1272 {
1273   if (only_selected) {
1274     /* Loop over all selected + editable objects in scene. */
1275     CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1276       object_clear_mpath(ob);
1277     }
1278     CTX_DATA_END;
1279   }
1280   else {
1281     /* Loop over all editable objects in scene. */
1282     CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
1283       object_clear_mpath(ob);
1284     }
1285     CTX_DATA_END;
1286   }
1287 }
1288
1289 /* operator callback for this */
1290 static int object_clear_paths_exec(bContext *C, wmOperator *op)
1291 {
1292   bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
1293
1294   /* use the backend function for this */
1295   ED_objects_clear_paths(C, only_selected);
1296
1297   /* notifiers for updates */
1298   WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
1299
1300   return OPERATOR_FINISHED;
1301 }
1302
1303 /* operator callback/wrapper */
1304 static int object_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
1305 {
1306   if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
1307     RNA_boolean_set(op->ptr, "only_selected", true);
1308   }
1309   return object_clear_paths_exec(C, op);
1310 }
1311
1312 void OBJECT_OT_paths_clear(wmOperatorType *ot)
1313 {
1314   /* identifiers */
1315   ot->name = "Clear Object Paths";
1316   ot->idname = "OBJECT_OT_paths_clear";
1317   ot->description = "Clear path caches for all objects, hold Shift key for selected objects only";
1318
1319   /* api callbacks */
1320   ot->invoke = object_clear_paths_invoke;
1321   ot->exec = object_clear_paths_exec;
1322   ot->poll = ED_operator_object_active_editable;
1323
1324   /* flags */
1325   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1326
1327   /* properties */
1328   ot->prop = RNA_def_boolean(
1329       ot->srna, "only_selected", false, "Only Selected", "Only clear paths from selected objects");
1330   RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
1331 }
1332
1333 /** \} */
1334
1335 /* -------------------------------------------------------------------- */
1336 /** \name Update Motion Paths Range from Scene Operator
1337  * \{ */
1338
1339 static int object_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op))
1340 {
1341   Scene *scene = CTX_data_scene(C);
1342
1343   /* Loop over all editable objects in scene. */
1344   CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
1345     /* use Preview Range or Full Frame Range - whichever is in use */
1346     ob->avs.path_sf = PSFRA;
1347     ob->avs.path_ef = PEFRA;
1348
1349     /* tag for updates */
1350     DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
1351     WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
1352   }
1353   CTX_DATA_END;
1354
1355   return OPERATOR_FINISHED;
1356 }
1357
1358 void OBJECT_OT_paths_range_update(wmOperatorType *ot)
1359 {
1360   /* identifiers */
1361   ot->name = "Update Range from Scene";
1362   ot->idname = "OBJECT_OT_paths_range_update";
1363   ot->description = "Update frame range for motion paths from the Scene's current frame range";
1364
1365   /* callbacks */
1366   ot->exec = object_update_paths_range_exec;
1367   ot->poll = ED_operator_object_active_editable;
1368
1369   /* flags */
1370   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1371 }
1372
1373 /** \} */
1374
1375 /* -------------------------------------------------------------------- */
1376 /** \name Object Shade Smooth/Flat Operator
1377  * \{ */
1378
1379 static int shade_smooth_exec(bContext *C, wmOperator *op)
1380 {
1381   const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth");
1382   bool changed_multi = false;
1383   bool has_linked_data = false;
1384
1385   ListBase ctx_objects = {NULL, NULL};
1386   CollectionPointerLink ctx_ob_single_active = {NULL};
1387
1388   /* For modes that only use an active object, don't handle the whole selection. */
1389   {
1390     ViewLayer *view_layer = CTX_data_view_layer(C);
1391     Object *obact = OBACT(view_layer);
1392     if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) {
1393       ctx_ob_single_active.ptr.data = obact;
1394       BLI_addtail(&ctx_objects, &ctx_ob_single_active);
1395     }
1396   }
1397
1398   if (ctx_objects.first != &ctx_ob_single_active) {
1399     CTX_data_selected_editable_objects(C, &ctx_objects);
1400   }
1401
1402   for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) {
1403     Object *ob = ctx_ob->ptr.data;
1404     ID *data = ob->data;
1405     if (data != NULL) {
1406       data->tag |= LIB_TAG_DOIT;
1407     }
1408   }
1409
1410   for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) {
1411     /* Always un-tag all object data-blocks irrespective of our ability to operate on them. */
1412     Object *ob = ctx_ob->ptr.data;
1413     ID *data = ob->data;
1414     if ((data == NULL) || ((data->tag & LIB_TAG_DOIT) == 0)) {
1415       continue;
1416     }
1417     data->tag &= ~LIB_TAG_DOIT;
1418     /* Finished un-tagging, continue with regular logic. */
1419
1420     if (data && ID_IS_LINKED(data)) {
1421       has_linked_data = true;
1422       continue;
1423     }
1424
1425     bool changed = false;
1426     if (ob->type == OB_MESH) {
1427       BKE_mesh_smooth_flag_set(ob->data, use_smooth);
1428       BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
1429       changed = true;
1430     }
1431     else if (ELEM(ob->type, OB_SURF, OB_CURVE)) {
1432       BKE_curve_smooth_flag_set(ob->data, use_smooth);
1433       changed = true;
1434     }
1435
1436     if (changed) {
1437       changed_multi = true;
1438
1439       DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
1440       WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
1441     }
1442   }
1443
1444   if (ctx_objects.first != &ctx_ob_single_active) {
1445     BLI_freelistN(&ctx_objects);
1446   }
1447
1448   if (has_linked_data) {
1449     BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data");
1450   }
1451
1452   return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1453 }
1454
1455 static bool shade_poll(bContext *C)
1456 {
1457   ViewLayer *view_layer = CTX_data_view_layer(C);
1458   Object *obact = OBACT(view_layer);
1459   if (obact != NULL) {
1460     /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */
1461     if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT) || obact->data == NULL ||
1462         ID_IS_OVERRIDE_LIBRARY(obact) || ID_IS_OVERRIDE_LIBRARY(obact->data)) {
1463       return false;
1464     }
1465   }
1466   return true;
1467 }
1468
1469 void OBJECT_OT_shade_flat(wmOperatorType *ot)
1470 {
1471   /* identifiers */
1472   ot->name = "Shade Flat";
1473   ot->description = "Render and display faces uniform, using Face Normals";
1474   ot->idname = "OBJECT_OT_shade_flat";
1475
1476   /* api callbacks */
1477   ot->poll = shade_poll;
1478   ot->exec = shade_smooth_exec;
1479
1480   /* flags */
1481   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1482 }
1483
1484 void OBJECT_OT_shade_smooth(wmOperatorType *ot)
1485 {
1486   /* identifiers */
1487   ot->name = "Shade Smooth";
1488   ot->description = "Render and display faces smooth, using interpolated Vertex Normals";
1489   ot->idname = "OBJECT_OT_shade_smooth";
1490
1491   /* api callbacks */
1492   ot->poll = shade_poll;
1493   ot->exec = shade_smooth_exec;
1494
1495   /* flags */
1496   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1497 }
1498
1499 /** \} */
1500
1501 /* -------------------------------------------------------------------- */
1502 /** \name Object Mode Set Operator
1503  * \{ */
1504
1505 static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
1506                                                       PointerRNA *UNUSED(ptr),
1507                                                       PropertyRNA *UNUSED(prop),
1508                                                       bool *r_free)
1509 {
1510   const EnumPropertyItem *input = rna_enum_object_mode_items;
1511   EnumPropertyItem *item = NULL;
1512   Object *ob;
1513   int totitem = 0;
1514
1515   if (!C) { /* needed for docs */
1516     return rna_enum_object_mode_items;
1517   }
1518
1519   ob = CTX_data_active_object(C);
1520   if (ob) {
1521     const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) ||
1522                                         (ob->soft != NULL) ||
1523                                         (BKE_modifiers_findby_type(ob, eModifierType_Cloth) !=
1524                                          NULL);
1525     while (input->identifier) {
1526       if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
1527           (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
1528           (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
1529           (ELEM(input->value,
1530                 OB_MODE_SCULPT,
1531                 OB_MODE_VERTEX_PAINT,
1532                 OB_MODE_WEIGHT_PAINT,
1533                 OB_MODE_TEXTURE_PAINT) &&
1534            (ob->type == OB_MESH)) ||
1535           (ELEM(input->value,
1536                 OB_MODE_EDIT_GPENCIL,
1537                 OB_MODE_PAINT_GPENCIL,
1538                 OB_MODE_SCULPT_GPENCIL,
1539                 OB_MODE_WEIGHT_GPENCIL,
1540                 OB_MODE_VERTEX_GPENCIL) &&
1541            (ob->type == OB_GPENCIL)) ||
1542           (input->value == OB_MODE_OBJECT)) {
1543         RNA_enum_item_add(&item, &totitem, input);
1544       }
1545       input++;
1546     }
1547   }
1548   else {
1549     /* We need at least this one! */
1550     RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT);
1551   }
1552
1553   RNA_enum_item_end(&item, &totitem);
1554
1555   *r_free = true;
1556
1557   return item;
1558 }
1559
1560 static bool object_mode_set_poll(bContext *C)
1561 {
1562   /* Needed as #ED_operator_object_active_editable doesn't call use 'active_object'. */
1563   Object *ob = CTX_data_active_object(C);
1564   return ED_operator_object_active_editable_ex(C, ob);
1565 }
1566
1567 static int object_mode_set_exec(bContext *C, wmOperator *op)
1568 {
1569   const bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode");
1570   Object *ob = CTX_data_active_object(C);
1571   eObjectMode mode = RNA_enum_get(op->ptr, "mode");
1572   const bool toggle = RNA_boolean_get(op->ptr, "toggle");
1573
1574   /* by default the operator assume is a mesh, but if gp object change mode */
1575   if ((ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
1576     mode = OB_MODE_EDIT_GPENCIL;
1577   }
1578
1579   if (!ED_object_mode_compat_test(ob, mode)) {
1580     return OPERATOR_PASS_THROUGH;
1581   }
1582
1583   /**
1584    * Mode Switching Logic (internal details).
1585    *
1586    * Notes:
1587    * - Code below avoids calling mode switching functions more than once,
1588    *   as this causes unnecessary calculations and undo steps to be added.
1589    * - The previous mode (#Object.restore_mode) is object mode by default.
1590    *
1591    * Supported Cases:
1592    * - Setting the mode (when the 'toggle' setting is off).
1593    * - Toggle the mode:
1594    *   - Toggle between object mode and non-object mode property.
1595    *   - Toggle between the previous mode (#Object.restore_mode) and the mode property.
1596    *   - Toggle object mode.
1597    *     While this is similar to regular toggle,
1598    *     this operator depends on there being a previous mode set
1599    *     (this isn't bound to a key with the default key-map).
1600    */
1601   if (toggle == false) {
1602     if (ob->mode != mode) {
1603       ED_object_mode_set_ex(C, mode, true, op->reports);
1604     }
1605   }
1606   else {
1607     const eObjectMode mode_prev = ob->mode;
1608     /* When toggling object mode, we always use the restore mode,
1609      * otherwise there is nothing to do. */
1610     if (mode == OB_MODE_OBJECT) {
1611       if (ob->mode != OB_MODE_OBJECT) {
1612         if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) {
1613           /* Store old mode so we know what to go back to. */
1614           ob->restore_mode = mode_prev;
1615         }
1616       }
1617       else {
1618         if (ob->restore_mode != OB_MODE_OBJECT) {
1619           ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports);
1620         }
1621       }
1622     }
1623     else {
1624       /* Non-object modes, enter the 'mode' unless it's already set,
1625        * in that case use restore mode. */
1626       if (ob->mode != mode) {
1627         if (ED_object_mode_set_ex(C, mode, true, op->reports)) {
1628           /* Store old mode so we know what to go back to. */
1629           ob->restore_mode = mode_prev;
1630         }
1631       }
1632       else {
1633         if (ob->restore_mode != OB_MODE_OBJECT) {
1634           ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports);
1635         }
1636         else {
1637           ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports);
1638         }
1639       }
1640     }
1641   }
1642
1643   if (use_submode) {
1644     if (ob->type == OB_MESH) {
1645       if (ob->mode & OB_MODE_EDIT) {
1646         PropertyRNA *prop = RNA_struct_find_property(op->ptr, "mesh_select_mode");
1647         if (RNA_property_is_set(op->ptr, prop)) {
1648           int mesh_select_mode = RNA_property_enum_get(op->ptr, prop);
1649           if (mesh_select_mode != 0) {
1650             EDBM_selectmode_set_multi(C, mesh_select_mode);
1651           }
1652         }
1653       }
1654     }
1655   }
1656
1657   return OPERATOR_FINISHED;
1658 }
1659
1660 void OBJECT_OT_mode_set(wmOperatorType *ot)
1661 {
1662   PropertyRNA *prop;
1663
1664   /* identifiers */
1665   ot->name = "Set Object Mode";
1666   ot->description = "Sets the object interaction mode";
1667   ot->idname = "OBJECT_OT_mode_set";
1668
1669   /* api callbacks */
1670   ot->exec = object_mode_set_exec;
1671   ot->poll = object_mode_set_poll;
1672
1673   /* flags */
1674   ot->flag = 0; /* no register/undo here, leave it to operators being called */
1675
1676   ot->prop = RNA_def_enum(
1677       ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
1678   RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
1679   RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
1680
1681   prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
1682   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1683 }
1684
1685 void OBJECT_OT_mode_set_with_submode(wmOperatorType *ot)
1686 {
1687   OBJECT_OT_mode_set(ot);
1688
1689   /* identifiers */
1690   ot->name = "Set Object Mode with Submode";
1691   ot->idname = "OBJECT_OT_mode_set_with_submode";
1692
1693   /* properties */
1694   /* we could add other types - particle for eg. */
1695   PropertyRNA *prop;
1696   prop = RNA_def_enum_flag(
1697       ot->srna, "mesh_select_mode", rna_enum_mesh_select_mode_items, 0, "Mesh Mode", "");
1698   RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
1699 }
1700
1701 /** \} */
1702
1703 /* -------------------------------------------------------------------- */
1704 /** \name Object Link/Move to Collection Operator
1705  * \{ */
1706
1707 static ListBase selected_objects_get(bContext *C)
1708 {
1709   ListBase objects = {NULL};
1710
1711   if (CTX_wm_space_outliner(C) != NULL) {
1712     ED_outliner_selected_objects_get(C, &objects);
1713   }
1714   else {
1715     CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
1716       BLI_addtail(&objects, BLI_genericNodeN(ob));
1717     }
1718     CTX_DATA_END;
1719   }
1720
1721   return objects;
1722 }
1723
1724 static bool move_to_collection_poll(bContext *C)
1725 {
1726   if (CTX_wm_space_outliner(C) != NULL) {
1727     return ED_outliner_collections_editor_poll(C);
1728   }
1729
1730   View3D *v3d = CTX_wm_view3d(C);
1731
1732   if (v3d && v3d->localvd) {
1733     return false;
1734   }
1735
1736   return ED_operator_objectmode(C);
1737 }
1738
1739 static int move_to_collection_exec(bContext *C, wmOperator *op)
1740 {
1741   Main *bmain = CTX_data_main(C);
1742   Scene *scene = CTX_data_scene(C);
1743   PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
1744   const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
1745   const bool is_new = RNA_boolean_get(op->ptr, "is_new");
1746   Collection *collection;
1747   ListBase objects = {NULL};
1748
1749   if (!RNA_property_is_set(op->ptr, prop)) {
1750     BKE_report(op->reports, RPT_ERROR, "No collection selected");
1751     return OPERATOR_CANCELLED;
1752   }
1753
1754   int collection_index = RNA_property_int_get(op->ptr, prop);
1755   collection = BKE_collection_from_index(scene, collection_index);
1756   if (collection == NULL) {
1757     BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
1758     return OPERATOR_CANCELLED;
1759   }
1760
1761   objects = selected_objects_get(C);
1762
1763   if (is_new) {
1764     char new_collection_name[MAX_NAME];
1765     RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
1766     collection = BKE_collection_add(bmain, collection, new_collection_name);
1767   }
1768
1769   Object *single_object = BLI_listbase_is_single(&objects) ? ((LinkData *)objects.first)->data :
1770                                                              NULL;
1771
1772   if ((single_object != NULL) && is_link &&
1773       BLI_findptr(&collection->gobject, single_object, offsetof(CollectionObject, ob))) {
1774     BKE_reportf(op->reports,
1775                 RPT_ERROR,
1776                 "%s already in %s",
1777                 single_object->id.name + 2,
1778                 collection->id.name + 2);
1779     BLI_freelistN(&objects);
1780     return OPERATOR_CANCELLED;
1781   }
1782
1783   LISTBASE_FOREACH (LinkData *, link, &objects) {
1784     Object *ob = link->data;
1785
1786     if (!is_link) {
1787       BKE_collection_object_move(bmain, scene, collection, NULL, ob);
1788     }
1789     else {
1790       BKE_collection_object_add(bmain, collection, ob);
1791     }
1792   }
1793   BLI_freelistN(&objects);
1794
1795   BKE_reportf(op->reports,
1796               RPT_INFO,
1797               "%s %s to %s",
1798               (single_object != NULL) ? single_object->id.name + 2 : "Objects",
1799               is_link ? "linked" : "moved",
1800               collection->id.name + 2);
1801
1802   DEG_relations_tag_update(bmain);
1803   DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
1804
1805   WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
1806   WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
1807   WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
1808
1809   return OPERATOR_FINISHED;
1810 }
1811
1812 struct MoveToCollectionData {
1813   struct MoveToCollectionData *next, *prev;
1814   int index;
1815   struct Collection *collection;
1816   struct ListBase submenus;
1817   PointerRNA ptr;
1818   struct wmOperatorType *ot;
1819 };
1820
1821 static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
1822 {
1823   int index = menu->index;
1824   for (CollectionChild *child = menu->collection->children.first; child != NULL;
1825        child = child->next) {
1826     Collection *collection = child->collection;
1827     MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
1828                                                 "MoveToCollectionData submenu - expected memleak");
1829     BLI_addtail(&menu->submenus, submenu);
1830     submenu->collection = collection;
1831     submenu->index = ++index;
1832     index = move_to_collection_menus_create(op, submenu);
1833     submenu->ot = op->type;
1834   }
1835   return index;
1836 }
1837
1838 static void move_to_collection_menus_free_recursive(MoveToCollectionData *menu)
1839 {
1840   for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL;
1841        submenu = submenu->next) {
1842     move_to_collection_menus_free_recursive(submenu);
1843   }
1844   BLI_freelistN(&menu->submenus);
1845 }
1846
1847 static void move_to_collection_menus_free(MoveToCollectionData **menu)
1848 {
1849   if (*menu == NULL) {
1850     return;
1851   }
1852
1853   move_to_collection_menus_free_recursive(*menu);
1854   MEM_freeN(*menu);
1855   *menu = NULL;
1856 }
1857
1858 static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *menu_v)
1859 {
1860   MoveToCollectionData *menu = menu_v;
1861   const char *name = BKE_collection_ui_name_get(menu->collection);
1862
1863   UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
1864
1865   WM_operator_properties_create_ptr(&menu->ptr, menu->ot);
1866   RNA_int_set(&menu->ptr, "collection_index", menu->index);
1867   RNA_boolean_set(&menu->ptr, "is_new", true);
1868
1869   uiItemFullO_ptr(
1870       layout, menu->ot, "New Collection", ICON_ADD, menu->ptr.data, WM_OP_INVOKE_DEFAULT, 0, NULL);
1871
1872   uiItemS(layout);
1873
1874   Scene *scene = CTX_data_scene(C);
1875   const int icon = (menu->collection == scene->master_collection) ?
1876                        ICON_SCENE_DATA :
1877                        UI_icon_color_from_collection(menu->collection);
1878   uiItemIntO(layout, name, icon, menu->ot->idname, "collection_index", menu->index);
1879
1880   for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL;
1881        submenu = submenu->next) {
1882     move_to_collection_menus_items(layout, submenu);
1883   }
1884 }
1885
1886 static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu)
1887 {
1888   const int icon = UI_icon_color_from_collection(menu->collection);
1889
1890   if (BLI_listbase_is_empty(&menu->submenus)) {
1891     uiItemIntO(layout,
1892                menu->collection->id.name + 2,
1893                icon,
1894                menu->ot->idname,
1895                "collection_index",
1896                menu->index);
1897   }
1898   else {
1899     uiItemMenuF(layout, menu->collection->id.name + 2, icon, move_to_collection_menu_create, menu);
1900   }
1901 }
1902
1903 /* This is allocated statically because we need this available for the menus creation callback. */
1904 static MoveToCollectionData *master_collection_menu = NULL;
1905
1906 static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1907 {
1908   Scene *scene = CTX_data_scene(C);
1909
1910   ListBase objects = selected_objects_get(C);
1911   if (BLI_listbase_is_empty(&objects)) {
1912     BKE_report(op->reports, RPT_ERROR, "No objects selected");
1913     return OPERATOR_CANCELLED;
1914   }
1915   BLI_freelistN(&objects);
1916
1917   /* Reset the menus data for the current master collection, and free previously allocated data. */
1918   move_to_collection_menus_free(&master_collection_menu);
1919
1920   PropertyRNA *prop;
1921   prop = RNA_struct_find_property(op->ptr, "collection_index");
1922   if (RNA_property_is_set(op->ptr, prop)) {
1923     int collection_index = RNA_property_int_get(op->ptr, prop);
1924
1925     if (RNA_boolean_get(op->ptr, "is_new")) {
1926       prop = RNA_struct_find_property(op->ptr, "new_collection_name");
1927       if (!RNA_property_is_set(op->ptr, prop)) {
1928         char name[MAX_NAME];
1929         Collection *collection;
1930
1931         collection = BKE_collection_from_index(scene, collection_index);
1932         BKE_collection_new_name_get(collection, name);
1933
1934         RNA_property_string_set(op->ptr, prop, name);
1935         return WM_operator_props_dialog_popup(C, op, 200);
1936       }
1937     }
1938     return move_to_collection_exec(C, op);
1939   }
1940
1941   Collection *master_collection = scene->master_collection;
1942
1943   /* We need the data to be allocated so it's available during menu drawing.
1944    * Technically we could use wmOperator->customdata. However there is no free callback
1945    * called to an operator that exit with OPERATOR_INTERFACE to launch a menu.
1946    *
1947    * So we are left with a memory that will necessarily leak. It's a small leak though.*/
1948   if (master_collection_menu == NULL) {
1949     master_collection_menu = MEM_callocN(sizeof(MoveToCollectionData),
1950                                          "MoveToCollectionData menu - expected eventual memleak");
1951   }
1952
1953   master_collection_menu->collection = master_collection;
1954   master_collection_menu->ot = op->type;
1955   move_to_collection_menus_create(op, master_collection_menu);
1956
1957   uiPopupMenu *pup;
1958   uiLayout *layout;
1959
1960   /* Build the menus. */
1961   const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
1962   pup = UI_popup_menu_begin(C, title, ICON_NONE);
1963   layout = UI_popup_menu_layout(pup);
1964
1965   uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
1966
1967   move_to_collection_menu_create(C, layout, master_collection_menu);
1968
1969   UI_popup_menu_end(C, pup);
1970
1971   return OPERATOR_INTERFACE;
1972 }
1973
1974 void OBJECT_OT_move_to_collection(wmOperatorType *ot)
1975 {
1976   PropertyRNA *prop;
1977
1978   /* identifiers */
1979   ot->name = "Move to Collection";
1980   ot->description = "Move objects to a collection";
1981   ot->idname = "OBJECT_OT_move_to_collection";
1982
1983   /* api callbacks */
1984   ot->exec = move_to_collection_exec;
1985   ot->invoke = move_to_collection_invoke;
1986   ot->poll = move_to_collection_poll;
1987
1988   /* flags */
1989   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1990
1991   prop = RNA_def_int(ot->srna,
1992                      "collection_index",
1993                      COLLECTION_INVALID_INDEX,
1994                      COLLECTION_INVALID_INDEX,
1995                      INT_MAX,
1996                      "Collection Index",
1997                      "Index of the collection to move to",
1998                      0,
1999                      INT_MAX);
2000   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
2001   prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
2002   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
2003   prop = RNA_def_string(ot->srna,
2004                         "new_collection_name",
2005                         NULL,
2006                         MAX_NAME,
2007                         "Name",
2008                         "Name of the newly added collection");
2009   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2010   ot->prop = prop;
2011 }
2012
2013 void OBJECT_OT_link_to_collection(wmOperatorType *ot)
2014 {
2015   PropertyRNA *prop;
2016
2017   /* identifiers */
2018   ot->name = "Link to Collection";
2019   ot->description = "Link objects to a collection";
2020   ot->idname = "OBJECT_OT_link_to_collection";
2021
2022   /* api callbacks */
2023   ot->exec = move_to_collection_exec;
2024   ot->invoke = move_to_collection_invoke;
2025   ot->poll = move_to_collection_poll;
2026
2027   /* flags */
2028   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2029
2030   prop = RNA_def_int(ot->srna,
2031                      "collection_index",
2032                      COLLECTION_INVALID_INDEX,
2033                      COLLECTION_INVALID_INDEX,
2034                      INT_MAX,
2035                      "Collection Index",
2036                      "Index of the collection to move to",
2037                      0,
2038                      INT_MAX);
2039   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
2040   prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
2041   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
2042   prop = RNA_def_string(ot->srna,
2043                         "new_collection_name",
2044                         NULL,
2045                         MAX_NAME,
2046                         "Name",
2047                         "Name of the newly added collection");
2048   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2049   ot->prop = prop;
2050 }
2051
2052 /** \} */