Blender V5.0
object_edit.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cctype>
10#include <cfloat>
11#include <cstdlib>
12#include <cstring>
13#include <ctime>
14
15#include "AS_asset_library.hh"
16#include "BLI_path_utils.hh"
17#include "MEM_guardedalloc.h"
18
19#include "BLI_listbase.h"
20#include "BLI_math_rotation.h"
21#include "BLI_string.h"
22#include "BLI_string_utf8.h"
23#include "BLI_utildefines.h"
24
25#include "BLT_translation.hh"
26
27#include "DNA_armature_types.h"
28#include "DNA_asset_types.h"
30#include "DNA_curve_types.h"
31#include "DNA_lattice_types.h"
32#include "DNA_material_types.h"
33#include "DNA_mesh_types.h"
34#include "DNA_meta_types.h"
36#include "DNA_object_types.h"
37#include "DNA_scene_types.h"
38
40#include "BKE_armature.hh"
41#include "BKE_collection.hh"
42#include "BKE_constraint.h"
43#include "BKE_context.hh"
44#include "BKE_curve.hh"
45#include "BKE_editlattice.h"
46#include "BKE_editmesh.hh"
47#include "BKE_effect.h"
48#include "BKE_global.hh"
49#include "BKE_idprop.hh"
50#include "BKE_image.hh"
51#include "BKE_lattice.hh"
52#include "BKE_layer.hh"
53#include "BKE_lib_id.hh"
54#include "BKE_library.hh"
55#include "BKE_main.hh"
56#include "BKE_material.hh"
57#include "BKE_mball.hh"
58#include "BKE_mesh.hh"
59#include "BKE_modifier.hh"
60#include "BKE_node_runtime.hh"
61#include "BKE_object.hh"
62#include "BKE_paint.hh"
63#include "BKE_particle.h"
64#include "BKE_pointcache.h"
65#include "BKE_report.hh"
66#include "BKE_scene.hh"
67#include "BKE_screen.hh"
68#include "BKE_softbody.h"
69#include "BKE_workspace.hh"
70
71#include "DEG_depsgraph.hh"
73
74#include "ED_anim_api.hh"
75#include "ED_armature.hh"
76#include "ED_asset.hh"
78#include "ED_curve.hh"
79#include "ED_gpencil_legacy.hh"
80#include "ED_grease_pencil.hh"
81#include "ED_image.hh"
83#include "ED_lattice.hh"
84#include "ED_mball.hh"
85#include "ED_mesh.hh"
86#include "ED_object.hh"
87#include "ED_outliner.hh"
88#include "ED_screen.hh"
89#include "ED_undo.hh"
90
91#include "RNA_access.hh"
92#include "RNA_define.hh"
93#include "RNA_enum_types.hh"
94#include "RNA_types.hh"
95
96#include "UI_interface.hh"
97#include "UI_interface_icons.hh"
99
100#include "CLG_log.h"
101
102/* For menu/popup icons etc. */
103
104#include "UI_interface_layout.hh"
105#include "UI_resources.hh"
106
107#include "WM_api.hh"
108#include "WM_message.hh"
109#include "WM_toolsystem.hh"
110#include "WM_types.hh"
111
112#include "MOD_nodes.hh"
113
114#include "object_intern.hh" /* own include */
115
116namespace blender::ed::object {
117
118static CLG_LogRef LOG = {"object.edit"};
119
120/* prototypes */
122
123/* -------------------------------------------------------------------- */
126
128{
129 /* NOTE(@ideasman42): toggling modes while transforming should not be allowed by the key-map,
130 * so users should not be able do this. Python scripts can though,
131 * so check here to report an error instead of crashing.
132 *
133 * This is *not* a comprehensive check, since users might be trying to change modes
134 * while in the middle of *any* modal operator (painting or dragging a UI slider... etc).
135 *
136 * This check could be removed if it causes any problems since the error it prevents
137 * is quite obscure. See: #137380. */
138
139 if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
140 BKE_reportf(reports, RPT_ERROR, "Unable to change object mode while transforming");
141 return false;
142 }
143
144 return true;
145}
146
148{
149 return static_cast<Object *>(CTX_data_pointer_get_type(C, "object", &RNA_Object).data);
150}
151
153{
154 Object *ob = nullptr;
155 if (C) {
156 ob = context_object(C);
157 if (!ob) {
159 }
160 }
161 return ob;
162}
163
165 bool (*filter_fn)(const Object *ob, void *user_data),
166 void *filter_user_data)
167{
168 ScrArea *area = CTX_wm_area(C);
169 const Scene *scene = CTX_data_scene(C);
170 ViewLayer *view_layer = CTX_data_view_layer(C);
171 BKE_view_layer_synced_ensure(scene, view_layer);
172 Object *ob_active = BKE_view_layer_active_object_get(view_layer);
173 ID *id_pin = nullptr;
174 const bool use_objects_in_mode = (ob_active != nullptr) &&
175 (ob_active->mode & (OB_MODE_EDIT | OB_MODE_POSE));
176 const eSpace_Type space_type = area ? eSpace_Type(area->spacetype) : SPACE_EMPTY;
177
178 Object *ob = nullptr;
179 bool use_ob = true;
180
181 if (space_type == SPACE_PROPERTIES) {
182 SpaceProperties *sbuts = static_cast<SpaceProperties *>(area->spacedata.first);
183 id_pin = sbuts->pinid;
184 }
185
186 if (id_pin && (GS(id_pin->name) == ID_OB)) {
187 /* Pinned data takes priority, in this case ignore selection & other objects in the mode. */
188 ob = (Object *)id_pin;
189 }
190 else if ((space_type == SPACE_PROPERTIES) && (use_objects_in_mode == false)) {
191 /* When using the space-properties, we don't want to use the entire selection
192 * as the current active object may not be selected.
193 *
194 * This is not the case when we're in a mode that supports multi-mode editing,
195 * since the active object and all other objects in the mode will be included
196 * irrespective of selection. */
197 ob = ob_active;
198 }
199 else if (ob_active && (ob_active->mode &
201 {
202 /* When painting, limit to active. */
203 ob = ob_active;
204 }
205 else {
206 /* Otherwise use full selection. */
207 use_ob = false;
208 }
209
210 if (use_ob) {
211 if ((ob != nullptr) && !filter_fn(ob, filter_user_data)) {
212 ob = nullptr;
213 }
214 return ob ? Vector<Object *>({ob}) : Vector<Object *>();
215 }
216 const View3D *v3d = (space_type == SPACE_VIEW3D) ?
217 static_cast<const View3D *>(area->spacedata.first) :
218 nullptr;
219
220 /* When in a mode that supports multiple active objects, use "objects in mode"
221 * instead of the object's selection. */
222 if (use_objects_in_mode) {
224 params.object_mode = ob_active->mode;
225 params.no_dup_data = true;
226 params.filter_fn = filter_fn;
227 params.filter_userdata = filter_user_data;
228 return BKE_view_layer_array_from_objects_in_mode_params(scene, view_layer, v3d, &params);
229 }
230
232 params.no_dup_data = true;
233 params.filter_fn = filter_fn;
234 params.filter_userdata = filter_user_data;
236}
237
239
240/* -------------------------------------------------------------------- */
243
245 ViewLayer *view_layer,
246 const eObjectMode mode,
247 const Object *ob)
248{
249 BLI_assert(ob != nullptr);
250 /* NOTE: the `v3d` is always nullptr because the purpose of this function is to return
251 * a reusable index, using the `v3d` only increases the chance the index may become
252 * invalid-parameters. */
253 int index = -1;
254 int i = 0;
255 FOREACH_BASE_IN_MODE_BEGIN (scene, view_layer, nullptr, -1, mode, base_iter) {
256 if (base_iter->object == ob) {
257 index = i;
258 break;
259 }
260 i++;
261 }
263 return index;
264}
265
267 ViewLayer *view_layer,
268 const eObjectMode mode,
269 int index)
270{
271 BLI_assert(index >= 0);
272 Object *ob = nullptr;
273 int i = 0;
274 FOREACH_BASE_IN_MODE_BEGIN (scene, view_layer, nullptr, -1, mode, base_iter) {
275 if (index == i) {
276 ob = base_iter->object;
277 break;
278 }
279 i++;
280 }
282 return ob;
283}
284
286
287/* -------------------------------------------------------------------- */
290
292{
293 if (CTX_wm_space_outliner(C) != nullptr) {
295 }
297}
298
300{
301 Scene *scene = CTX_data_scene(C);
302 ViewLayer *view_layer = CTX_data_view_layer(C);
303 const bool select = RNA_boolean_get(op->ptr, "select");
304 bool changed = false;
305
306 BKE_view_layer_synced_ensure(scene, view_layer);
308 if (base->flag & BASE_HIDDEN) {
309 base->flag &= ~BASE_HIDDEN;
310 changed = true;
311
312 if (select) {
313 /* We cannot call `base_select` because
314 * base is not selectable while it is hidden. */
315 base->flag |= BASE_SELECTED;
317 }
318 }
319 }
320
321 if (!changed) {
322 return OPERATOR_CANCELLED;
323 }
324
329
330 return OPERATOR_FINISHED;
331}
332
334{
335 /* identifiers */
336 ot->name = "Show Hidden Objects";
337 ot->description = "Reveal temporarily hidden objects";
338 ot->idname = "OBJECT_OT_hide_view_clear";
339
340 /* API callbacks. */
342 ot->poll = object_hide_poll;
343
344 /* flags */
346
347 RNA_def_boolean(ot->srna, "select", true, "Select", "Select revealed objects");
348}
349
351{
352 Scene *scene = CTX_data_scene(C);
353 ViewLayer *view_layer = CTX_data_view_layer(C);
354 const bool unselected = RNA_boolean_get(op->ptr, "unselected");
355 bool changed = false;
356 const bool confirm = op->flag & OP_IS_INVOKE;
357 uint hide_count = 0;
358
359 /* Hide selected or unselected objects. */
360 BKE_view_layer_synced_ensure(scene, view_layer);
363 continue;
364 }
365
366 if (!unselected) {
367 if (base->flag & BASE_SELECTED) {
369 base->flag |= BASE_HIDDEN;
370 hide_count++;
371 changed = true;
372 }
373 }
374 else {
375 if (!(base->flag & BASE_SELECTED)) {
377 base->flag |= BASE_HIDDEN;
378 hide_count++;
379 changed = true;
380 }
381 }
382 }
383 if (!changed) {
384 return OPERATOR_CANCELLED;
385 }
386
387 if (hide_count > 0 && confirm) {
388 BKE_reportf(op->reports, RPT_INFO, "%u object(s) hidden", (hide_count));
389 }
390
395
396 return OPERATOR_FINISHED;
397}
398
400{
401 /* identifiers */
402 ot->name = "Hide Objects";
403 ot->description = "Temporarily hide objects from the viewport";
404 ot->idname = "OBJECT_OT_hide_view_set";
405
406 /* API callbacks. */
408 ot->poll = object_hide_poll;
409
410 /* flags */
412
413 PropertyRNA *prop;
414 prop = RNA_def_boolean(
415 ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected objects");
417}
418
420{
421 View3D *v3d = CTX_wm_view3d(C);
422
423 int index = RNA_int_get(op->ptr, "collection_index");
424 const bool extend = RNA_boolean_get(op->ptr, "extend");
425 const bool toggle = RNA_boolean_get(op->ptr, "toggle");
426
427 Scene *scene = CTX_data_scene(C);
428 ViewLayer *view_layer = CTX_data_view_layer(C);
429 LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
430
431 if (!lc) {
432 return OPERATOR_CANCELLED;
433 }
434
436
437 if (v3d && v3d->flag & V3D_LOCAL_COLLECTIONS) {
439 return OPERATOR_CANCELLED;
440 }
441 if (toggle) {
443 BKE_layer_collection_local_sync(scene, view_layer, v3d);
444 }
445 else {
446 BKE_layer_collection_isolate_local(scene, view_layer, v3d, lc, extend);
447 }
448 }
449 else {
450 BKE_layer_collection_isolate_global(scene, view_layer, lc, extend);
451 }
452
454
455 return OPERATOR_FINISHED;
456}
457
458#define COLLECTION_INVALID_INDEX -1
459
461{
462 const Scene *scene = CTX_data_scene(C);
463 ViewLayer *view_layer = CTX_data_view_layer(C);
464 LayerCollection *lc_scene = static_cast<LayerCollection *>(view_layer->layer_collections.first);
465
466 /* Use the "invoke" operator context so the "Shift" modifier is used to extend. */
468
470 int index = BKE_layer_collection_findindex(view_layer, lc);
471 uiLayout *row = &layout->row(false);
472
473 if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
474 continue;
475 }
476
477 if (lc->collection->flag & COLLECTION_HIDE_VIEWPORT) {
478 continue;
479 }
480
481 int icon = ICON_NONE;
482 if (BKE_layer_collection_has_selected_objects(scene, view_layer, lc)) {
483 icon = ICON_LAYER_ACTIVE;
484 }
485 else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) {
486 icon = ICON_LAYER_USED;
487 }
488 PointerRNA op_ptr = row->op("OBJECT_OT_hide_collection", lc->collection->id.name + 2, icon);
489 RNA_int_set(&op_ptr, "collection_index", index);
490 }
491}
492
494 wmOperator *op,
495 const wmEvent *event)
496{
497 /* Immediately execute if collection index was specified. */
498 int index = RNA_int_get(op->ptr, "collection_index");
499 if (index != COLLECTION_INVALID_INDEX) {
500 /* Only initialize extend from the shift key if the property isn't set
501 * (typically initialized from the key-map). */
502 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "extend");
503 if (!RNA_property_is_set(op->ptr, prop)) {
504 RNA_property_boolean_set(op->ptr, prop, (event->modifier & KM_SHIFT) != 0);
505 }
506 return object_hide_collection_exec(C, op);
507 }
508
509 /* Open popup menu. */
510 const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
511 uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_OUTLINER_COLLECTION);
512 uiLayout *layout = UI_popup_menu_layout(pup);
513
515
516 UI_popup_menu_end(C, pup);
517
518 return OPERATOR_INTERFACE;
519}
520
522{
523 /* identifiers */
524 ot->name = "Hide Other Collections";
525 ot->description = "Show only objects in collection (Shift to extend)";
526 ot->idname = "OBJECT_OT_hide_collection";
527
528 /* API callbacks. */
531
532 /* flags */
534
535 /* Properties. */
536 PropertyRNA *prop;
537 prop = RNA_def_int(ot->srna,
538 "collection_index",
541 INT_MAX,
542 "Collection Index",
543 "Index of the collection to change visibility",
544 0,
545 INT_MAX);
547 prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "Toggle visibility");
549 prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend visibility");
551}
552
554
555/* -------------------------------------------------------------------- */
558
559/* When switching mode, certain data needs to be copied from the `bPoseChannel` to the `Bone`. This
560 * is not done in `BKE_pose_rebuild` because that is called in other cases other than mode
561 * switching. */
563{
564 BLI_assert(ob.pose);
565 LISTBASE_FOREACH (bPoseChannel *, pose_bone, &ob.pose->chanbase) {
566 if (pose_bone->bone->flag & BONE_SELECTED) {
567 pose_bone->flag |= POSE_SELECTED;
568 }
569 else {
570 pose_bone->flag &= ~POSE_SELECTED;
571 }
572 }
573}
575{
576 BLI_assert(ob.pose);
577 constexpr int selection_flags = (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
578 LISTBASE_FOREACH (bPoseChannel *, pose_bone, &ob.pose->chanbase) {
579 if (pose_bone->flag & POSE_SELECTED) {
580 pose_bone->bone->flag |= selection_flags;
581 }
582 else {
583 pose_bone->bone->flag &= ~selection_flags;
584 }
585 }
586}
587
588static bool mesh_needs_keyindex(Main *bmain, const Mesh *mesh)
589{
590 if (mesh->key) {
591 return false; /* will be added */
592 }
593
594 LISTBASE_FOREACH (const Object *, ob, &bmain->objects) {
595 if ((ob->parent) && (ob->parent->data == mesh) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
596 return true;
597 }
598 if (ob->data == mesh) {
599 LISTBASE_FOREACH (const ModifierData *, md, &ob->modifiers) {
600 if (md->type == eModifierType_Hook) {
601 return true;
602 }
603 }
604 }
605 }
606 return false;
607}
608
615static bool editmode_load_free_ex(Main *bmain,
616 Object *obedit,
617 const bool load_data,
618 const bool free_data)
619{
621
622 if (obedit == nullptr) {
623 return false;
624 }
625
626 if (obedit->type == OB_MESH) {
627 Mesh *mesh = static_cast<Mesh *>(obedit->data);
628 if (mesh->runtime->edit_mesh == nullptr) {
629 return false;
630 }
631
632 if (mesh->runtime->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
633 /* This used to be warned int the UI, we could warn again although it's quite rare. */
634 CLOG_WARN(&LOG,
635 "Too many vertices for mesh '%s' (%d)",
636 mesh->id.name + 2,
637 mesh->runtime->edit_mesh->bm->totvert);
638 return false;
639 }
640
641 if (load_data) {
642 EDBM_mesh_load_ex(bmain, obedit, free_data);
643 }
644
645 if (free_data) {
646 EDBM_mesh_free_data(mesh->runtime->edit_mesh.get());
647 mesh->runtime->edit_mesh.reset();
648 }
649 /* will be recalculated as needed. */
650 {
653 }
654 }
655 else if (obedit->type == OB_ARMATURE) {
656 const bArmature *arm = static_cast<const bArmature *>(obedit->data);
657 if (arm->edbo == nullptr) {
658 return false;
659 }
660
661 if (load_data) {
662 ED_armature_from_edit(bmain, static_cast<bArmature *>(obedit->data));
663 }
664
665 if (free_data) {
666 ED_armature_edit_free(static_cast<bArmature *>(obedit->data));
667
668 if (load_data == false) {
669 /* Don't keep unused pose channels created by duplicating bones
670 * which may have been deleted/undone, see: #87631. */
671 if (obedit->pose != nullptr) {
673 }
674 }
675 }
676
677 /* After regenerating the bones, sync the selection onto the pose bones. */
679 /* TODO(sergey): Pose channels might have been changed, so need
680 * to inform dependency graph about this. But is it really the
681 * best place to do this?
682 */
684 }
685 else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) {
686 const Curve *cu = static_cast<const Curve *>(obedit->data);
687 if (cu->editnurb == nullptr) {
688 return false;
689 }
690
691 if (load_data) {
692 ED_curve_editnurb_load(bmain, obedit);
693 }
694
695 if (free_data) {
697 }
698 }
699 else if (obedit->type == OB_FONT) {
700 const Curve *cu = static_cast<const Curve *>(obedit->data);
701 if (cu->editfont == nullptr) {
702 return false;
703 }
704
705 if (load_data) {
707 }
708
709 if (free_data) {
711 }
712 }
713 else if (obedit->type == OB_LATTICE) {
714 const Lattice *lt = static_cast<const Lattice *>(obedit->data);
715 if (lt->editlatt == nullptr) {
716 return false;
717 }
718
719 if (load_data) {
720 BKE_editlattice_load(obedit);
721 }
722
723 if (free_data) {
724 BKE_editlattice_free(obedit);
725 }
726 }
727 else if (obedit->type == OB_MBALL) {
728 const MetaBall *mb = static_cast<const MetaBall *>(obedit->data);
729 if (mb->editelems == nullptr) {
730 return false;
731 }
732
733 if (load_data) {
735 }
736
737 if (free_data) {
739 }
740 }
741 else if (ELEM(obedit->type, OB_CURVES, OB_GREASE_PENCIL, OB_POINTCLOUD)) {
742 /* Object doesn't have specific edit mode data, so pass. */
743 }
744 else {
745 return false;
746 }
747
748 if (load_data) {
749 char *needs_flush_ptr = BKE_object_data_editmode_flush_ptr_get(
750 static_cast<ID *>(obedit->data));
751 if (needs_flush_ptr) {
752 *needs_flush_ptr = false;
753 }
754 }
755
756 return true;
757}
758
759bool editmode_load(Main *bmain, Object *obedit)
760{
761 return editmode_load_free_ex(bmain, obedit, true, false);
762}
763
764bool editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag)
765{
766 const bool free_data = (flag & EM_FREEDATA) != 0;
767
768 if (editmode_load_free_ex(bmain, obedit, true, free_data) == false) {
769 /* in rare cases (background mode) its possible active object
770 * is flagged for editmode, without 'obedit' being set #35489. */
771 if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
772 obedit->mode &= ~OB_MODE_EDIT;
773 /* Also happens when mesh is shared across multiple objects. #69834. */
775 /* Leaving edit mode may modify the original object data; tag that as well. */
776 DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
777 }
778 return true;
779 }
780
781 /* `free_data` only false now on file saves and render. */
782 if (free_data) {
783 /* flag object caches as outdated */
784 ListBase pidlist;
785 BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
786 LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
787 /* particles don't need reset on geometry change */
788 if (pid->type != PTCACHE_TYPE_PARTICLES) {
789 pid->cache->flag |= PTCACHE_OUTDATED;
790 }
791 }
792 BLI_freelistN(&pidlist);
793
796
797 /* also flush ob recalc, doesn't take much overhead, but used for particles */
799 /* Leaving edit mode may modify the original object data; tag that as well. */
800 DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
801
803
804 obedit->mode &= ~OB_MODE_EDIT;
805 }
806
807 return (obedit->mode & OB_MODE_EDIT) == 0;
808}
809
811{
812 Main *bmain = CTX_data_main(C);
813 Scene *scene = CTX_data_scene(C);
814 Object *obedit = CTX_data_edit_object(C);
815 return editmode_exit_ex(bmain, scene, obedit, flag);
816}
817
818bool editmode_free_ex(Main *bmain, Object *obedit)
819{
820 return editmode_load_free_ex(bmain, obedit, false, true);
821}
822
823bool editmode_exit_multi_ex(Main *bmain, Scene *scene, ViewLayer *view_layer, int flag)
824{
825 BKE_view_layer_synced_ensure(scene, view_layer);
826 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
827 if (obedit == nullptr) {
828 return false;
829 }
830 bool changed = false;
831 const short obedit_type = obedit->type;
832
833 BKE_view_layer_synced_ensure(scene, view_layer);
835 Object *ob = base->object;
836 if ((ob->type == obedit_type) && (ob->mode & OB_MODE_EDIT)) {
837 changed |= editmode_exit_ex(bmain, scene, base->object, flag);
838 }
839 }
840 return changed;
841}
842
844{
845 Main *bmain = CTX_data_main(C);
846 Scene *scene = CTX_data_scene(C);
847 ViewLayer *view_layer = CTX_data_view_layer(C);
848 return editmode_exit_multi_ex(bmain, scene, view_layer, flag);
849}
850
851bool editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
852{
853 bool ok = false;
854
855 if (ELEM(nullptr, ob, ob->data) || !ID_IS_EDITABLE(ob) || ID_IS_OVERRIDE_LIBRARY(ob) ||
857 {
858 return false;
859 }
860
861 /* This checks actual `ob->data`, for cases when other scenes have it in edit-mode context.
862 * Currently multiple objects sharing a mesh being in edit-mode at once isn't supported,
863 * see: #86767. */
865 return true;
866 }
867
869 /* Ideally the caller should check this. */
870 CLOG_WARN(&LOG, "Unable to enter edit-mode on library data for object '%s'", ob->id.name + 2);
871 return false;
872 }
873
874 ob->restore_mode = ob->mode;
875
876 ob->mode = OB_MODE_EDIT;
877
878 if (ob->type == OB_MESH) {
879 ok = true;
880
881 const bool use_key_index = mesh_needs_keyindex(bmain, static_cast<const Mesh *>(ob->data));
882
883 EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
884
886 if (LIKELY(em)) {
888 }
889
891 }
892 else if (ob->type == OB_ARMATURE) {
893 /* Syncing the selection to the `Bone` before converting to edit bones. This is not possible if
894 * the Armature was just created, because then there is no pose data yet. Which is fine, the
895 * just-created edit bones already have the expected selection state. */
896 if (ob->pose) {
898 }
899
900 bArmature *arm = static_cast<bArmature *>(ob->data);
901 ok = true;
903 /* To ensure all goes in rest-position and without striding. */
904
905 arm->needs_flush_to_id = 0;
906
907 /* WORKAROUND / FIXME: this is a temporary workaround to ensure that
908 * full bone collection data gets restored when exiting edit mode
909 * via an undo step. The correct fix is to have a full edit-mode
910 * copy of bone collections so that edit-mode changes don't modify
911 * object-mode armature data until exiting edit mode. But that
912 * change is a bit of a project, and will be done later. This line
913 * should be removed when that is done. */
914 bmain->is_memfile_undo_written = false;
915
916 /* XXX: should this be ID_RECALC_GEOMETRY? */
918
920 }
921 else if (ob->type == OB_FONT) {
922 ok = true;
924
926 }
927 else if (ob->type == OB_MBALL) {
928 MetaBall *mb = static_cast<MetaBall *>(ob->data);
929
930 ok = true;
932
933 mb->needs_flush_to_id = 0;
934
936 }
937 else if (ob->type == OB_LATTICE) {
938 ok = true;
940
942 }
943 else if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY)) {
944 ok = true;
946
948 }
949 else if (ob->type == OB_CURVES) {
950 ok = true;
952 }
953 else if (ob->type == OB_GREASE_PENCIL) {
954 ok = true;
957 }
958 else if (ob->type == OB_POINTCLOUD) {
959 ok = true;
961 }
962
963 if (ok) {
965 }
966 else {
967 if ((flag & EM_NO_CONTEXT) == 0) {
968 ob->mode &= ~OB_MODE_EDIT;
969 }
971 }
972
973 return (ob->mode & OB_MODE_EDIT) != 0;
974}
975
977{
978 Main *bmain = CTX_data_main(C);
979 Scene *scene = CTX_data_scene(C);
980
981 /* Active layer checked here for view3d,
982 * callers that don't want view context can call the extended version. */
984 return editmode_enter_ex(bmain, scene, ob, flag);
985}
986
988{
989 Main *bmain = CTX_data_main(C);
990 Scene *scene = CTX_data_scene(C);
991 View3D *v3d = CTX_wm_view3d(C);
992 ViewLayer *view_layer = CTX_data_view_layer(C);
993 BKE_view_layer_synced_ensure(scene, view_layer);
994 Object *obact = BKE_view_layer_active_object_get(view_layer);
995 const int mode_flag = OB_MODE_EDIT;
996 const bool is_mode_set = (obact->mode & mode_flag) != 0;
998
1000 return OPERATOR_CANCELLED;
1001 }
1002 if (!is_mode_set) {
1003 if (!mode_compat_set(C, obact, eObjectMode(mode_flag), op->reports)) {
1004 return OPERATOR_CANCELLED;
1005 }
1006 }
1007
1008 if (!is_mode_set) {
1009 editmode_enter_ex(bmain, scene, obact, 0);
1010 /* Grease Pencil does not support multi-object editing. */
1011 if ((obact->type != OB_GREASE_PENCIL) && ((obact->mode & mode_flag) != 0)) {
1012 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
1013 if ((ob != obact) && (ob->type == obact->type)) {
1014 editmode_enter_ex(bmain, scene, ob, EM_NO_CONTEXT);
1015 }
1016 }
1018 }
1019 }
1020 else {
1021 editmode_exit_ex(bmain, scene, obact, EM_FREEDATA);
1022
1023 if ((obact->mode & mode_flag) == 0) {
1024 FOREACH_OBJECT_BEGIN (scene, view_layer, ob) {
1025 if ((ob != obact) && (ob->type == obact->type)) {
1026 editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
1027 }
1028 }
1030 }
1031 }
1032
1033 WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
1034
1035 if (G.background == false) {
1037 }
1038
1039 return OPERATOR_FINISHED;
1040}
1041
1043{
1044 /* Get object the same way as in editmode_toggle_exec(). Otherwise overriding context can crash,
1045 * see #137998. */
1046 ViewLayer *view_layer = CTX_data_view_layer(C);
1048 Object *ob = BKE_view_layer_active_object_get(view_layer);
1049
1050 /* Covers liboverrides too. */
1051 if (ELEM(nullptr, ob, ob->data) || !ID_IS_EDITABLE(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob) ||
1053 {
1054 return false;
1055 }
1056
1057 /* If hidden but in edit mode, we still display. */
1058 if ((ob->visibility_flag & OB_HIDE_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) {
1059 return false;
1060 }
1061
1062 return OB_TYPE_SUPPORT_EDITMODE(ob->type);
1063}
1064
1066{
1067
1068 /* identifiers */
1069 ot->name = "Edit Mode";
1070 ot->description = "Toggle object's edit mode";
1071 ot->idname = "OBJECT_OT_editmode_toggle";
1072
1073 /* API callbacks. */
1074 ot->exec = editmode_toggle_exec;
1075 ot->poll = editmode_toggle_poll;
1076
1077 /* flags */
1078 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1079}
1080
1082
1083/* -------------------------------------------------------------------- */
1086
1088{
1089 wmMsgBus *mbus = CTX_wm_message_bus(C);
1090 Main *bmain = CTX_data_main(C);
1091 Scene *scene = CTX_data_scene(C);
1092 ViewLayer *view_layer = CTX_data_view_layer(C);
1093 Base *base = CTX_data_active_base(C);
1094
1096 return OPERATOR_CANCELLED;
1097 }
1098
1099 /* If the base is nullptr it means we have an active object, but the object itself is hidden. */
1100 if (base == nullptr) {
1101 return OPERATOR_CANCELLED;
1102 }
1103
1104 Object *obact = base->object;
1105 const int mode_flag = OB_MODE_POSE;
1106 bool is_mode_set = (obact->mode & mode_flag) != 0;
1107
1108 if (!is_mode_set) {
1109 if (!mode_compat_set(C, obact, eObjectMode(mode_flag), op->reports)) {
1110 return OPERATOR_CANCELLED;
1111 }
1112 }
1113
1114 if (obact->type != OB_ARMATURE) {
1115 return OPERATOR_PASS_THROUGH;
1116 }
1117
1118 {
1119 BKE_view_layer_synced_ensure(scene, view_layer);
1120 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
1121 if (obact == obedit) {
1122 editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
1123 is_mode_set = false;
1124 }
1125 }
1126
1127 if (is_mode_set) {
1128 bool ok = ED_object_posemode_exit(C, obact);
1129 if (ok) {
1130 FOREACH_OBJECT_BEGIN (scene, view_layer, ob) {
1131 if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) {
1132 ED_object_posemode_exit_ex(bmain, ob);
1133 }
1134 }
1136 }
1137 }
1138 else {
1139 bool ok = ED_object_posemode_enter(C, obact);
1140 if (ok) {
1141 const View3D *v3d = CTX_wm_view3d(C);
1142 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
1143 if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) &&
1144 BKE_id_is_editable(bmain, &ob->id))
1145 {
1146 ED_object_posemode_enter_ex(bmain, ob);
1147 }
1148 }
1150 }
1151 }
1152
1153 WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
1154
1155 if (G.background == false) {
1157 }
1158
1159 return OPERATOR_FINISHED;
1160}
1161
1163{
1164 /* identifiers */
1165 ot->name = "Toggle Pose Mode";
1166 ot->idname = "OBJECT_OT_posemode_toggle";
1167 ot->description = "Enable or disable posing/selecting bones";
1168
1169 /* API callbacks. */
1170 ot->exec = posemode_exec;
1172
1173 /* flag */
1174 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1175}
1176
1178
1179/* -------------------------------------------------------------------- */
1182
1183void check_force_modifiers(Main *bmain, Scene *scene, Object *object)
1184{
1185 PartDeflect *pd = object->pd;
1187
1188 /* add/remove modifier as needed */
1189 if (!md) {
1190 if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) &&
1192 {
1194 modifier_add(nullptr, bmain, scene, object, nullptr, eModifierType_Surface);
1195 }
1196 }
1197 }
1198 else {
1199 if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) ||
1201 {
1202 modifier_remove(nullptr, bmain, scene, object, md);
1203 }
1204 }
1205}
1206
1208{
1210
1211 if (ob->pd == nullptr) {
1214 }
1215 else if (ob->pd->forcefield == 0) {
1216 ob->pd->forcefield = PFIELD_FORCE;
1218 }
1219 else {
1220 ob->pd->forcefield = 0;
1221 }
1222
1226
1228
1229 return OPERATOR_FINISHED;
1230}
1231
1233{
1234
1235 /* identifiers */
1236 ot->name = "Toggle Force Field";
1237 ot->description = "Toggle object's force field";
1238 ot->idname = "OBJECT_OT_forcefield_toggle";
1239
1240 /* API callbacks. */
1241 ot->exec = forcefield_toggle_exec;
1243
1244 /* flags */
1245 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1246}
1247
1249
1250/* -------------------------------------------------------------------- */
1253
1266
1268{
1269 ListBase selected_objects = {nullptr, nullptr};
1270 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1271 BLI_addtail(&selected_objects, BLI_genericNodeN(ob));
1272 }
1274
1275 motion_paths_recalc(C, scene, range, &selected_objects);
1276
1277 BLI_freelistN(&selected_objects);
1278}
1279
1281{
1282 ListBase visible_objects = {nullptr, nullptr};
1283 CTX_DATA_BEGIN (C, Object *, ob, visible_objects) {
1284 BLI_addtail(&visible_objects, BLI_genericNodeN(ob));
1285 }
1287
1288 motion_paths_recalc(C, scene, range, &visible_objects);
1289
1290 BLI_freelistN(&visible_objects);
1291}
1292
1294{
1295 return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1296}
1297
1299{
1300 return ob->pose && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1301}
1302
1304 Scene *scene,
1306 ListBase *ld_objects)
1307{
1308 /* Transform doesn't always have context available to do update. */
1309 if (C == nullptr) {
1310 return;
1311 }
1312
1313 Main *bmain = CTX_data_main(C);
1314 ViewLayer *view_layer = CTX_data_view_layer(C);
1315
1317 LISTBASE_FOREACH (LinkData *, link, ld_objects) {
1318 Object *ob = static_cast<Object *>(link->data);
1319
1320 /* set flag to force recalc, then grab path(s) from object */
1321 if (has_object_motion_paths(ob)) {
1323 }
1324
1325 if (has_pose_motion_paths(ob)) {
1327 }
1328
1330 }
1331
1332 Depsgraph *depsgraph;
1333 bool free_depsgraph = false;
1334 /* For a single frame update it's faster to re-use existing dependency graph and avoid overhead
1335 * of building all the relations and so on for a temporary one. */
1337 /* NOTE: Dependency graph will be evaluated at all the frames, but we first need to access some
1338 * nested pointers, like animation data. */
1340 free_depsgraph = false;
1341 }
1342 else {
1343 depsgraph = animviz_depsgraph_build(bmain, scene, view_layer, targets);
1344 free_depsgraph = true;
1345 }
1346
1348 depsgraph, bmain, scene, targets, object_path_convert_range(range), true);
1350
1352 /* Tag objects for copy-on-eval - so paths will draw/redraw
1353 * For currently frame only we update evaluated object directly. */
1354 LISTBASE_FOREACH (LinkData *, link, ld_objects) {
1355 Object *ob = static_cast<Object *>(link->data);
1356
1359 }
1360 }
1361 }
1362
1363 /* Free temporary depsgraph. */
1364 if (free_depsgraph) {
1366 }
1367}
1368
1369/* show popup to determine settings */
1371 wmOperator *op,
1372 const wmEvent * /*event*/)
1373{
1375
1376 if (ob == nullptr) {
1377 return OPERATOR_CANCELLED;
1378 }
1379
1380 /* set default settings from existing/stored settings */
1381 {
1382 bAnimVizSettings *avs = &ob->avs;
1383 RNA_enum_set(op->ptr, "display_type", avs->path_type);
1384 RNA_enum_set(op->ptr, "range", avs->path_range);
1385 }
1386
1387 /* show popup dialog to allow editing of range... */
1388 /* FIXME: hard-coded dimensions here are just arbitrary. */
1390 C, op, 270, IFACE_("Calculate Object Motion Paths"), IFACE_("Calculate"));
1391}
1392
1393/* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */
1395{
1396 Scene *scene = CTX_data_scene(C);
1397 short path_type = RNA_enum_get(op->ptr, "display_type");
1398 short path_range = RNA_enum_get(op->ptr, "range");
1399
1400 /* set up path data for objects being calculated */
1401 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1402 bAnimVizSettings *avs = &ob->avs;
1403 /* grab baking settings from operator settings */
1404 avs->path_type = path_type;
1405 avs->path_range = path_range;
1407
1408 /* verify that the selected object has the appropriate settings */
1409 animviz_verify_motionpaths(op->reports, scene, ob, nullptr);
1410 }
1412
1413 /* calculate the paths for objects that have them (and are tagged to get refreshed) */
1415
1416 /* notifiers for updates */
1418 /* NOTE: the notifier below isn't actually correct, but kept around just to be on the safe side.
1419 * If further testing shows it's not necessary (for both bones and objects) removal is fine. */
1421
1422 return OPERATOR_FINISHED;
1423}
1424
1426{
1427 /* identifiers */
1428 ot->name = "Calculate Object Motion Paths";
1429 ot->idname = "OBJECT_OT_paths_calculate";
1430 ot->description = "Generate motion paths for the selected objects";
1431
1432 /* API callbacks. */
1436
1437 /* flags */
1438 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1439
1440 /* properties */
1441 RNA_def_enum(ot->srna,
1442 "display_type",
1445 "Display Type",
1446 "");
1447 RNA_def_enum(ot->srna,
1448 "range",
1451 "Computation Range",
1452 "");
1453}
1454
1456
1457/* -------------------------------------------------------------------- */
1460
1462{
1465 return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1466 }
1467
1468 return false;
1469}
1470
1472{
1473 Scene *scene = CTX_data_scene(C);
1474
1475 if (scene == nullptr) {
1476 return OPERATOR_CANCELLED;
1477 }
1478 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1480 /* verify that the selected object has the appropriate settings */
1481 animviz_verify_motionpaths(op->reports, scene, ob, nullptr);
1482 }
1484
1485 /* calculate the paths for objects that have them (and are tagged to get refreshed) */
1487
1488 /* notifiers for updates */
1490 /* NOTE: the notifier below isn't actually correct, but kept around just to be on the safe side.
1491 * If further testing shows it's not necessary (for both bones and objects) removal is fine. */
1493
1494 return OPERATOR_FINISHED;
1495}
1496
1498{
1499 /* identifiers */
1500 ot->name = "Update Object Paths";
1501 ot->idname = "OBJECT_OT_paths_update";
1502 ot->description = "Recalculate motion paths for selected objects";
1503
1504 /* API callbacks. */
1507
1508 /* flags */
1509 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1510}
1511
1513
1514/* -------------------------------------------------------------------- */
1517
1519{
1520 return true;
1521}
1522
1524{
1525 Scene *scene = CTX_data_scene(C);
1526
1527 if (scene == nullptr) {
1528 return OPERATOR_CANCELLED;
1529 }
1530
1532
1534
1535 return OPERATOR_FINISHED;
1536}
1537
1539{
1540 /* identifiers */
1541 ot->name = "Update All Object Paths";
1542 ot->idname = "OBJECT_OT_paths_update_visible";
1543 ot->description = "Recalculate all visible motion paths for objects and poses";
1544
1545 /* API callbacks. */
1548
1549 /* flags */
1550 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1551}
1552
1554
1555/* -------------------------------------------------------------------- */
1558
1559/* Helper for motion_paths_clear() */
1561{
1562 if (ob->mpath) {
1564 ob->mpath = nullptr;
1566
1567 /* tag object for copy-on-eval - so removed paths don't still show */
1569 }
1570}
1571
1572void motion_paths_clear(bContext *C, bool only_selected)
1573{
1574 if (only_selected) {
1575 /* Loop over all selected + editable objects in scene. */
1576 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1578 }
1580 }
1581 else {
1582 /* Loop over all editable objects in scene. */
1583 CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
1585 }
1587 }
1588}
1589
1590/* operator callback for this */
1592{
1593 bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
1594
1595 /* use the backend function for this */
1596 motion_paths_clear(C, only_selected);
1597
1598 /* notifiers for updates */
1600
1601 return OPERATOR_FINISHED;
1602}
1603
1605 wmOperatorType * /*ot*/,
1606 PointerRNA *ptr)
1607{
1608 const bool only_selected = RNA_boolean_get(ptr, "only_selected");
1609 if (only_selected) {
1610 return TIP_("Clear motion paths of selected objects");
1611 }
1612 return TIP_("Clear motion paths of all objects");
1613}
1614
1616{
1617 /* identifiers */
1618 ot->name = "Clear Object Paths";
1619 ot->idname = "OBJECT_OT_paths_clear";
1620
1621 /* API callbacks. */
1624 ot->get_description = object_clear_paths_get_description;
1625
1626 /* flags */
1627 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1628
1629 /* properties */
1630 ot->prop = RNA_def_boolean(ot->srna,
1631 "only_selected",
1632 false,
1633 "Only Selected",
1634 "Only clear motion paths of selected objects");
1636}
1637
1639
1640/* -------------------------------------------------------------------- */
1643
1645{
1646 if (md.type != eModifierType_Nodes) {
1647 return false;
1648 }
1649 const NodesModifierData &nmd = reinterpret_cast<const NodesModifierData &>(md);
1650 if (!nmd.node_group) {
1651 return false;
1652 }
1653 if (const LibraryWeakReference *library_ref = nmd.node_group->id.library_weak_reference) {
1654 /* Support appended assets added before asset packing in Blender 5.0. */
1655 if (!library_ref) {
1656 return false;
1657 }
1658 if (!STREQ(library_ref->library_id_name + 2, "Smooth by Angle")) {
1659 return false;
1660 }
1661 return true;
1662 }
1663 const Library *library = nmd.node_group->id.lib;
1664 if (!library) {
1665 return false;
1666 }
1667 char auto_smooth_asset_path[FILE_MAX] = "datafiles/assets/nodes/geometry_nodes_essentials.blend";
1668 BLI_path_slash_native(auto_smooth_asset_path);
1669 if (!StringRef(library->filepath).endswith(auto_smooth_asset_path)) {
1670 return false;
1671 }
1672 if (!STREQ(BKE_id_name(nmd.node_group->id), "Smooth by Angle")) {
1673 return false;
1674 }
1675 return true;
1676}
1677
1679{
1680 const bool use_flat = STREQ(op->idname, "OBJECT_OT_shade_flat");
1681 const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth");
1682 const bool use_smooth_by_angle = STREQ(op->idname, "OBJECT_OT_shade_smooth_by_angle");
1683 Main *bmain = CTX_data_main(C);
1684 Scene *scene = CTX_data_scene(C);
1685
1686 Vector<PointerRNA> ctx_objects;
1687
1688 /* For modes that only use an active object, don't handle the whole selection. */
1689 {
1690 Scene *scene = CTX_data_scene(C);
1691 ViewLayer *view_layer = CTX_data_view_layer(C);
1692 BKE_view_layer_synced_ensure(scene, view_layer);
1693 Object *obact = BKE_view_layer_active_object_get(view_layer);
1694 if (obact && (obact->mode & OB_MODE_ALL_PAINT)) {
1695 ctx_objects.append(RNA_id_pointer_create(&obact->id));
1696 }
1697 }
1698
1699 if (ctx_objects.is_empty()) {
1701 }
1702
1703 Set<ID *> object_data;
1704 for (const PointerRNA &ptr : ctx_objects) {
1705 Object *ob = static_cast<Object *>(ptr.data);
1706 if (ID *data = static_cast<ID *>(ob->data)) {
1707 object_data.add(data);
1708
1709 if (ob->type == OB_MESH) {
1710 if (use_flat || use_smooth) {
1712 if (is_smooth_by_angle_modifier(*md)) {
1713 modifier_remove(op->reports, bmain, scene, ob, md);
1716 break;
1717 }
1718 }
1719 }
1720 }
1721 }
1722 }
1723
1724 bool changed_multi = false;
1725 bool has_linked_data = false;
1726 for (ID *data : object_data) {
1727 if (!BKE_id_is_editable(bmain, data)) {
1728 has_linked_data = true;
1729 continue;
1730 }
1731
1732 bool changed = false;
1733 if (GS(data->name) == ID_ME) {
1734 Mesh &mesh = *reinterpret_cast<Mesh *>(data);
1735 const bool keep_sharp_edges = RNA_boolean_get(op->ptr, "keep_sharp_edges");
1736 bke::mesh_smooth_set(mesh, use_smooth || use_smooth_by_angle, keep_sharp_edges);
1737 if (use_smooth_by_angle) {
1738 const float angle = RNA_float_get(op->ptr, "angle");
1740 }
1742 changed = true;
1743 }
1744 else if (GS(data->name) == ID_CU_LEGACY) {
1745 BKE_curve_smooth_flag_set(reinterpret_cast<Curve *>(data), use_smooth);
1746 changed = true;
1747 }
1748
1749 if (changed) {
1750 changed_multi = true;
1753 }
1754 }
1755
1756 if (has_linked_data) {
1757 BKE_report(op->reports, RPT_WARNING, "Cannot edit linked mesh or curve data");
1758 }
1759
1760 return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1761}
1762
1763static bool shade_poll(bContext *C)
1764{
1765 const Scene *scene = CTX_data_scene(C);
1766 ViewLayer *view_layer = CTX_data_view_layer(C);
1767 BKE_view_layer_synced_ensure(scene, view_layer);
1768 Object *obact = BKE_view_layer_active_object_get(view_layer);
1769 if (obact != nullptr) {
1770 /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */
1771 if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT) || obact->data == nullptr ||
1772 !ID_IS_EDITABLE(obact) || !ID_IS_EDITABLE(obact->data) || ID_IS_OVERRIDE_LIBRARY(obact) ||
1774 {
1775 return false;
1776 }
1777 }
1778 return true;
1779}
1780
1782{
1783 /* identifiers */
1784 ot->name = "Shade Flat";
1785 ot->description = "Render and display faces uniform, using face normals";
1786 ot->idname = "OBJECT_OT_shade_flat";
1787
1788 /* API callbacks. */
1789 ot->poll = shade_poll;
1790 ot->exec = shade_smooth_exec;
1791
1792 /* flags */
1793 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1794
1795 RNA_def_boolean(ot->srna,
1796 "keep_sharp_edges",
1797 true,
1798 "Keep Sharp Edges",
1799 "Don't remove sharp edges, which are redundant with faces shaded smooth");
1800}
1801
1803{
1804 /* identifiers */
1805 ot->name = "Shade Smooth";
1806 ot->description = "Render and display faces smooth, using interpolated vertex normals";
1807 ot->idname = "OBJECT_OT_shade_smooth";
1808
1809 /* API callbacks. */
1810 ot->poll = shade_poll;
1811 ot->exec = shade_smooth_exec;
1812
1813 /* flags */
1814 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1815
1816 RNA_def_boolean(ot->srna,
1817 "keep_sharp_edges",
1818 true,
1819 "Keep Sharp Edges",
1820 "Don't remove sharp edges. Tagged edges will remain sharp");
1821}
1822
1824{
1825 ot->name = "Shade Smooth by Angle";
1826 ot->description =
1827 "Set the sharpness of mesh edges based on the angle between the neighboring faces";
1828 ot->idname = "OBJECT_OT_shade_smooth_by_angle";
1829
1830 ot->poll = shade_poll;
1831 ot->exec = shade_smooth_exec;
1832
1833 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1834
1835 PropertyRNA *prop = RNA_def_property(ot->srna, "angle", PROP_FLOAT, PROP_ANGLE);
1836 RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
1839 prop, "Angle", "Maximum angle between face normals that will be considered as smooth");
1840
1841 RNA_def_boolean(ot->srna,
1842 "keep_sharp_edges",
1843 true,
1844 "Keep Sharp Edges",
1845 "Only add sharp edges instead of clearing existing tags first");
1846}
1847
1849
1850/* -------------------------------------------------------------------- */
1853
1859{
1860 if (ntree.type != NTREE_GEOMETRY) {
1861 return false;
1862 }
1863 if (ntree.interface_inputs().size() != 3) {
1864 return false;
1865 }
1866 if (ntree.interface_outputs().size() != 1) {
1867 return false;
1868 }
1869 return true;
1870}
1871
1873{
1874 Main &bmain = *CTX_data_main(C);
1875 Scene &scene = *CTX_data_scene(C);
1876
1877 const bool use_auto_smooth = RNA_boolean_get(op->ptr, "use_auto_smooth");
1878 const float angle = RNA_float_get(op->ptr, "angle");
1879
1880 Vector<PointerRNA> ctx_objects;
1882
1883 if (use_auto_smooth) {
1884 AssetWeakReference asset_weak_ref{};
1886 asset_weak_ref.relative_asset_identifier = BLI_strdup(
1887 "nodes/geometry_nodes_essentials.blend/NodeTree/Smooth by Angle");
1888
1889 if (G.background) {
1890 /* For testing purposes, make sure assets are loaded (this make take too long to do
1891 * automatically during user interaction). */
1893 }
1894
1895 const asset_system::AssetRepresentation *asset_representation =
1896 asset::find_asset_from_weak_ref(*C, asset_weak_ref, op->reports);
1897 if (!asset_representation) {
1898 return OPERATOR_CANCELLED;
1899 }
1900
1901 bNodeTree *node_group = nullptr;
1902 while (!node_group) {
1903 ID *node_group_id = asset::asset_local_id_ensure_imported(bmain, *asset_representation);
1904 if (!node_group_id) {
1905 return OPERATOR_CANCELLED;
1906 }
1907 if (GS(node_group_id->name) != ID_NT) {
1908 return OPERATOR_CANCELLED;
1909 }
1910 node_group = reinterpret_cast<bNodeTree *>(node_group_id);
1911 node_group->ensure_topology_cache();
1912 node_group->ensure_interface_cache();
1913 if (is_valid_smooth_by_angle_group(*node_group)) {
1914 break;
1915 }
1916 /* Remove the weak library reference, since the already loaded group is not valid anymore. */
1917 MEM_SAFE_FREE(node_group_id->library_weak_reference);
1918 /* Stay in the loop and load the asset again. */
1919 node_group = nullptr;
1920 }
1921
1922 const StringRefNull angle_identifier = node_group->interface_inputs()[1]->identifier;
1923
1924 for (const PointerRNA &ob_ptr : ctx_objects) {
1925 Object *object = static_cast<Object *>(ob_ptr.data);
1926 if (object->type == OB_MESH) {
1927 Mesh *mesh = static_cast<Mesh *>(object->data);
1928 bke::mesh_smooth_set(*mesh, true, true);
1930 }
1931 NodesModifierData *smooth_by_angle_nmd = nullptr;
1932 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
1933 if (is_smooth_by_angle_modifier(*md)) {
1934 smooth_by_angle_nmd = reinterpret_cast<NodesModifierData *>(md);
1935 break;
1936 }
1937 }
1938 if (!smooth_by_angle_nmd) {
1939 smooth_by_angle_nmd = reinterpret_cast<NodesModifierData *>(
1940 modifier_add(op->reports, &bmain, &scene, object, nullptr, eModifierType_Nodes));
1941 if (!smooth_by_angle_nmd) {
1942 continue;
1943 }
1944 smooth_by_angle_nmd->modifier.flag |= eModifierFlag_PinLast;
1945 smooth_by_angle_nmd->node_group = node_group;
1946 id_us_plus(&node_group->id);
1947 MOD_nodes_update_interface(object, smooth_by_angle_nmd);
1948 smooth_by_angle_nmd->flag |= NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR |
1950 STRNCPY_UTF8(smooth_by_angle_nmd->modifier.name, DATA_(node_group->id.name + 2));
1951 BKE_modifier_unique_name(&object->modifiers, &smooth_by_angle_nmd->modifier);
1952 }
1953
1954 IDProperty *angle_prop = IDP_GetPropertyFromGroup(smooth_by_angle_nmd->settings.properties,
1955 angle_identifier.c_str());
1956 if (angle_prop->type == IDP_FLOAT) {
1957 IDP_float_set(angle_prop, angle);
1958 }
1959 else if (angle_prop->type == IDP_DOUBLE) {
1960 IDP_double_set(angle_prop, angle);
1961 }
1962
1965 }
1966 }
1967 else {
1968 for (const PointerRNA &ob_ptr : ctx_objects) {
1969 Object *object = static_cast<Object *>(ob_ptr.data);
1970 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
1971 if (is_smooth_by_angle_modifier(*md)) {
1972 modifier_remove(op->reports, &bmain, &scene, object, md);
1974 break;
1975 }
1976 }
1977 }
1978 }
1979
1980 return OPERATOR_FINISHED;
1981}
1982
1984{
1985 uiLayout *layout = op->layout;
1986
1987 layout->use_property_split_set(true);
1988 layout->use_property_decorate_set(false);
1989
1990 layout->prop(op->ptr, "use_auto_smooth", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1991
1992 uiLayout *col = &layout->column(false);
1993 col->active_set(RNA_boolean_get(op->ptr, "use_auto_smooth"));
1994 layout->prop(op->ptr, "angle", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1995}
1996
1998{
1999 ot->name = "Shade Auto Smooth";
2000 ot->description =
2001 "Add modifier to automatically set the sharpness of mesh edges based on the angle between "
2002 "the neighboring faces";
2003 ot->idname = "OBJECT_OT_shade_auto_smooth";
2004
2005 ot->poll = shade_poll;
2006 ot->exec = shade_auto_smooth_exec;
2008
2009 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2010
2011 PropertyRNA *prop;
2012
2013 prop = RNA_def_boolean(ot->srna,
2014 "use_auto_smooth",
2015 true,
2016 "Auto Smooth",
2017 "Add modifier to set edge sharpness automatically");
2019
2020 prop = RNA_def_property(ot->srna, "angle", PROP_FLOAT, PROP_ANGLE);
2021 RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
2024 prop, "Angle", "Maximum angle between face normals that will be considered as smooth");
2025}
2026
2028
2029/* -------------------------------------------------------------------- */
2032
2034 PointerRNA * /*ptr*/,
2035 PropertyRNA * /*prop*/,
2036 bool *r_free)
2037{
2039 EnumPropertyItem *item = nullptr;
2040 int totitem = 0;
2041
2042 if (!C) { /* needed for docs */
2044 }
2045
2046 const Object *ob = CTX_data_active_object(C);
2047 if (ob) {
2048 while (input->identifier) {
2049 if (mode_compat_test(ob, eObjectMode(input->value))) {
2050 RNA_enum_item_add(&item, &totitem, input);
2051 }
2052 input++;
2053 }
2054 }
2055 else {
2056 /* We need at least this one! */
2058 }
2059
2060 RNA_enum_item_end(&item, &totitem);
2061
2062 *r_free = true;
2063
2064 return item;
2065}
2066
2068{
2069 /* Needed as #ED_operator_object_active_editable doesn't call use 'active_object'. */
2072}
2073
2075{
2076 const bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode");
2078 eObjectMode mode = eObjectMode(RNA_enum_get(op->ptr, "mode"));
2079 const bool toggle = RNA_boolean_get(op->ptr, "toggle");
2080
2081 if (!mode_compat_test(ob, mode)) {
2082 return OPERATOR_PASS_THROUGH;
2083 }
2085 return OPERATOR_CANCELLED;
2086 }
2087
2106 if (toggle == false) {
2107 if (ob->mode != mode) {
2108 mode_set_ex(C, mode, true, op->reports);
2109 }
2110 }
2111 else {
2112 const eObjectMode mode_prev = eObjectMode(ob->mode);
2113 /* When toggling object mode, we always use the restore mode,
2114 * otherwise there is nothing to do. */
2115 if (mode == OB_MODE_OBJECT) {
2116 if (ob->mode != OB_MODE_OBJECT) {
2117 if (mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) {
2118 /* Store old mode so we know what to go back to. */
2119 ob->restore_mode = mode_prev;
2120 }
2121 }
2122 else {
2123 if (ob->restore_mode != OB_MODE_OBJECT) {
2124 mode_set_ex(C, eObjectMode(ob->restore_mode), true, op->reports);
2125 }
2126 }
2127 }
2128 else {
2129 /* Non-object modes, enter the 'mode' unless it's already set,
2130 * in that case use restore mode. */
2131 if (ob->mode != mode) {
2132 if (mode_set_ex(C, mode, true, op->reports)) {
2133 /* Store old mode so we know what to go back to. */
2134 ob->restore_mode = mode_prev;
2135 }
2136 }
2137 else {
2138 if (ob->restore_mode != OB_MODE_OBJECT) {
2139 mode_set_ex(C, eObjectMode(ob->restore_mode), true, op->reports);
2140 }
2141 else {
2142 mode_set_ex(C, OB_MODE_OBJECT, true, op->reports);
2143 }
2144 }
2145 }
2146 }
2147
2148 if (use_submode) {
2149 if (ob->type == OB_MESH) {
2150 if (ob->mode & OB_MODE_EDIT) {
2151 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "mesh_select_mode");
2152 if (RNA_property_is_set(op->ptr, prop)) {
2153 int mesh_select_mode = RNA_property_enum_get(op->ptr, prop);
2154 if (mesh_select_mode != 0) {
2155 EDBM_selectmode_set_multi(C, mesh_select_mode);
2156 }
2157 }
2158 }
2159 }
2160 }
2161
2163 if (wm) {
2166 }
2167 }
2168
2169 return OPERATOR_FINISHED;
2170}
2171
2173{
2174 PropertyRNA *prop;
2175
2176 /* identifiers */
2177 ot->name = "Set Object Mode";
2178 ot->description = "Sets the object interaction mode";
2179 ot->idname = "OBJECT_OT_mode_set";
2180
2181 /* API callbacks. */
2182 ot->exec = object_mode_set_exec;
2183 ot->poll = object_mode_set_poll;
2184
2185 /* flags */
2186 ot->flag = 0; /* no register/undo here, leave it to operators being called */
2187
2188 ot->prop = RNA_def_enum(
2189 ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
2192
2193 prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "");
2195}
2196
2198{
2200
2201 /* identifiers */
2202 ot->name = "Set Object Mode with Sub-mode";
2203 ot->idname = "OBJECT_OT_mode_set_with_submode";
2204
2205 /* properties */
2206 /* we could add other types - particle for eg. */
2207 PropertyRNA *prop;
2208 prop = RNA_def_enum_flag(
2209 ot->srna, "mesh_select_mode", rna_enum_mesh_select_mode_items, 0, "Mesh Mode", "");
2211}
2212
2214
2215/* -------------------------------------------------------------------- */
2218
2220{
2221 ListBase objects = {nullptr};
2222
2223 if (CTX_wm_space_outliner(C) != nullptr) {
2225 }
2226 else {
2227 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2228 BLI_addtail(&objects, BLI_genericNodeN(ob));
2229 }
2231 }
2232
2233 return objects;
2234}
2235
2237{
2238 if (CTX_wm_space_outliner(C) != nullptr) {
2240 }
2241 return ED_operator_objectmode(C);
2242}
2243
2245{
2246 Main *bmain = CTX_data_main(C);
2247 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_uid");
2248 const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
2249 const bool is_new = RNA_boolean_get(op->ptr, "is_new");
2250
2251 if (!RNA_property_is_set(op->ptr, prop)) {
2252 BKE_report(op->reports, RPT_ERROR, "No collection selected");
2253 return OPERATOR_CANCELLED;
2254 }
2255 Scene *src_scene = CTX_data_scene(C);
2256
2257 int collection_uid = RNA_property_int_get(op->ptr, prop);
2258 Scene *dest_scene = nullptr;
2259 Collection *collection = BKE_collection_from_session_uid(bmain, collection_uid, &dest_scene);
2260 if (collection == nullptr) {
2261 BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
2262 return OPERATOR_CANCELLED;
2263 }
2264
2265 if (!ID_IS_EDITABLE(collection) || ID_IS_OVERRIDE_LIBRARY(collection)) {
2266 BKE_report(
2267 op->reports, RPT_ERROR, "Cannot add objects to a library override or linked collection");
2268 return OPERATOR_CANCELLED;
2269 }
2270
2271 ListBase objects = selected_objects_get(C);
2272
2273 if (is_new) {
2274 char new_collection_name[MAX_ID_NAME - 2];
2275 RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
2276 collection = BKE_collection_add(bmain, collection, new_collection_name);
2277 }
2278
2279 Object *single_object = BLI_listbase_is_single(&objects) ?
2280 static_cast<Object *>(((LinkData *)objects.first)->data) :
2281 nullptr;
2282
2283 if ((single_object != nullptr) && is_link &&
2284 BKE_collection_has_object(collection, single_object))
2285 {
2286 BKE_reportf(op->reports,
2287 RPT_ERROR,
2288 "%s already in %s",
2289 single_object->id.name + 2,
2290 BKE_collection_ui_name_get(collection));
2291 BLI_freelistN(&objects);
2292 return OPERATOR_CANCELLED;
2293 }
2294
2295 LISTBASE_FOREACH (LinkData *, link, &objects) {
2296 Object *ob = static_cast<Object *>(link->data);
2297
2298 if (!is_link) {
2299 BKE_collection_object_move(bmain, src_scene, collection, nullptr, ob);
2300 }
2301 else {
2302 BKE_collection_object_add(bmain, collection, ob);
2303 }
2304 }
2305 BLI_freelistN(&objects);
2306
2307 if (is_link) {
2308 if (single_object != nullptr) {
2309 BKE_reportf(op->reports,
2310 RPT_INFO,
2311 "%s linked to %s",
2312 single_object->id.name + 2,
2313 BKE_collection_ui_name_get(collection));
2314 }
2315 else {
2317 op->reports, RPT_INFO, "Objects linked to %s", BKE_collection_ui_name_get(collection));
2318 }
2319 }
2320 else {
2321 if (single_object != nullptr) {
2322 BKE_reportf(op->reports,
2323 RPT_INFO,
2324 "%s moved to %s",
2325 single_object->id.name + 2,
2326 BKE_collection_ui_name_get(collection));
2327 }
2328 else {
2330 op->reports, RPT_INFO, "Objects moved to %s", BKE_collection_ui_name_get(collection));
2331 }
2332 }
2333
2336
2340
2341 if (src_scene != dest_scene) {
2343
2344 WM_event_add_notifier(C, NC_SCENE | ND_LAYER, dest_scene);
2347 }
2348
2349 return OPERATOR_FINISHED;
2350}
2351
2353 wmOperator *op,
2354 const wmEvent * /*event*/)
2355{
2356 ListBase objects = selected_objects_get(C);
2357 if (BLI_listbase_is_empty(&objects)) {
2358 BKE_report(op->reports, RPT_ERROR, "No objects selected");
2359 return OPERATOR_CANCELLED;
2360 }
2361 BLI_freelistN(&objects);
2362 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_uid");
2363 bool is_move = STREQ(op->type->idname, "OBJECT_OT_move_to_collection");
2364 if (!RNA_property_is_set(op->ptr, prop)) {
2366 is_move ? "OBJECT_MT_move_to_collection" : "OBJECT_MT_link_to_collection",
2368 return OPERATOR_FINISHED;
2369 }
2370
2371 if (!RNA_boolean_get(op->ptr, "is_new")) {
2372 return move_to_collection_exec(C, op);
2373 }
2374
2375 int collection_uid = RNA_property_int_get(op->ptr, prop);
2376 Collection *collection = BKE_collection_from_session_uid(CTX_data_main(C), collection_uid);
2377
2378 if (!collection) {
2379 BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
2380 return OPERATOR_CANCELLED;
2381 }
2382
2383 prop = RNA_struct_find_property(op->ptr, "new_collection_name");
2384 if (!RNA_property_is_set(op->ptr, prop)) {
2385 char name[MAX_ID_NAME - 2];
2386
2387 BKE_collection_new_name_get(collection, name);
2388
2389 RNA_property_string_set(op->ptr, prop, name);
2391 op,
2392 200,
2393 is_move ? IFACE_("Move to New Collection") :
2394 IFACE_("Link to New Collection"),
2395 IFACE_("Create"));
2396 }
2397 return move_to_collection_exec(C, op);
2398}
2399
2400static void move_to_collection_menu_draw(Menu *menu, Collection *collection, int icon)
2401{
2402 uiLayout &layout = *menu->layout;
2403 bool is_move = ELEM(StringRefNull(menu->type->idname),
2404 "OBJECT_MT_move_to_collection",
2405 "OBJECT_MT_move_to_collection_recursive");
2407 is_move ? "OBJECT_OT_move_to_collection" : "OBJECT_OT_link_to_collection", false);
2408
2410
2411 PointerRNA op_ptr = layout.op(
2412 ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "New Collection"), ICON_ADD);
2413 RNA_int_set(&op_ptr, "collection_uid", collection->id.session_uid);
2414 RNA_boolean_set(&op_ptr, "is_new", true);
2415 layout.separator();
2416
2417 op_ptr = layout.op(ot, BKE_collection_ui_name_get(collection), icon);
2418 RNA_int_set(&op_ptr, "collection_uid", collection->id.session_uid);
2419
2420 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
2421 collection = child->collection;
2422 if (BLI_listbase_is_empty(&collection->children)) {
2423 op_ptr = layout.op(
2425 RNA_int_set(&op_ptr, "collection_uid", collection->id.session_uid);
2426 continue;
2427 }
2428 const PointerRNA ptr = RNA_id_pointer_create(&collection->id);
2429 layout.context_ptr_set("collection", &ptr);
2430 layout.menu(is_move ? "OBJECT_MT_move_to_collection_recursive" :
2431 "OBJECT_MT_link_to_collection_recursive",
2432 BKE_collection_ui_name_get(collection),
2433 UI_icon_color_from_collection(collection));
2434 }
2435}
2436
2438{
2439 uiLayout &layout = *menu->layout;
2440 const PointerRNA *ptr = layout.context_ptr_get("collection", &RNA_Collection);
2441 Collection *collection = ptr ? ptr->data_as<Collection>() : nullptr;
2442 if (!collection) {
2443 return;
2444 }
2445 move_to_collection_menu_draw(menu, collection, UI_icon_color_from_collection(collection));
2446}
2447
2449{
2450 uiLayout &layout = *menu->layout;
2451 Scene *scene = CTX_data_scene(C);
2454 PointerRNA op_ptr = layout.op("WM_OT_search_single_menu",
2456 ICON_VIEWZOOM);
2457 RNA_string_set(&op_ptr, "menu_idname", menu->type->idname);
2458 layout.separator();
2459 }
2460 move_to_collection_menu_draw(menu, scene->master_collection, ICON_SCENE_DATA);
2461}
2462
2464{
2465 /* Add recursive sub-menu type, to avoid each sub-menu from showing the main menu shortcut. */
2466 MenuType *mt = MEM_callocN<MenuType>("OBJECT_MT_move_to_collection_recursive");
2467 STRNCPY_UTF8(mt->idname, "OBJECT_MT_move_to_collection_recursive");
2468 STRNCPY_UTF8(mt->label, N_("Move to Collection Recursive"));
2472 WM_menutype_add(mt);
2473
2474 mt = MEM_callocN<MenuType>("OBJECT_MT_move_to_collection");
2475 STRNCPY_UTF8(mt->idname, "OBJECT_MT_move_to_collection");
2476 STRNCPY_UTF8(mt->label, N_("Move to Collection"));
2480 WM_menutype_add(mt);
2481}
2482
2484{
2485 /* Add recursive sub-menu type, to avoid each sub-menu from showing the main menu shortcut. */
2486 MenuType *mt = MEM_callocN<MenuType>("OBJECT_MT_link_to_collection_recursive");
2487 STRNCPY_UTF8(mt->idname, "OBJECT_MT_link_to_collection_recursive");
2488 STRNCPY_UTF8(mt->label, N_("Link to Collection Recursive"));
2492 WM_menutype_add(mt);
2493
2494 mt = MEM_callocN<MenuType>("OBJECT_MT_link_to_collection");
2495 STRNCPY_UTF8(mt->idname, "OBJECT_MT_link_to_collection");
2496 STRNCPY_UTF8(mt->label, N_("Link to Collection"));
2500 WM_menutype_add(mt);
2501}
2502
2504{
2505 PropertyRNA *prop;
2506
2507 /* identifiers */
2508 ot->name = "Move to Collection";
2509 ot->description = "Move objects to a collection";
2510 ot->idname = "OBJECT_OT_move_to_collection";
2511
2512 /* API callbacks. */
2514 ot->invoke = move_to_collection_invoke;
2516
2517 /* flags */
2518 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2519
2520 prop = RNA_def_int(ot->srna,
2521 "collection_uid",
2524 INT_MAX,
2525 "Collection UID",
2526 "Session UID of the collection to move to",
2527 0,
2528 INT_MAX);
2530 prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
2532 prop = RNA_def_string(ot->srna,
2533 "new_collection_name",
2534 nullptr,
2535 MAX_ID_NAME - 2,
2536 "Name",
2537 "Name of the newly added collection");
2539 ot->prop = prop;
2540}
2541
2543{
2544 PropertyRNA *prop;
2545
2546 /* identifiers */
2547 ot->name = "Link to Collection";
2548 ot->description = "Link objects to a collection";
2549 ot->idname = "OBJECT_OT_link_to_collection";
2550
2551 /* API callbacks. */
2553 ot->invoke = move_to_collection_invoke;
2555
2556 /* flags */
2557 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2558
2559 prop = RNA_def_int(ot->srna,
2560 "collection_uid",
2563 INT_MAX,
2564 "Collection UID",
2565 "Session UID of the collection to link to",
2566 0,
2567 INT_MAX);
2569 prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Link objects to a new collection");
2571 prop = RNA_def_string(ot->srna,
2572 "new_collection_name",
2573 nullptr,
2574 MAX_ID_NAME - 2,
2575 "Name",
2576 "Name of the newly added collection");
2578 ot->prop = prop;
2579}
2580
2582
2583} // namespace blender::ed::object
struct bMotionPath * animviz_verify_motionpaths(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan)
void animviz_free_motionpath(struct bMotionPath *mpath)
void BKE_pose_channels_clear_with_null_bone(bPose *pose, bool do_id_user)
const char * BKE_collection_ui_name_get(Collection *collection)
Collection * BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
bool BKE_collection_has_object(Collection *collection, const Object *ob)
void BKE_collection_object_move(Main *bmain, Scene *scene, Collection *collection_dst, Collection *collection_src, Object *ob)
Collection * BKE_collection_from_session_uid(Scene *scene, uint64_t session_uid)
void BKE_collection_new_name_get(Collection *collection_parent, char r_name[256])
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
SpaceOutliner * CTX_wm_space_outliner(const bContext *C)
#define CTX_DATA_BEGIN(C, Type, instance, member)
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
bool CTX_data_selected_editable_objects(const bContext *C, blender::Vector< PointerRNA > *list)
wmWindowManager * CTX_wm_manager(const bContext *C)
#define CTX_DATA_END
wmMsgBus * CTX_wm_message_bus(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_curve_smooth_flag_set(Curve *cu, bool use_smooth)
Definition curve.cc:5407
void BKE_editlattice_load(struct Object *obedit)
void BKE_editlattice_make(struct Object *obedit)
void BKE_editlattice_free(struct Object *ob)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
Definition editmesh.cc:95
struct PartDeflect * BKE_partdeflect_new(int type)
Definition effect.cc:71
@ G_TRANSFORM_OBJ
@ G_TRANSFORM_EDIT
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:747
#define IDP_float_set(prop, value)
#define IDP_double_set(prop, value)
#define FOREACH_BASE_IN_MODE_END
Definition BKE_layer.hh:367
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
#define FOREACH_SELECTED_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition BKE_layer.hh:298
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_mode_params(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, const ObjectsInModeParams *params)
void BKE_layer_collection_local_sync(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
LayerCollection * BKE_layer_collection_from_index(ViewLayer *view_layer, int index)
#define FOREACH_OBJECT_END
Definition BKE_layer.hh:432
#define FOREACH_BASE_IN_MODE_BEGIN(_scene, _view_layer, _v3d, _object_type, _object_mode, _instance)
Definition BKE_layer.hh:349
void BKE_layer_collection_isolate_local(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, LayerCollection *lc, bool extend)
#define FOREACH_OBJECT_BEGIN(scene, view_layer, _instance)
Definition BKE_layer.hh:422
bool BKE_layer_collection_has_selected_objects(const Scene *scene, ViewLayer *view_layer, LayerCollection *lc)
blender::Vector< Object * > BKE_view_layer_array_selected_objects_params(ViewLayer *view_layer, const View3D *v3d, const ObjectsInViewLayerParams *params)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
void BKE_layer_collection_isolate_global(Scene *scene, ViewLayer *view_layer, LayerCollection *lc, bool extend)
void BKE_view_layer_need_resync_tag(ViewLayer *view_layer)
#define FOREACH_SELECTED_OBJECT_END
Definition BKE_layer.hh:310
int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection *lc)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
Object * BKE_view_layer_edit_object_get(const ViewLayer *view_layer)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2523
void id_us_plus(ID *id)
Definition lib_id.cc:358
const char * BKE_id_name(const ID &id)
General operations, lookup, etc. for materials.
void BKE_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode)
@ BKE_MESH_BATCH_DIRTY_ALL
Definition BKE_mesh.h:38
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const Object *ob)
char * BKE_object_data_editmode_flush_ptr_get(ID *id)
bool BKE_object_obdata_is_libdata(const Object *ob)
void BKE_particlesystem_reset_all(struct Object *object)
void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis)
#define PTCACHE_TYPE_PARTICLES
#define PTCACHE_RESET_OUTDATED
int BKE_ptcache_object_reset(struct Scene *scene, struct Object *ob, int mode)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void BKE_scene_object_base_flag_sync_from_base(Base *base)
Definition scene.cc:2858
#define BLI_assert(a)
Definition BLI_assert.h:46
LinkData * BLI_genericNodeN(void *data)
Definition listbase.cc:922
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void void BLI_INLINE bool BLI_listbase_is_single(const ListBase *lb)
#define DEG2RADF(_deg)
#define FILE_MAX
void BLI_path_slash_native(char *path) ATTR_NONNULL(1)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
#define STRNCPY_UTF8(dst, src)
unsigned int uint
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define LIKELY(x)
#define TIP_(msgid)
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_DEFAULT_BPYRNA
#define DATA_(msgid)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:306
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1054
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1077
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1104
#define MAX_ID_NAME
Definition DNA_ID.h:373
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
@ ID_NT
@ ID_CU_LEGACY
@ ID_ME
@ ID_OB
@ IDP_DOUBLE
@ IDP_FLOAT
@ MOTIONPATH_BAKE_HAS_PATHS
@ MOTIONPATH_TYPE_RANGE
@ MOTIONPATH_RANGE_SCENE
@ ANIMVIZ_RECALC_PATHS
@ POSE_SELECTED
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_TIPSEL
@ ASSET_LIBRARY_ESSENTIALS
Object groups, one object can be in many groups at once.
@ COLLECTION_HIDE_VIEWPORT
@ LAYER_COLLECTION_EXCLUDE
@ BASE_HIDDEN
@ BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT
@ LAYER_COLLECTION_HIDE_VIEWPORT
@ LAYER_COLLECTION_HAS_OBJECTS
#define MESH_MAX_VERTS
@ eModifierFlag_PinLast
@ NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR
@ NODES_MODIFIER_HIDE_MANAGE_PANEL
@ eModifierType_Surface
@ eModifierType_Hook
@ eModifierType_Nodes
@ NTREE_GEOMETRY
#define OB_MODE_ALL_PAINT
#define OB_MODE_ALL_PAINT_GPENCIL
eObjectMode
@ OB_MODE_EDIT
@ OB_MODE_SCULPT
@ OB_MODE_POSE
@ OB_MODE_OBJECT
#define OB_MODE_ALL_SCULPT
@ PFIELD_SHAPE_SURFACE
Object is a sort of wrapper for general info.
@ PARVERT1
@ PARVERT3
@ OB_HIDE_VIEWPORT
@ OB_PLAINAXES
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES_LEGACY
@ OB_CURVES
#define OB_TYPE_SUPPORT_EDITMODE(_type)
@ PTCACHE_OUTDATED
#define BASE_SELECTED(v3d, base)
eSpace_Type
@ SPACE_PROPERTIES
@ SPACE_EMPTY
@ SPACE_VIEW3D
@ V3D_LOCAL_COLLECTIONS
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
eAnimvizCalcRange
@ ANIMVIZ_CALC_RANGE_FULL
@ ANIMVIZ_CALC_RANGE_CURRENT_FRAME
@ ANIMVIZ_CALC_RANGE_CHANGED
void ED_mball_editmball_free(Object *obedit)
Definition mball_edit.cc:62
void ED_mball_editmball_load(Object *obedit)
Definition mball_edit.cc:87
void ED_mball_editmball_make(Object *obedit)
Definition mball_edit.cc:70
void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
void EDBM_mesh_make(Object *ob, int select_mode, bool add_key_index)
void ED_mesh_mirror_topo_table_end(Object *ob)
Definition meshtools.cc:258
void EDBM_mesh_free_data(BMEditMesh *em)
bool EDBM_selectmode_set_multi(bContext *C, short selectmode)
void ED_mesh_mirror_spatial_table_end(Object *ob)
void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects)
bool ED_outliner_collections_editor_poll(bContext *C)
bool ED_operator_objectmode(bContext *C)
bool ED_operator_view3d_active(bContext *C)
bool ED_operator_object_active_editable(bContext *C)
bool ED_operator_object_active_editable_ex(bContext *C, const Object *ob)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
Definition MOD_nodes.cc:449
@ PROP_FLOAT
Definition RNA_types.hh:164
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
@ PROP_HIDDEN
Definition RNA_types.hh:338
@ PROP_ANGLE
Definition RNA_types.hh:252
#define C
Definition RandGen.cpp:29
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
uiPopupMenu * UI_popup_menu_begin(bContext *C, const char *title, int icon) ATTR_NONNULL()
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
int UI_icon_color_from_collection(const Collection *collection)
#define UI_ITEM_NONE
#define NS_EDITMODE_MESH
Definition WM_types.hh:562
#define NS_EDITMODE_TEXT
Definition WM_types.hh:565
#define NC_GEOM
Definition WM_types.hh:393
@ KM_SHIFT
Definition WM_types.hh:278
#define ND_DRAW
Definition WM_types.hh:461
#define ND_OB_ACTIVE
Definition WM_types.hh:440
#define NS_EDITMODE_POINTCLOUD
Definition WM_types.hh:573
#define ND_DATA
Definition WM_types.hh:509
#define NS_EDITMODE_CURVES
Definition WM_types.hh:571
#define ND_MODE
Definition WM_types.hh:445
#define ND_OB_SELECT
Definition WM_types.hh:442
#define NC_SCENE
Definition WM_types.hh:378
#define NS_EDITMODE_ARMATURE
Definition WM_types.hh:568
#define ND_OB_VISIBLE
Definition WM_types.hh:443
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_LAYER_CONTENT
Definition WM_types.hh:453
#define ND_MODIFIER
Definition WM_types.hh:462
#define ND_POSE
Definition WM_types.hh:458
#define NS_MODE_OBJECT
Definition WM_types.hh:560
#define NA_REMOVED
Definition WM_types.hh:587
#define NS_EDITMODE_MBALL
Definition WM_types.hh:566
#define NS_EDITMODE_GREASE_PENCIL
Definition WM_types.hh:572
#define ND_TRANSFORM
Definition WM_types.hh:456
#define NS_EDITMODE_LATTICE
Definition WM_types.hh:567
#define ND_LAYER
Definition WM_types.hh:450
#define ND_DRAW_ANIMVIZ
Definition WM_types.hh:473
#define NC_OBJECT
Definition WM_types.hh:379
#define NS_EDITMODE_CURVE
Definition WM_types.hh:563
Depsgraph * animviz_depsgraph_build(Main *bmain, Scene *scene, ViewLayer *view_layer, blender::Span< MPathTarget * > targets)
void animviz_free_motionpath_targets(blender::Vector< MPathTarget * > &targets)
void animviz_motionpath_compute_range(Object *ob, Scene *scene)
void animviz_calc_motionpaths(Depsgraph *depsgraph, Main *bmain, Scene *scene, blender::MutableSpan< MPathTarget * > targets, eAnimvizCalcRange range, bool restore)
void animviz_build_motionpath_targets(Object *ob, blender::Vector< MPathTarget * > &r_targets)
void ED_armature_edit_free(bArmature *arm)
void ED_armature_from_edit(Main *bmain, bArmature *arm)
void ED_armature_to_edit(bArmature *arm)
BMesh const char void * data
BPy_StructRNA * depsgraph
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr bool endswith(StringRef suffix) const
constexpr const char * c_str() const
void append(const T &value)
bool is_empty() const
float4 load_data(StoredFloat4 data)
void ED_curve_editnurb_make(Object *obedit)
void ED_curve_editnurb_free(Object *obedit)
void ED_curve_editnurb_load(Main *bmain, Object *obedit)
void ED_curve_editfont_make(Object *obedit)
Definition editfont.cc:2236
void ED_curve_editfont_load(Object *obedit)
Definition editfont.cc:2275
void ED_curve_editfont_free(Object *obedit)
Definition editfont.cc:2307
#define GS(x)
uint col
#define input
#define select(A, B, C)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
#define G(x, y, z)
AssetLibraryReference all_library_reference()
void mesh_sharp_edges_set_from_angle(Mesh &mesh, float angle, bool keep_sharp_edges=false)
void mesh_smooth_set(Mesh &mesh, bool use_smooth, bool keep_sharp_edges=false)
void storage_fetch_blocking(const AssetLibraryReference &library_reference, const bContext &C)
const asset_system::AssetRepresentation * find_asset_from_weak_ref(const bContext &C, const AssetWeakReference &weak_ref, ReportList *reports)
ID * asset_local_id_ensure_imported(Main &bmain, const asset_system::AssetRepresentation &asset, const std::optional< eAssetImportMethod > import_method=std::nullopt)
bool ensure_selection_domain(ToolSettings *ts, Object *object)
void OBJECT_OT_paths_update_visible(wmOperatorType *ot)
void OBJECT_OT_shade_smooth(wmOperatorType *ot)
void motion_paths_recalc(bContext *C, Scene *scene, eObjectPathCalcRange range, ListBase *ld_objects)
ModifierData * modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
static bool is_valid_smooth_by_angle_group(const bNodeTree &ntree)
static wmOperatorStatus object_update_paths_exec(bContext *C, wmOperator *op)
@ OBJECT_PATH_CALC_RANGE_CURRENT_FRAME
Definition ED_object.hh:373
void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
bool editmode_exit_multi(bContext *C, int flag)
void OBJECT_OT_mode_set(wmOperatorType *ot)
static bool editmode_load_free_ex(Main *bmain, Object *obedit, const bool load_data, const bool free_data)
bool editmode_enter(bContext *C, int flag)
void motion_paths_recalc_selected(bContext *C, Scene *scene, eObjectPathCalcRange range)
void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
static bool object_mode_set_poll(bContext *C)
static void flush_pose_selection_to_bone(Object &ob)
static bool object_mode_set_ok_or_report(ReportList *reports)
int object_in_mode_to_index(const Scene *scene, ViewLayer *view_layer, eObjectMode mode, const Object *ob)
static wmOperatorStatus object_calculate_paths_exec(bContext *C, wmOperator *op)
void OBJECT_OT_shade_flat(wmOperatorType *ot)
void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
void OBJECT_OT_shade_auto_smooth(wmOperatorType *ot)
static void move_to_collection_menu_draw(Menu *menu, Collection *collection, int icon)
static wmOperatorStatus editmode_toggle_exec(bContext *C, wmOperator *op)
void motion_paths_recalc_visible(bContext *C, Scene *scene, eObjectPathCalcRange range)
static void object_clear_mpath(Object *ob)
void motion_paths_clear(bContext *C, bool only_selected)
void OBJECT_OT_shade_smooth_by_angle(wmOperatorType *ot)
static wmOperatorStatus object_clear_paths_exec(bContext *C, wmOperator *op)
void OBJECT_OT_move_to_collection(wmOperatorType *ot)
static void move_to_collection_recursive_menu_draw(const bContext *, Menu *menu)
bool editmode_free_ex(Main *bmain, Object *obedit)
static wmOperatorStatus move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *)
bool mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports)
static wmOperatorStatus object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *)
void OBJECT_OT_hide_view_set(wmOperatorType *ot)
static wmOperatorStatus object_update_all_paths_exec(bContext *C, wmOperator *)
static wmOperatorStatus object_hide_collection_exec(bContext *C, wmOperator *op)
void base_select(Base *base, eObjectSelect_Mode mode)
static wmOperatorStatus object_hide_view_set_exec(bContext *C, wmOperator *op)
static wmOperatorStatus move_to_collection_exec(bContext *C, wmOperator *op)
Object * context_object(const bContext *C)
void OBJECT_OT_mode_set_with_submode(wmOperatorType *ot)
void OBJECT_OT_hide_collection(wmOperatorType *ot)
static bool shade_poll(bContext *C)
void OBJECT_OT_paths_update(wmOperatorType *ot)
void link_to_collection_menu_register()
void OBJECT_OT_paths_calculate(wmOperatorType *ot)
static wmOperatorStatus object_hide_view_clear_exec(bContext *C, wmOperator *op)
void collection_hide_menu_draw(const bContext *C, uiLayout *layout)
static eAnimvizCalcRange object_path_convert_range(eObjectPathCalcRange range)
bool mode_compat_test(const Object *ob, eObjectMode mode)
bool editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
static ListBase selected_objects_get(bContext *C)
Object * context_active_object(const bContext *C)
static wmOperatorStatus shade_auto_smooth_exec(bContext *C, wmOperator *op)
void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
static const EnumPropertyItem * object_mode_set_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
bool editmode_exit(bContext *C, int flag)
Object * object_in_mode_from_index(const Scene *scene, ViewLayer *view_layer, eObjectMode mode, int index)
static bool has_object_motion_paths(Object *ob)
void OBJECT_OT_link_to_collection(wmOperatorType *ot)
static bool move_to_collection_poll(bContext *C)
static wmOperatorStatus object_mode_set_exec(bContext *C, wmOperator *op)
bool mode_compat_set(bContext *C, Object *ob, eObjectMode mode, ReportList *reports)
void move_to_collection_menu_register()
bool editmode_exit_multi_ex(Main *bmain, Scene *scene, ViewLayer *view_layer, int flag)
static bool object_update_all_paths_poll(bContext *)
void check_force_modifiers(Main *bmain, Scene *scene, Object *object)
static bool object_update_paths_poll(bContext *C)
static bool editmode_toggle_poll(bContext *C)
static void shade_auto_smooth_ui(bContext *, wmOperator *op)
static bool mesh_needs_keyindex(Main *bmain, const Mesh *mesh)
static bool has_pose_motion_paths(Object *ob)
static bool is_smooth_by_angle_modifier(const ModifierData &md)
static wmOperatorStatus shade_smooth_exec(bContext *C, wmOperator *op)
static void flush_bone_selection_to_pose(Object &ob)
bool editmode_load(Main *bmain, Object *obedit)
static wmOperatorStatus object_hide_collection_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static std::string object_clear_paths_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
blender::Vector< Object * > objects_in_mode_or_selected(bContext *C, bool(*filter_fn)(const Object *ob, void *user_data), void *filter_user_data)
bool editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag)
static CLG_LogRef LOG
void OBJECT_OT_paths_clear(wmOperatorType *ot)
static bool object_hide_poll(bContext *C)
static wmOperatorStatus posemode_exec(bContext *C, wmOperator *op)
static wmOperatorStatus forcefield_toggle_exec(bContext *C, wmOperator *)
bool modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
static void free_data(ModifierData *md)
#define COLLECTION_INVALID_INDEX
bool ED_object_posemode_enter_ex(Main *bmain, Object *ob)
Definition pose_edit.cc:77
bool ED_object_posemode_enter(bContext *C, Object *ob)
Definition pose_edit.cc:98
bool ED_object_posemode_exit_ex(Main *bmain, Object *ob)
Definition pose_edit.cc:113
bool ED_object_posemode_exit(bContext *C, Object *ob)
Definition pose_edit.cc:126
const char * name
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_int_get(PointerRNA *ptr, const char *name)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_id_pointer_create(ID *id)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
const EnumPropertyItem rna_enum_motionpath_display_type_items[]
const EnumPropertyItem rna_enum_motionpath_range_items[]
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
void RNA_def_property_float_default(PropertyRNA *prop, float value)
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_range(PropertyRNA *prop, double min, double max)
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
PropertyRNA * RNA_def_enum_flag(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_enum_items_add_value(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item, int value)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_object_mode_items[]
Definition rna_object.cc:33
const EnumPropertyItem rna_enum_mesh_select_mode_items[]
Definition rna_scene.cc:124
const char * relative_asset_identifier
struct Object * object
struct EditFont * editfont
EditNurb * editnurb
char type
Definition DNA_ID.h:156
Definition DNA_ID.h:414
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
unsigned int session_uid
Definition DNA_ID.h:462
struct LibraryWeakReference * library_weak_reference
Definition DNA_ID.h:526
struct EditLatt * editlatt
ListBase layer_collections
unsigned short local_collections_bits
char filepath[1024]
Definition DNA_ID.h:552
void * first
bool is_memfile_undo_written
Definition BKE_main.hh:208
ListBase objects
Definition BKE_main.hh:280
MenuTypeFlag flag
char label[BKE_ST_MAXNAME]
char idname[BKE_ST_MAXNAME]
void(* draw)(const bContext *C, Menu *menu)
char translation_context[BKE_ST_MAXNAME]
uiLayout * layout
MenuType * type
ListBase * editelems
char needs_flush_to_id
struct bNodeTree * node_group
struct NodesModifierSettings settings
struct IDProperty * properties
struct bPose * pose
ListBase modifiers
struct PartDeflect * pd
char empty_drawtype
short visibility_flag
bMotionPath * mpath
bAnimVizSettings avs
void * data
Definition RNA_types.hh:53
struct Collection * master_collection
struct ToolSettings * toolsettings
ListBase spacedata
unsigned short local_collections_uid
ListBase layer_collections
ListBase * edbo
ListBase chanbase
bAnimVizSettings avs
void use_property_decorate_set(bool is_sep)
blender::wm::OpCallContext operator_context() const
void operator_context_set(blender::wm::OpCallContext opcontext)
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void context_ptr_set(blender::StringRef name, const PointerRNA *ptr)
uiLayout & row(bool align)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
void menu(MenuType *mt, std::optional< blender::StringRef > name, int icon)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
const PointerRNA * context_ptr_get(const blender::StringRef name, const StructRNA *type) const
wmEventModifierFlag modifier
Definition WM_types.hh:774
const char * name
Definition WM_types.hh:1033
const char * idname
Definition WM_types.hh:1035
const char * translation_context
Definition WM_types.hh:1037
struct ReportList * reports
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
i
Definition text_draw.cc:230
#define N_(msgid)
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_menu_name_call(bContext *C, const char *menu_name, blender::wm::OpCallContext context)
void WM_autosave_write(wmWindowManager *wm, Main *bmain)
Definition wm_files.cc:2351
bool WM_autosave_is_scheduled(wmWindowManager *wm)
Definition wm_files.cc:2346
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
bool WM_menutype_add(MenuType *mt)
#define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
wmOperatorStatus WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default, std::optional< std::string > message)
void WM_toolsystem_update_from_context_view3d(bContext *C)
uint8_t flag
Definition wm_window.cc:145