Blender V4.5
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 "MEM_guardedalloc.h"
16
17#include "BLI_listbase.h"
18#include "BLI_math_rotation.h"
19#include "BLI_string.h"
20#include "BLI_utildefines.h"
21
22#include "BLT_translation.hh"
23
24#include "DNA_armature_types.h"
25#include "DNA_asset_types.h"
27#include "DNA_curve_types.h"
28#include "DNA_lattice_types.h"
29#include "DNA_material_types.h"
30#include "DNA_mesh_types.h"
31#include "DNA_meta_types.h"
33#include "DNA_object_types.h"
34#include "DNA_scene_types.h"
35
37#include "BKE_armature.hh"
38#include "BKE_collection.hh"
39#include "BKE_constraint.h"
40#include "BKE_context.hh"
41#include "BKE_curve.hh"
42#include "BKE_editlattice.h"
43#include "BKE_editmesh.hh"
44#include "BKE_effect.h"
45#include "BKE_global.hh"
46#include "BKE_idprop.hh"
47#include "BKE_image.hh"
48#include "BKE_lattice.hh"
49#include "BKE_layer.hh"
50#include "BKE_lib_id.hh"
51#include "BKE_library.hh"
52#include "BKE_main.hh"
53#include "BKE_material.hh"
54#include "BKE_mball.hh"
55#include "BKE_mesh.hh"
56#include "BKE_modifier.hh"
57#include "BKE_node_runtime.hh"
58#include "BKE_object.hh"
59#include "BKE_paint.hh"
60#include "BKE_particle.h"
61#include "BKE_pointcache.h"
62#include "BKE_report.hh"
63#include "BKE_scene.hh"
64#include "BKE_softbody.h"
65#include "BKE_workspace.hh"
66
67#include "DEG_depsgraph.hh"
69
70#include "ED_anim_api.hh"
71#include "ED_armature.hh"
72#include "ED_asset.hh"
74#include "ED_curve.hh"
75#include "ED_gpencil_legacy.hh"
76#include "ED_grease_pencil.hh"
77#include "ED_image.hh"
79#include "ED_lattice.hh"
80#include "ED_mball.hh"
81#include "ED_mesh.hh"
82#include "ED_object.hh"
83#include "ED_outliner.hh"
84#include "ED_screen.hh"
85#include "ED_undo.hh"
86
87#include "RNA_access.hh"
88#include "RNA_define.hh"
89#include "RNA_enum_types.hh"
90#include "RNA_types.hh"
91
92#include "UI_interface_icons.hh"
93
94#include "CLG_log.h"
95
96/* For menu/popup icons etc. */
97
98#include "UI_interface.hh"
99#include "UI_resources.hh"
100
101#include "WM_api.hh"
102#include "WM_message.hh"
103#include "WM_toolsystem.hh"
104#include "WM_types.hh"
105
106#include "MOD_nodes.hh"
107
108#include "object_intern.hh" /* own include */
109
110namespace blender::ed::object {
111
112static CLG_LogRef LOG = {"ed.object.edit"};
113
114/* prototypes */
115struct MoveToCollectionData;
116static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu);
118
119/* -------------------------------------------------------------------- */
122
124{
125 /* NOTE(@ideasman42): toggling modes while transforming should not be allowed by the key-map,
126 * so users should not be able do this. Python scripts can though,
127 * so check here to report an error instead of crashing.
128 *
129 * This is *not* a comprehensive check, since users might be trying to change modes
130 * while in the middle of *any* modal operator (painting or dragging a UI slider... etc).
131 *
132 * This check could be removed if it causes any problems since the error it prevents
133 * is quite obscure. See: #137380. */
134
135 if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
136 BKE_reportf(reports, RPT_ERROR, "Unable to change object mode while transforming");
137 return false;
138 }
139
140 return true;
141}
142
144{
145 return static_cast<Object *>(CTX_data_pointer_get_type(C, "object", &RNA_Object).data);
146}
147
149{
150 Object *ob = nullptr;
151 if (C) {
152 ob = context_object(C);
153 if (!ob) {
155 }
156 }
157 return ob;
158}
159
161 bool (*filter_fn)(const Object *ob, void *user_data),
162 void *filter_user_data)
163{
164 ScrArea *area = CTX_wm_area(C);
165 const Scene *scene = CTX_data_scene(C);
166 ViewLayer *view_layer = CTX_data_view_layer(C);
167 BKE_view_layer_synced_ensure(scene, view_layer);
168 Object *ob_active = BKE_view_layer_active_object_get(view_layer);
169 ID *id_pin = nullptr;
170 const bool use_objects_in_mode = (ob_active != nullptr) &&
171 (ob_active->mode & (OB_MODE_EDIT | OB_MODE_POSE));
172 const eSpace_Type space_type = area ? eSpace_Type(area->spacetype) : SPACE_EMPTY;
173
174 Object *ob = nullptr;
175 bool use_ob = true;
176
177 if (space_type == SPACE_PROPERTIES) {
178 SpaceProperties *sbuts = static_cast<SpaceProperties *>(area->spacedata.first);
179 id_pin = sbuts->pinid;
180 }
181
182 if (id_pin && (GS(id_pin->name) == ID_OB)) {
183 /* Pinned data takes priority, in this case ignore selection & other objects in the mode. */
184 ob = (Object *)id_pin;
185 }
186 else if ((space_type == SPACE_PROPERTIES) && (use_objects_in_mode == false)) {
187 /* When using the space-properties, we don't want to use the entire selection
188 * as the current active object may not be selected.
189 *
190 * This is not the case when we're in a mode that supports multi-mode editing,
191 * since the active object and all other objects in the mode will be included
192 * irrespective of selection. */
193 ob = ob_active;
194 }
195 else if (ob_active && (ob_active->mode &
197 {
198 /* When painting, limit to active. */
199 ob = ob_active;
200 }
201 else {
202 /* Otherwise use full selection. */
203 use_ob = false;
204 }
205
206 if (use_ob) {
207 if ((ob != nullptr) && !filter_fn(ob, filter_user_data)) {
208 ob = nullptr;
209 }
210 return ob ? Vector<Object *>({ob}) : Vector<Object *>();
211 }
212 const View3D *v3d = (space_type == SPACE_VIEW3D) ?
213 static_cast<const View3D *>(area->spacedata.first) :
214 nullptr;
215
216 /* When in a mode that supports multiple active objects, use "objects in mode"
217 * instead of the object's selection. */
218 if (use_objects_in_mode) {
220 params.object_mode = ob_active->mode;
221 params.no_dup_data = true;
222 params.filter_fn = filter_fn;
223 params.filter_userdata = filter_user_data;
224 return BKE_view_layer_array_from_objects_in_mode_params(scene, view_layer, v3d, &params);
225 }
226
228 params.no_dup_data = true;
229 params.filter_fn = filter_fn;
230 params.filter_userdata = filter_user_data;
232}
233
235
236/* -------------------------------------------------------------------- */
239
241 ViewLayer *view_layer,
242 const eObjectMode mode,
243 const Object *ob)
244{
245 BLI_assert(ob != nullptr);
246 /* NOTE: the `v3d` is always nullptr because the purpose of this function is to return
247 * a reusable index, using the `v3d` only increases the chance the index may become
248 * invalid-parameters. */
249 int index = -1;
250 int i = 0;
251 FOREACH_BASE_IN_MODE_BEGIN (scene, view_layer, nullptr, -1, mode, base_iter) {
252 if (base_iter->object == ob) {
253 index = i;
254 break;
255 }
256 i++;
257 }
259 return index;
260}
261
263 ViewLayer *view_layer,
264 const eObjectMode mode,
265 int index)
266{
267 BLI_assert(index >= 0);
268 Object *ob = nullptr;
269 int i = 0;
270 FOREACH_BASE_IN_MODE_BEGIN (scene, view_layer, nullptr, -1, mode, base_iter) {
271 if (index == i) {
272 ob = base_iter->object;
273 break;
274 }
275 i++;
276 }
278 return ob;
279}
280
282
283/* -------------------------------------------------------------------- */
286
288{
289 if (CTX_wm_space_outliner(C) != nullptr) {
291 }
293}
294
296{
297 Scene *scene = CTX_data_scene(C);
298 ViewLayer *view_layer = CTX_data_view_layer(C);
299 const bool select = RNA_boolean_get(op->ptr, "select");
300 bool changed = false;
301
302 BKE_view_layer_synced_ensure(scene, view_layer);
304 if (base->flag & BASE_HIDDEN) {
305 base->flag &= ~BASE_HIDDEN;
306 changed = true;
307
308 if (select) {
309 /* We cannot call `base_select` because
310 * base is not selectable while it is hidden. */
311 base->flag |= BASE_SELECTED;
313 }
314 }
315 }
316
317 if (!changed) {
318 return OPERATOR_CANCELLED;
319 }
320
325
326 return OPERATOR_FINISHED;
327}
328
330{
331 /* identifiers */
332 ot->name = "Show Hidden Objects";
333 ot->description = "Reveal temporarily hidden objects";
334 ot->idname = "OBJECT_OT_hide_view_clear";
335
336 /* API callbacks. */
338 ot->poll = object_hide_poll;
339
340 /* flags */
342
343 RNA_def_boolean(ot->srna, "select", true, "Select", "Select revealed objects");
344}
345
347{
348 Scene *scene = CTX_data_scene(C);
349 ViewLayer *view_layer = CTX_data_view_layer(C);
350 const bool unselected = RNA_boolean_get(op->ptr, "unselected");
351 bool changed = false;
352 const bool confirm = op->flag & OP_IS_INVOKE;
353 uint hide_count = 0;
354
355 /* Hide selected or unselected objects. */
356 BKE_view_layer_synced_ensure(scene, view_layer);
359 continue;
360 }
361
362 if (!unselected) {
363 if (base->flag & BASE_SELECTED) {
365 base->flag |= BASE_HIDDEN;
366 hide_count++;
367 changed = true;
368 }
369 }
370 else {
371 if (!(base->flag & BASE_SELECTED)) {
373 base->flag |= BASE_HIDDEN;
374 hide_count++;
375 changed = true;
376 }
377 }
378 }
379 if (!changed) {
380 return OPERATOR_CANCELLED;
381 }
382
383 if (hide_count > 0 && confirm) {
384 BKE_reportf(op->reports, RPT_INFO, "%u object(s) hidden", (hide_count));
385 }
386
391
392 return OPERATOR_FINISHED;
393}
394
396{
397 /* identifiers */
398 ot->name = "Hide Objects";
399 ot->description = "Temporarily hide objects from the viewport";
400 ot->idname = "OBJECT_OT_hide_view_set";
401
402 /* API callbacks. */
404 ot->poll = object_hide_poll;
405
406 /* flags */
408
409 PropertyRNA *prop;
410 prop = RNA_def_boolean(
411 ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected objects");
413}
414
416{
417 View3D *v3d = CTX_wm_view3d(C);
418
419 int index = RNA_int_get(op->ptr, "collection_index");
420 const bool extend = RNA_boolean_get(op->ptr, "extend");
421 const bool toggle = RNA_boolean_get(op->ptr, "toggle");
422
423 Scene *scene = CTX_data_scene(C);
424 ViewLayer *view_layer = CTX_data_view_layer(C);
425 LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
426
427 if (!lc) {
428 return OPERATOR_CANCELLED;
429 }
430
432
433 if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
435 return OPERATOR_CANCELLED;
436 }
437 if (toggle) {
439 BKE_layer_collection_local_sync(scene, view_layer, v3d);
440 }
441 else {
442 BKE_layer_collection_isolate_local(scene, view_layer, v3d, lc, extend);
443 }
444 }
445 else {
446 BKE_layer_collection_isolate_global(scene, view_layer, lc, extend);
447 }
448
450
451 return OPERATOR_FINISHED;
452}
453
454#define COLLECTION_INVALID_INDEX -1
455
457{
458 const Scene *scene = CTX_data_scene(C);
459 ViewLayer *view_layer = CTX_data_view_layer(C);
460 LayerCollection *lc_scene = static_cast<LayerCollection *>(view_layer->layer_collections.first);
461
462 /* Use the "invoke" operator context so the "Shift" modifier is used to extend. */
464
466 int index = BKE_layer_collection_findindex(view_layer, lc);
467 uiLayout *row = &layout->row(false);
468
469 if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
470 continue;
471 }
472
473 if (lc->collection->flag & COLLECTION_HIDE_VIEWPORT) {
474 continue;
475 }
476
477 int icon = ICON_NONE;
478 if (BKE_layer_collection_has_selected_objects(scene, view_layer, lc)) {
479 icon = ICON_LAYER_ACTIVE;
480 }
481 else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) {
482 icon = ICON_LAYER_USED;
483 }
484 PointerRNA op_ptr = row->op("OBJECT_OT_hide_collection", lc->collection->id.name + 2, icon);
485 RNA_int_set(&op_ptr, "collection_index", index);
486 }
487}
488
490 wmOperator *op,
491 const wmEvent *event)
492{
493 /* Immediately execute if collection index was specified. */
494 int index = RNA_int_get(op->ptr, "collection_index");
495 if (index != COLLECTION_INVALID_INDEX) {
496 /* Only initialize extend from the shift key if the property isn't set
497 * (typically initialized from the key-map). */
498 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "extend");
499 if (!RNA_property_is_set(op->ptr, prop)) {
500 RNA_property_boolean_set(op->ptr, prop, (event->modifier & KM_SHIFT) != 0);
501 }
502 return object_hide_collection_exec(C, op);
503 }
504
505 /* Open popup menu. */
506 const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
507 uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_OUTLINER_COLLECTION);
508 uiLayout *layout = UI_popup_menu_layout(pup);
509
511
512 UI_popup_menu_end(C, pup);
513
514 return OPERATOR_INTERFACE;
515}
516
518{
519 /* identifiers */
520 ot->name = "Hide Other Collections";
521 ot->description = "Show only objects in collection (Shift to extend)";
522 ot->idname = "OBJECT_OT_hide_collection";
523
524 /* API callbacks. */
528
529 /* flags */
531
532 /* Properties. */
533 PropertyRNA *prop;
534 prop = RNA_def_int(ot->srna,
535 "collection_index",
538 INT_MAX,
539 "Collection Index",
540 "Index of the collection to change visibility",
541 0,
542 INT_MAX);
544 prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "Toggle visibility");
546 prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend visibility");
548}
549
551
552/* -------------------------------------------------------------------- */
555
556static bool mesh_needs_keyindex(Main *bmain, const Mesh *mesh)
557{
558 if (mesh->key) {
559 return false; /* will be added */
560 }
561
562 LISTBASE_FOREACH (const Object *, ob, &bmain->objects) {
563 if ((ob->parent) && (ob->parent->data == mesh) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
564 return true;
565 }
566 if (ob->data == mesh) {
567 LISTBASE_FOREACH (const ModifierData *, md, &ob->modifiers) {
568 if (md->type == eModifierType_Hook) {
569 return true;
570 }
571 }
572 }
573 }
574 return false;
575}
576
583static bool editmode_load_free_ex(Main *bmain,
584 Object *obedit,
585 const bool load_data,
586 const bool free_data)
587{
588 BLI_assert(load_data || free_data);
589
590 if (obedit == nullptr) {
591 return false;
592 }
593
594 if (obedit->type == OB_MESH) {
595 Mesh *mesh = static_cast<Mesh *>(obedit->data);
596 if (mesh->runtime->edit_mesh == nullptr) {
597 return false;
598 }
599
600 if (mesh->runtime->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
601 /* This used to be warned int the UI, we could warn again although it's quite rare. */
602 CLOG_WARN(&LOG,
603 "Too many vertices for mesh '%s' (%d)",
604 mesh->id.name + 2,
605 mesh->runtime->edit_mesh->bm->totvert);
606 return false;
607 }
608
609 if (load_data) {
610 EDBM_mesh_load_ex(bmain, obedit, free_data);
611 }
612
613 if (free_data) {
614 EDBM_mesh_free_data(mesh->runtime->edit_mesh.get());
615 mesh->runtime->edit_mesh.reset();
616 }
617 /* will be recalculated as needed. */
618 {
621 }
622 }
623 else if (obedit->type == OB_ARMATURE) {
624 const bArmature *arm = static_cast<const bArmature *>(obedit->data);
625 if (arm->edbo == nullptr) {
626 return false;
627 }
628
629 if (load_data) {
630 ED_armature_from_edit(bmain, static_cast<bArmature *>(obedit->data));
631 }
632
633 if (free_data) {
634 ED_armature_edit_free(static_cast<bArmature *>(obedit->data));
635
636 if (load_data == false) {
637 /* Don't keep unused pose channels created by duplicating bones
638 * which may have been deleted/undone, see: #87631. */
639 if (obedit->pose != nullptr) {
641 }
642 }
643 }
644 /* TODO(sergey): Pose channels might have been changed, so need
645 * to inform dependency graph about this. But is it really the
646 * best place to do this?
647 */
649 }
650 else if (ELEM(obedit->type, OB_CURVES_LEGACY, OB_SURF)) {
651 const Curve *cu = static_cast<const Curve *>(obedit->data);
652 if (cu->editnurb == nullptr) {
653 return false;
654 }
655
656 if (load_data) {
657 ED_curve_editnurb_load(bmain, obedit);
658 }
659
660 if (free_data) {
662 }
663 }
664 else if (obedit->type == OB_FONT) {
665 const Curve *cu = static_cast<const Curve *>(obedit->data);
666 if (cu->editfont == nullptr) {
667 return false;
668 }
669
670 if (load_data) {
672 }
673
674 if (free_data) {
676 }
677 }
678 else if (obedit->type == OB_LATTICE) {
679 const Lattice *lt = static_cast<const Lattice *>(obedit->data);
680 if (lt->editlatt == nullptr) {
681 return false;
682 }
683
684 if (load_data) {
685 BKE_editlattice_load(obedit);
686 }
687
688 if (free_data) {
689 BKE_editlattice_free(obedit);
690 }
691 }
692 else if (obedit->type == OB_MBALL) {
693 const MetaBall *mb = static_cast<const MetaBall *>(obedit->data);
694 if (mb->editelems == nullptr) {
695 return false;
696 }
697
698 if (load_data) {
700 }
701
702 if (free_data) {
704 }
705 }
706 else if (ELEM(obedit->type, OB_CURVES, OB_GREASE_PENCIL, OB_POINTCLOUD)) {
707 /* Object doesn't have specific edit mode data, so pass. */
708 }
709 else {
710 return false;
711 }
712
713 if (load_data) {
714 char *needs_flush_ptr = BKE_object_data_editmode_flush_ptr_get(
715 static_cast<ID *>(obedit->data));
716 if (needs_flush_ptr) {
717 *needs_flush_ptr = false;
718 }
719 }
720
721 return true;
722}
723
724bool editmode_load(Main *bmain, Object *obedit)
725{
726 return editmode_load_free_ex(bmain, obedit, true, false);
727}
728
729bool editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag)
730{
731 const bool free_data = (flag & EM_FREEDATA) != 0;
732
733 if (editmode_load_free_ex(bmain, obedit, true, free_data) == false) {
734 /* in rare cases (background mode) its possible active object
735 * is flagged for editmode, without 'obedit' being set #35489. */
736 if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
737 obedit->mode &= ~OB_MODE_EDIT;
738 /* Also happens when mesh is shared across multiple objects. #69834. */
740 /* Leaving edit mode may modify the original object data; tag that as well. */
741 DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
742 }
743 return true;
744 }
745
746 /* `free_data` only false now on file saves and render. */
747 if (free_data) {
748 /* flag object caches as outdated */
749 ListBase pidlist;
750 BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
751 LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
752 /* particles don't need reset on geometry change */
753 if (pid->type != PTCACHE_TYPE_PARTICLES) {
754 pid->cache->flag |= PTCACHE_OUTDATED;
755 }
756 }
757 BLI_freelistN(&pidlist);
758
761
762 /* also flush ob recalc, doesn't take much overhead, but used for particles */
764 /* Leaving edit mode may modify the original object data; tag that as well. */
765 DEG_id_tag_update(static_cast<ID *>(obedit->data), ID_RECALC_GEOMETRY);
766
768
769 obedit->mode &= ~OB_MODE_EDIT;
770 }
771
772 return (obedit->mode & OB_MODE_EDIT) == 0;
773}
774
776{
777 Main *bmain = CTX_data_main(C);
778 Scene *scene = CTX_data_scene(C);
779 Object *obedit = CTX_data_edit_object(C);
780 return editmode_exit_ex(bmain, scene, obedit, flag);
781}
782
783bool editmode_free_ex(Main *bmain, Object *obedit)
784{
785 return editmode_load_free_ex(bmain, obedit, false, true);
786}
787
788bool editmode_exit_multi_ex(Main *bmain, Scene *scene, ViewLayer *view_layer, int flag)
789{
790 BKE_view_layer_synced_ensure(scene, view_layer);
791 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
792 if (obedit == nullptr) {
793 return false;
794 }
795 bool changed = false;
796 const short obedit_type = obedit->type;
797
798 BKE_view_layer_synced_ensure(scene, view_layer);
800 Object *ob = base->object;
801 if ((ob->type == obedit_type) && (ob->mode & OB_MODE_EDIT)) {
802 changed |= editmode_exit_ex(bmain, scene, base->object, flag);
803 }
804 }
805 return changed;
806}
807
809{
810 Main *bmain = CTX_data_main(C);
811 Scene *scene = CTX_data_scene(C);
812 ViewLayer *view_layer = CTX_data_view_layer(C);
813 return editmode_exit_multi_ex(bmain, scene, view_layer, flag);
814}
815
816bool editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
817{
818 bool ok = false;
819
820 if (ELEM(nullptr, ob, ob->data) || !ID_IS_EDITABLE(ob) || ID_IS_OVERRIDE_LIBRARY(ob) ||
822 {
823 return false;
824 }
825
826 /* This checks actual `ob->data`, for cases when other scenes have it in edit-mode context.
827 * Currently multiple objects sharing a mesh being in edit-mode at once isn't supported,
828 * see: #86767. */
830 return true;
831 }
832
834 /* Ideally the caller should check this. */
835 CLOG_WARN(&LOG, "Unable to enter edit-mode on library data for object '%s'", ob->id.name + 2);
836 return false;
837 }
838
839 ob->restore_mode = ob->mode;
840
841 ob->mode = OB_MODE_EDIT;
842
843 if (ob->type == OB_MESH) {
844 ok = true;
845
846 const bool use_key_index = mesh_needs_keyindex(bmain, static_cast<const Mesh *>(ob->data));
847
848 EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
849
851 if (LIKELY(em)) {
853 }
854
856 }
857 else if (ob->type == OB_ARMATURE) {
858 bArmature *arm = static_cast<bArmature *>(ob->data);
859 ok = true;
861 /* To ensure all goes in rest-position and without striding. */
862
863 arm->needs_flush_to_id = 0;
864
865 /* WORKAROUND / FIXME: this is a temporary workaround to ensure that
866 * full bone collection data gets restored when exiting edit mode
867 * via an undo step. The correct fix is to have a full edit-mode
868 * copy of bone collections so that edit-mode changes don't modify
869 * object-mode armature data until exiting edit mode. But that
870 * change is a bit of a project, and will be done later. This line
871 * should be removed when that is done. */
872 bmain->is_memfile_undo_written = false;
873
874 /* XXX: should this be ID_RECALC_GEOMETRY? */
876
878 }
879 else if (ob->type == OB_FONT) {
880 ok = true;
882
884 }
885 else if (ob->type == OB_MBALL) {
886 MetaBall *mb = static_cast<MetaBall *>(ob->data);
887
888 ok = true;
890
891 mb->needs_flush_to_id = 0;
892
894 }
895 else if (ob->type == OB_LATTICE) {
896 ok = true;
898
900 }
901 else if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY)) {
902 ok = true;
904
906 }
907 else if (ob->type == OB_CURVES) {
908 ok = true;
910 }
911 else if (ob->type == OB_GREASE_PENCIL) {
912 ok = true;
915 }
916 else if (ob->type == OB_POINTCLOUD) {
917 ok = true;
919 }
920
921 if (ok) {
923 }
924 else {
925 if ((flag & EM_NO_CONTEXT) == 0) {
926 ob->mode &= ~OB_MODE_EDIT;
927 }
929 }
930
931 return (ob->mode & OB_MODE_EDIT) != 0;
932}
933
935{
936 Main *bmain = CTX_data_main(C);
937 Scene *scene = CTX_data_scene(C);
938
939 /* Active layer checked here for view3d,
940 * callers that don't want view context can call the extended version. */
942 return editmode_enter_ex(bmain, scene, ob, flag);
943}
944
946{
947 Main *bmain = CTX_data_main(C);
948 Scene *scene = CTX_data_scene(C);
949 View3D *v3d = CTX_wm_view3d(C);
950 ViewLayer *view_layer = CTX_data_view_layer(C);
951 BKE_view_layer_synced_ensure(scene, view_layer);
952 Object *obact = BKE_view_layer_active_object_get(view_layer);
953 const int mode_flag = OB_MODE_EDIT;
954 const bool is_mode_set = (obact->mode & mode_flag) != 0;
956
958 return OPERATOR_CANCELLED;
959 }
960 if (!is_mode_set) {
961 if (!mode_compat_set(C, obact, eObjectMode(mode_flag), op->reports)) {
962 return OPERATOR_CANCELLED;
963 }
964 }
965
966 if (!is_mode_set) {
967 editmode_enter_ex(bmain, scene, obact, 0);
968 /* Grease Pencil does not support multi-object editing. */
969 if ((obact->type != OB_GREASE_PENCIL) && ((obact->mode & mode_flag) != 0)) {
970 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
971 if ((ob != obact) && (ob->type == obact->type)) {
972 editmode_enter_ex(bmain, scene, ob, EM_NO_CONTEXT);
973 }
974 }
976 }
977 }
978 else {
979 editmode_exit_ex(bmain, scene, obact, EM_FREEDATA);
980
981 if ((obact->mode & mode_flag) == 0) {
982 FOREACH_OBJECT_BEGIN (scene, view_layer, ob) {
983 if ((ob != obact) && (ob->type == obact->type)) {
984 editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
985 }
986 }
988 }
989 }
990
991 WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
992
993 if (G.background == false) {
995 }
996
997 return OPERATOR_FINISHED;
998}
999
1001{
1002 /* Get object the same way as in editmode_toggle_exec(). Otherwise overriding context can crash,
1003 * see #137998. */
1004 ViewLayer *view_layer = CTX_data_view_layer(C);
1006 Object *ob = BKE_view_layer_active_object_get(view_layer);
1007
1008 /* Covers liboverrides too. */
1009 if (ELEM(nullptr, ob, ob->data) || !ID_IS_EDITABLE(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob) ||
1011 {
1012 return false;
1013 }
1014
1015 /* If hidden but in edit mode, we still display. */
1016 if ((ob->visibility_flag & OB_HIDE_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) {
1017 return false;
1018 }
1019
1020 return OB_TYPE_SUPPORT_EDITMODE(ob->type);
1021}
1022
1024{
1025
1026 /* identifiers */
1027 ot->name = "Edit Mode";
1028 ot->description = "Toggle object's edit mode";
1029 ot->idname = "OBJECT_OT_editmode_toggle";
1030
1031 /* API callbacks. */
1032 ot->exec = editmode_toggle_exec;
1033 ot->poll = editmode_toggle_poll;
1034
1035 /* flags */
1036 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1037}
1038
1040
1041/* -------------------------------------------------------------------- */
1044
1046{
1047 wmMsgBus *mbus = CTX_wm_message_bus(C);
1048 Main *bmain = CTX_data_main(C);
1049 Scene *scene = CTX_data_scene(C);
1050 ViewLayer *view_layer = CTX_data_view_layer(C);
1051 Base *base = CTX_data_active_base(C);
1052
1054 return OPERATOR_CANCELLED;
1055 }
1056
1057 /* If the base is nullptr it means we have an active object, but the object itself is hidden. */
1058 if (base == nullptr) {
1059 return OPERATOR_CANCELLED;
1060 }
1061
1062 Object *obact = base->object;
1063 const int mode_flag = OB_MODE_POSE;
1064 bool is_mode_set = (obact->mode & mode_flag) != 0;
1065
1066 if (!is_mode_set) {
1067 if (!mode_compat_set(C, obact, eObjectMode(mode_flag), op->reports)) {
1068 return OPERATOR_CANCELLED;
1069 }
1070 }
1071
1072 if (obact->type != OB_ARMATURE) {
1073 return OPERATOR_PASS_THROUGH;
1074 }
1075
1076 {
1077 BKE_view_layer_synced_ensure(scene, view_layer);
1078 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
1079 if (obact == obedit) {
1080 editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
1081 is_mode_set = false;
1082 }
1083 }
1084
1085 if (is_mode_set) {
1086 bool ok = ED_object_posemode_exit(C, obact);
1087 if (ok) {
1088 FOREACH_OBJECT_BEGIN (scene, view_layer, ob) {
1089 if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) {
1090 ED_object_posemode_exit_ex(bmain, ob);
1091 }
1092 }
1094 }
1095 }
1096 else {
1097 bool ok = ED_object_posemode_enter(C, obact);
1098 if (ok) {
1099 const View3D *v3d = CTX_wm_view3d(C);
1100 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
1101 if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) &&
1102 BKE_id_is_editable(bmain, &ob->id))
1103 {
1104 ED_object_posemode_enter_ex(bmain, ob);
1105 }
1106 }
1108 }
1109 }
1110
1111 WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
1112
1113 if (G.background == false) {
1115 }
1116
1117 return OPERATOR_FINISHED;
1118}
1119
1121{
1122 /* identifiers */
1123 ot->name = "Toggle Pose Mode";
1124 ot->idname = "OBJECT_OT_posemode_toggle";
1125 ot->description = "Enable or disable posing/selecting bones";
1126
1127 /* API callbacks. */
1128 ot->exec = posemode_exec;
1130
1131 /* flag */
1132 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1133}
1134
1136
1137/* -------------------------------------------------------------------- */
1140
1141void check_force_modifiers(Main *bmain, Scene *scene, Object *object)
1142{
1143 PartDeflect *pd = object->pd;
1145
1146 /* add/remove modifier as needed */
1147 if (!md) {
1148 if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) &&
1150 {
1152 modifier_add(nullptr, bmain, scene, object, nullptr, eModifierType_Surface);
1153 }
1154 }
1155 }
1156 else {
1157 if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) ||
1159 {
1160 modifier_remove(nullptr, bmain, scene, object, md);
1161 }
1162 }
1163}
1164
1166{
1168
1169 if (ob->pd == nullptr) {
1172 }
1173 else if (ob->pd->forcefield == 0) {
1174 ob->pd->forcefield = PFIELD_FORCE;
1176 }
1177 else {
1178 ob->pd->forcefield = 0;
1179 }
1180
1184
1186
1187 return OPERATOR_FINISHED;
1188}
1189
1191{
1192
1193 /* identifiers */
1194 ot->name = "Toggle Force Field";
1195 ot->description = "Toggle object's force field";
1196 ot->idname = "OBJECT_OT_forcefield_toggle";
1197
1198 /* API callbacks. */
1199 ot->exec = forcefield_toggle_exec;
1201
1202 /* flags */
1203 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1204}
1205
1207
1208/* -------------------------------------------------------------------- */
1211
1224
1226{
1227 ListBase selected_objects = {nullptr, nullptr};
1228 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1229 BLI_addtail(&selected_objects, BLI_genericNodeN(ob));
1230 }
1232
1233 motion_paths_recalc(C, scene, range, &selected_objects);
1234
1235 BLI_freelistN(&selected_objects);
1236}
1237
1239{
1240 ListBase visible_objects = {nullptr, nullptr};
1241 CTX_DATA_BEGIN (C, Object *, ob, visible_objects) {
1242 BLI_addtail(&visible_objects, BLI_genericNodeN(ob));
1243 }
1245
1246 motion_paths_recalc(C, scene, range, &visible_objects);
1247
1248 BLI_freelistN(&visible_objects);
1249}
1250
1252{
1253 return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1254}
1255
1257{
1258 return ob->pose && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1259}
1260
1262 Scene *scene,
1264 ListBase *ld_objects)
1265{
1266 /* Transform doesn't always have context available to do update. */
1267 if (C == nullptr) {
1268 return;
1269 }
1270
1271 Main *bmain = CTX_data_main(C);
1272 ViewLayer *view_layer = CTX_data_view_layer(C);
1273
1275 LISTBASE_FOREACH (LinkData *, link, ld_objects) {
1276 Object *ob = static_cast<Object *>(link->data);
1277
1278 /* set flag to force recalc, then grab path(s) from object */
1279 if (has_object_motion_paths(ob)) {
1281 }
1282
1283 if (has_pose_motion_paths(ob)) {
1285 }
1286
1288 }
1289
1290 Depsgraph *depsgraph;
1291 bool free_depsgraph = false;
1292 /* For a single frame update it's faster to re-use existing dependency graph and avoid overhead
1293 * of building all the relations and so on for a temporary one. */
1295 /* NOTE: Dependency graph will be evaluated at all the frames, but we first need to access some
1296 * nested pointers, like animation data. */
1298 free_depsgraph = false;
1299 }
1300 else {
1301 depsgraph = animviz_depsgraph_build(bmain, scene, view_layer, targets);
1302 free_depsgraph = true;
1303 }
1304
1306 depsgraph, bmain, scene, targets, object_path_convert_range(range), true);
1308
1310 /* Tag objects for copy-on-eval - so paths will draw/redraw
1311 * For currently frame only we update evaluated object directly. */
1312 LISTBASE_FOREACH (LinkData *, link, ld_objects) {
1313 Object *ob = static_cast<Object *>(link->data);
1314
1317 }
1318 }
1319 }
1320
1321 /* Free temporary depsgraph. */
1322 if (free_depsgraph) {
1324 }
1325}
1326
1327/* show popup to determine settings */
1329 wmOperator *op,
1330 const wmEvent * /*event*/)
1331{
1333
1334 if (ob == nullptr) {
1335 return OPERATOR_CANCELLED;
1336 }
1337
1338 /* set default settings from existing/stored settings */
1339 {
1340 bAnimVizSettings *avs = &ob->avs;
1341 RNA_enum_set(op->ptr, "display_type", avs->path_type);
1342 RNA_enum_set(op->ptr, "range", avs->path_range);
1343 }
1344
1345 /* show popup dialog to allow editing of range... */
1346 /* FIXME: hard-coded dimensions here are just arbitrary. */
1348 C, op, 270, IFACE_("Calculate Object Motion Paths"), IFACE_("Calculate"));
1349}
1350
1351/* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */
1353{
1354 Scene *scene = CTX_data_scene(C);
1355 short path_type = RNA_enum_get(op->ptr, "display_type");
1356 short path_range = RNA_enum_get(op->ptr, "range");
1357
1358 /* set up path data for objects being calculated */
1359 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1360 bAnimVizSettings *avs = &ob->avs;
1361 /* grab baking settings from operator settings */
1362 avs->path_type = path_type;
1363 avs->path_range = path_range;
1365
1366 /* verify that the selected object has the appropriate settings */
1367 animviz_verify_motionpaths(op->reports, scene, ob, nullptr);
1368 }
1370
1371 /* calculate the paths for objects that have them (and are tagged to get refreshed) */
1373
1374 /* notifiers for updates */
1376 /* NOTE: the notifier below isn't actually correct, but kept around just to be on the safe side.
1377 * If further testing shows it's not necessary (for both bones and objects) removal is fine. */
1379
1380 return OPERATOR_FINISHED;
1381}
1382
1384{
1385 /* identifiers */
1386 ot->name = "Calculate Object Motion Paths";
1387 ot->idname = "OBJECT_OT_paths_calculate";
1388 ot->description = "Generate motion paths for the selected objects";
1389
1390 /* API callbacks. */
1394
1395 /* flags */
1396 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1397
1398 /* properties */
1399 RNA_def_enum(ot->srna,
1400 "display_type",
1403 "Display type",
1404 "");
1405 RNA_def_enum(ot->srna,
1406 "range",
1409 "Computation Range",
1410 "");
1411}
1412
1414
1415/* -------------------------------------------------------------------- */
1418
1420{
1423 return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
1424 }
1425
1426 return false;
1427}
1428
1430{
1431 Scene *scene = CTX_data_scene(C);
1432
1433 if (scene == nullptr) {
1434 return OPERATOR_CANCELLED;
1435 }
1436 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1438 /* verify that the selected object has the appropriate settings */
1439 animviz_verify_motionpaths(op->reports, scene, ob, nullptr);
1440 }
1442
1443 /* calculate the paths for objects that have them (and are tagged to get refreshed) */
1445
1446 /* notifiers for updates */
1448 /* NOTE: the notifier below isn't actually correct, but kept around just to be on the safe side.
1449 * If further testing shows it's not necessary (for both bones and objects) removal is fine. */
1451
1452 return OPERATOR_FINISHED;
1453}
1454
1456{
1457 /* identifiers */
1458 ot->name = "Update Object Paths";
1459 ot->idname = "OBJECT_OT_paths_update";
1460 ot->description = "Recalculate motion paths for selected objects";
1461
1462 /* API callbacks. */
1465
1466 /* flags */
1467 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1468}
1469
1471
1472/* -------------------------------------------------------------------- */
1475
1477{
1478 return true;
1479}
1480
1482{
1483 Scene *scene = CTX_data_scene(C);
1484
1485 if (scene == nullptr) {
1486 return OPERATOR_CANCELLED;
1487 }
1488
1490
1492
1493 return OPERATOR_FINISHED;
1494}
1495
1497{
1498 /* identifiers */
1499 ot->name = "Update All Object Paths";
1500 ot->idname = "OBJECT_OT_paths_update_visible";
1501 ot->description = "Recalculate all visible motion paths for objects and poses";
1502
1503 /* API callbacks. */
1506
1507 /* flags */
1508 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1509}
1510
1512
1513/* -------------------------------------------------------------------- */
1516
1517/* Helper for motion_paths_clear() */
1519{
1520 if (ob->mpath) {
1522 ob->mpath = nullptr;
1524
1525 /* tag object for copy-on-eval - so removed paths don't still show */
1527 }
1528}
1529
1530void motion_paths_clear(bContext *C, bool only_selected)
1531{
1532 if (only_selected) {
1533 /* Loop over all selected + editable objects in scene. */
1534 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1536 }
1538 }
1539 else {
1540 /* Loop over all editable objects in scene. */
1541 CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
1543 }
1545 }
1546}
1547
1548/* operator callback for this */
1550{
1551 bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
1552
1553 /* use the backend function for this */
1554 motion_paths_clear(C, only_selected);
1555
1556 /* notifiers for updates */
1558
1559 return OPERATOR_FINISHED;
1560}
1561
1563 wmOperatorType * /*ot*/,
1564 PointerRNA *ptr)
1565{
1566 const bool only_selected = RNA_boolean_get(ptr, "only_selected");
1567 if (only_selected) {
1568 return TIP_("Clear motion paths of selected objects");
1569 }
1570 return TIP_("Clear motion paths of all objects");
1571}
1572
1574{
1575 /* identifiers */
1576 ot->name = "Clear Object Paths";
1577 ot->idname = "OBJECT_OT_paths_clear";
1578
1579 /* API callbacks. */
1582 ot->get_description = object_clear_paths_get_description;
1583
1584 /* flags */
1585 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1586
1587 /* properties */
1588 ot->prop = RNA_def_boolean(ot->srna,
1589 "only_selected",
1590 false,
1591 "Only Selected",
1592 "Only clear motion paths of selected objects");
1594}
1595
1597
1598/* -------------------------------------------------------------------- */
1601
1603{
1604 if (md.type != eModifierType_Nodes) {
1605 return false;
1606 }
1607 const NodesModifierData &nmd = reinterpret_cast<const NodesModifierData &>(md);
1608 if (!nmd.node_group) {
1609 return false;
1610 }
1611 const LibraryWeakReference *library_ref = nmd.node_group->id.library_weak_reference;
1612 if (!library_ref) {
1613 return false;
1614 }
1615 if (!STREQ(library_ref->library_id_name + 2, "Smooth by Angle")) {
1616 return false;
1617 }
1618 return true;
1619}
1620
1622{
1623 const bool use_flat = STREQ(op->idname, "OBJECT_OT_shade_flat");
1624 const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth");
1625 const bool use_smooth_by_angle = STREQ(op->idname, "OBJECT_OT_shade_smooth_by_angle");
1626 Main *bmain = CTX_data_main(C);
1627 Scene *scene = CTX_data_scene(C);
1628
1629 Vector<PointerRNA> ctx_objects;
1630
1631 /* For modes that only use an active object, don't handle the whole selection. */
1632 {
1633 Scene *scene = CTX_data_scene(C);
1634 ViewLayer *view_layer = CTX_data_view_layer(C);
1635 BKE_view_layer_synced_ensure(scene, view_layer);
1636 Object *obact = BKE_view_layer_active_object_get(view_layer);
1637 if (obact && (obact->mode & OB_MODE_ALL_PAINT)) {
1638 ctx_objects.append(RNA_id_pointer_create(&obact->id));
1639 }
1640 }
1641
1642 if (ctx_objects.is_empty()) {
1644 }
1645
1646 bool modifier_removed = false;
1647
1648 Set<ID *> object_data;
1649 for (const PointerRNA &ptr : ctx_objects) {
1650 Object *ob = static_cast<Object *>(ptr.data);
1651 if (ID *data = static_cast<ID *>(ob->data)) {
1652 object_data.add(data);
1653
1654 if (ob->type == OB_MESH) {
1655 if (use_flat || use_smooth) {
1657 if (is_smooth_by_angle_modifier(*md)) {
1658 modifier_remove(op->reports, bmain, scene, ob, md);
1660 modifier_removed = true;
1661 break;
1662 }
1663 }
1664 }
1665 }
1666 }
1667 }
1668
1669 bool changed_multi = false;
1670 bool has_linked_data = false;
1671 for (ID *data : object_data) {
1672 if (!BKE_id_is_editable(bmain, data)) {
1673 has_linked_data = true;
1674 continue;
1675 }
1676
1677 bool changed = false;
1678 if (GS(data->name) == ID_ME) {
1679 Mesh &mesh = *reinterpret_cast<Mesh *>(data);
1680 const bool keep_sharp_edges = RNA_boolean_get(op->ptr, "keep_sharp_edges");
1681 bke::mesh_smooth_set(mesh, use_smooth || use_smooth_by_angle, keep_sharp_edges);
1682 if (use_smooth_by_angle) {
1683 const float angle = RNA_float_get(op->ptr, "angle");
1685 }
1687 changed = true;
1688 }
1689 else if (GS(data->name) == ID_CU_LEGACY) {
1690 BKE_curve_smooth_flag_set(reinterpret_cast<Curve *>(data), use_smooth);
1691 changed = true;
1692 }
1693
1694 if (changed) {
1695 changed_multi = true;
1698 }
1699 }
1700
1701 if (modifier_removed) {
1702 /* Outliner needs to know. #124302. */
1704 }
1705
1706 if (has_linked_data) {
1707 BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data");
1708 }
1709
1710 return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1711}
1712
1713static bool shade_poll(bContext *C)
1714{
1715 const Scene *scene = CTX_data_scene(C);
1716 ViewLayer *view_layer = CTX_data_view_layer(C);
1717 BKE_view_layer_synced_ensure(scene, view_layer);
1718 Object *obact = BKE_view_layer_active_object_get(view_layer);
1719 if (obact != nullptr) {
1720 /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */
1721 if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT) || obact->data == nullptr ||
1722 !ID_IS_EDITABLE(obact) || !ID_IS_EDITABLE(obact->data) || ID_IS_OVERRIDE_LIBRARY(obact) ||
1724 {
1725 return false;
1726 }
1727 }
1728 return true;
1729}
1730
1732{
1733 /* identifiers */
1734 ot->name = "Shade Flat";
1735 ot->description = "Render and display faces uniform, using face normals";
1736 ot->idname = "OBJECT_OT_shade_flat";
1737
1738 /* API callbacks. */
1739 ot->poll = shade_poll;
1740 ot->exec = shade_smooth_exec;
1741
1742 /* flags */
1743 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1744
1745 RNA_def_boolean(ot->srna,
1746 "keep_sharp_edges",
1747 true,
1748 "Keep Sharp Edges",
1749 "Don't remove sharp edges, which are redundant with faces shaded smooth");
1750}
1751
1753{
1754 /* identifiers */
1755 ot->name = "Shade Smooth";
1756 ot->description = "Render and display faces smooth, using interpolated vertex normals";
1757 ot->idname = "OBJECT_OT_shade_smooth";
1758
1759 /* API callbacks. */
1760 ot->poll = shade_poll;
1761 ot->exec = shade_smooth_exec;
1762
1763 /* flags */
1764 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1765
1766 RNA_def_boolean(ot->srna,
1767 "keep_sharp_edges",
1768 true,
1769 "Keep Sharp Edges",
1770 "Don't remove sharp edges. Tagged edges will remain sharp");
1771}
1772
1774{
1775 ot->name = "Shade Smooth by Angle";
1776 ot->description =
1777 "Set the sharpness of mesh edges based on the angle between the neighboring faces";
1778 ot->idname = "OBJECT_OT_shade_smooth_by_angle";
1779
1780 ot->poll = shade_poll;
1781 ot->exec = shade_smooth_exec;
1782
1783 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1784
1785 PropertyRNA *prop = RNA_def_property(ot->srna, "angle", PROP_FLOAT, PROP_ANGLE);
1786 RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
1789 prop, "Angle", "Maximum angle between face normals that will be considered as smooth");
1790
1791 RNA_def_boolean(ot->srna,
1792 "keep_sharp_edges",
1793 true,
1794 "Keep Sharp Edges",
1795 "Only add sharp edges instead of clearing existing tags first");
1796}
1797
1799
1800/* -------------------------------------------------------------------- */
1803
1809{
1810 if (ntree.type != NTREE_GEOMETRY) {
1811 return false;
1812 }
1813 if (ntree.interface_inputs().size() != 3) {
1814 return false;
1815 }
1816 if (ntree.interface_outputs().size() != 1) {
1817 return false;
1818 }
1819 return true;
1820}
1821
1823{
1824 Main &bmain = *CTX_data_main(C);
1825 Scene &scene = *CTX_data_scene(C);
1826
1827 const bool use_auto_smooth = RNA_boolean_get(op->ptr, "use_auto_smooth");
1828 const float angle = RNA_float_get(op->ptr, "angle");
1829
1830 Vector<PointerRNA> ctx_objects;
1832
1833 if (use_auto_smooth) {
1834 AssetWeakReference asset_weak_ref{};
1836 asset_weak_ref.relative_asset_identifier = BLI_strdup(
1837 "geometry_nodes/smooth_by_angle.blend/NodeTree/Smooth by Angle");
1838
1839 const asset_system::AssetRepresentation *asset_representation =
1840 asset::find_asset_from_weak_ref(*C, asset_weak_ref, op->reports);
1841 if (!asset_representation) {
1842 return OPERATOR_CANCELLED;
1843 }
1844
1845 bNodeTree *node_group = nullptr;
1846 while (!node_group) {
1847 ID *node_group_id = asset::asset_local_id_ensure_imported(bmain, *asset_representation);
1848 if (!node_group_id) {
1849 return OPERATOR_CANCELLED;
1850 }
1851 if (GS(node_group_id->name) != ID_NT) {
1852 return OPERATOR_CANCELLED;
1853 }
1854 node_group = reinterpret_cast<bNodeTree *>(node_group_id);
1855 node_group->ensure_topology_cache();
1856 node_group->ensure_interface_cache();
1857 if (is_valid_smooth_by_angle_group(*node_group)) {
1858 break;
1859 }
1860 /* Remove the weak library reference, since the already loaded group is not valid anymore. */
1861 MEM_SAFE_FREE(node_group_id->library_weak_reference);
1862 /* Stay in the loop and load the asset again. */
1863 node_group = nullptr;
1864 }
1865
1866 const StringRefNull angle_identifier = node_group->interface_inputs()[1]->identifier;
1867
1868 for (const PointerRNA &ob_ptr : ctx_objects) {
1869 Object *object = static_cast<Object *>(ob_ptr.data);
1870 if (object->type == OB_MESH) {
1871 Mesh *mesh = static_cast<Mesh *>(object->data);
1872 bke::mesh_smooth_set(*mesh, true, true);
1874 }
1875 NodesModifierData *smooth_by_angle_nmd = nullptr;
1876 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
1877 if (is_smooth_by_angle_modifier(*md)) {
1878 smooth_by_angle_nmd = reinterpret_cast<NodesModifierData *>(md);
1879 break;
1880 }
1881 }
1882 if (!smooth_by_angle_nmd) {
1883 smooth_by_angle_nmd = reinterpret_cast<NodesModifierData *>(
1884 modifier_add(op->reports, &bmain, &scene, object, nullptr, eModifierType_Nodes));
1885 if (!smooth_by_angle_nmd) {
1886 continue;
1887 }
1888 smooth_by_angle_nmd->modifier.flag |= eModifierFlag_PinLast;
1889 smooth_by_angle_nmd->node_group = node_group;
1890 id_us_plus(&node_group->id);
1891 MOD_nodes_update_interface(object, smooth_by_angle_nmd);
1892 smooth_by_angle_nmd->flag |= NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR;
1893 STRNCPY(smooth_by_angle_nmd->modifier.name, DATA_(node_group->id.name + 2));
1894 BKE_modifier_unique_name(&object->modifiers, &smooth_by_angle_nmd->modifier);
1895 }
1896
1897 IDProperty *angle_prop = IDP_GetPropertyFromGroup(smooth_by_angle_nmd->settings.properties,
1898 angle_identifier.c_str());
1899 if (angle_prop->type == IDP_FLOAT) {
1900 IDP_Float(angle_prop) = angle;
1901 }
1902 else if (angle_prop->type == IDP_DOUBLE) {
1903 IDP_Double(angle_prop) = angle;
1904 }
1905
1908 }
1909 }
1910 else {
1911 for (const PointerRNA &ob_ptr : ctx_objects) {
1912 Object *object = static_cast<Object *>(ob_ptr.data);
1913 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
1914 if (is_smooth_by_angle_modifier(*md)) {
1915 modifier_remove(op->reports, &bmain, &scene, object, md);
1916 break;
1917 }
1918 }
1919 }
1920 }
1921
1922 return OPERATOR_FINISHED;
1923}
1924
1926{
1927 uiLayout *layout = op->layout;
1928
1929 uiLayoutSetPropSep(layout, true);
1930 uiLayoutSetPropDecorate(layout, false);
1931
1932 layout->prop(op->ptr, "use_auto_smooth", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1933
1934 uiLayout *col = &layout->column(false);
1935 uiLayoutSetActive(col, RNA_boolean_get(op->ptr, "use_auto_smooth"));
1936 layout->prop(op->ptr, "angle", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1937}
1938
1940{
1941 ot->name = "Shade Auto Smooth";
1942 ot->description =
1943 "Add modifier to automatically set the sharpness of mesh edges based on the angle between "
1944 "the neighboring faces";
1945 ot->idname = "OBJECT_OT_shade_auto_smooth";
1946
1947 ot->poll = shade_poll;
1948 ot->exec = shade_auto_smooth_exec;
1950
1951 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1952
1953 PropertyRNA *prop;
1954
1955 prop = RNA_def_boolean(ot->srna,
1956 "use_auto_smooth",
1957 true,
1958 "Auto Smooth",
1959 "Add modifier to set edge sharpness automatically");
1961
1962 prop = RNA_def_property(ot->srna, "angle", PROP_FLOAT, PROP_ANGLE);
1963 RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
1966 prop, "Angle", "Maximum angle between face normals that will be considered as smooth");
1967}
1968
1970
1971/* -------------------------------------------------------------------- */
1974
1976 PointerRNA * /*ptr*/,
1977 PropertyRNA * /*prop*/,
1978 bool *r_free)
1979{
1981 EnumPropertyItem *item = nullptr;
1982 int totitem = 0;
1983
1984 if (!C) { /* needed for docs */
1986 }
1987
1988 const Object *ob = CTX_data_active_object(C);
1989 if (ob) {
1990 while (input->identifier) {
1991 if (mode_compat_test(ob, eObjectMode(input->value))) {
1992 RNA_enum_item_add(&item, &totitem, input);
1993 }
1994 input++;
1995 }
1996 }
1997 else {
1998 /* We need at least this one! */
2000 }
2001
2002 RNA_enum_item_end(&item, &totitem);
2003
2004 *r_free = true;
2005
2006 return item;
2007}
2008
2010{
2011 /* Needed as #ED_operator_object_active_editable doesn't call use 'active_object'. */
2014}
2015
2017{
2018 const bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode");
2020 eObjectMode mode = eObjectMode(RNA_enum_get(op->ptr, "mode"));
2021 const bool toggle = RNA_boolean_get(op->ptr, "toggle");
2022
2023 if (!mode_compat_test(ob, mode)) {
2024 return OPERATOR_PASS_THROUGH;
2025 }
2027 return OPERATOR_CANCELLED;
2028 }
2029
2048 if (toggle == false) {
2049 if (ob->mode != mode) {
2050 mode_set_ex(C, mode, true, op->reports);
2051 }
2052 }
2053 else {
2054 const eObjectMode mode_prev = eObjectMode(ob->mode);
2055 /* When toggling object mode, we always use the restore mode,
2056 * otherwise there is nothing to do. */
2057 if (mode == OB_MODE_OBJECT) {
2058 if (ob->mode != OB_MODE_OBJECT) {
2059 if (mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) {
2060 /* Store old mode so we know what to go back to. */
2061 ob->restore_mode = mode_prev;
2062 }
2063 }
2064 else {
2065 if (ob->restore_mode != OB_MODE_OBJECT) {
2066 mode_set_ex(C, eObjectMode(ob->restore_mode), true, op->reports);
2067 }
2068 }
2069 }
2070 else {
2071 /* Non-object modes, enter the 'mode' unless it's already set,
2072 * in that case use restore mode. */
2073 if (ob->mode != mode) {
2074 if (mode_set_ex(C, mode, true, op->reports)) {
2075 /* Store old mode so we know what to go back to. */
2076 ob->restore_mode = mode_prev;
2077 }
2078 }
2079 else {
2080 if (ob->restore_mode != OB_MODE_OBJECT) {
2081 mode_set_ex(C, eObjectMode(ob->restore_mode), true, op->reports);
2082 }
2083 else {
2084 mode_set_ex(C, OB_MODE_OBJECT, true, op->reports);
2085 }
2086 }
2087 }
2088 }
2089
2090 if (use_submode) {
2091 if (ob->type == OB_MESH) {
2092 if (ob->mode & OB_MODE_EDIT) {
2093 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "mesh_select_mode");
2094 if (RNA_property_is_set(op->ptr, prop)) {
2095 int mesh_select_mode = RNA_property_enum_get(op->ptr, prop);
2096 if (mesh_select_mode != 0) {
2097 EDBM_selectmode_set_multi(C, mesh_select_mode);
2098 }
2099 }
2100 }
2101 }
2102 }
2103
2105 if (wm) {
2108 }
2109 }
2110
2111 return OPERATOR_FINISHED;
2112}
2113
2115{
2116 PropertyRNA *prop;
2117
2118 /* identifiers */
2119 ot->name = "Set Object Mode";
2120 ot->description = "Sets the object interaction mode";
2121 ot->idname = "OBJECT_OT_mode_set";
2122
2123 /* API callbacks. */
2124 ot->exec = object_mode_set_exec;
2125 ot->poll = object_mode_set_poll;
2126
2127 /* flags */
2128 ot->flag = 0; /* no register/undo here, leave it to operators being called */
2129
2130 ot->prop = RNA_def_enum(
2131 ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
2134
2135 prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "");
2137}
2138
2140{
2142
2143 /* identifiers */
2144 ot->name = "Set Object Mode with Sub-mode";
2145 ot->idname = "OBJECT_OT_mode_set_with_submode";
2146
2147 /* properties */
2148 /* we could add other types - particle for eg. */
2149 PropertyRNA *prop;
2150 prop = RNA_def_enum_flag(
2151 ot->srna, "mesh_select_mode", rna_enum_mesh_select_mode_items, 0, "Mesh Mode", "");
2153}
2154
2156
2157/* -------------------------------------------------------------------- */
2160
2162{
2163 ListBase objects = {nullptr};
2164
2165 if (CTX_wm_space_outliner(C) != nullptr) {
2167 }
2168 else {
2169 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2170 BLI_addtail(&objects, BLI_genericNodeN(ob));
2171 }
2173 }
2174
2175 return objects;
2176}
2177
2179{
2180 if (CTX_wm_space_outliner(C) != nullptr) {
2182 }
2183 return ED_operator_objectmode(C);
2184}
2185
2187{
2188 Main *bmain = CTX_data_main(C);
2189 Scene *scene = CTX_data_scene(C);
2190 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
2191 const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
2192 const bool is_new = RNA_boolean_get(op->ptr, "is_new");
2193
2194 if (!RNA_property_is_set(op->ptr, prop)) {
2195 BKE_report(op->reports, RPT_ERROR, "No collection selected");
2196 return OPERATOR_CANCELLED;
2197 }
2198
2199 int collection_index = RNA_property_int_get(op->ptr, prop);
2200 Collection *collection = BKE_collection_from_index(scene, collection_index);
2201 if (collection == nullptr) {
2202 BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
2203 return OPERATOR_CANCELLED;
2204 }
2205
2206 if (!ID_IS_EDITABLE(collection) || ID_IS_OVERRIDE_LIBRARY(collection)) {
2207 BKE_report(
2208 op->reports, RPT_ERROR, "Cannot add objects to a library override or linked collection");
2209 return OPERATOR_CANCELLED;
2210 }
2211
2212 ListBase objects = selected_objects_get(C);
2213
2214 if (is_new) {
2215 char new_collection_name[MAX_NAME];
2216 RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
2217 collection = BKE_collection_add(bmain, collection, new_collection_name);
2218 }
2219
2220 Object *single_object = BLI_listbase_is_single(&objects) ?
2221 static_cast<Object *>(((LinkData *)objects.first)->data) :
2222 nullptr;
2223
2224 if ((single_object != nullptr) && is_link &&
2225 BKE_collection_has_object(collection, single_object))
2226 {
2227 BKE_reportf(op->reports,
2228 RPT_ERROR,
2229 "%s already in %s",
2230 single_object->id.name + 2,
2231 BKE_collection_ui_name_get(collection));
2232 BLI_freelistN(&objects);
2233 return OPERATOR_CANCELLED;
2234 }
2235
2236 LISTBASE_FOREACH (LinkData *, link, &objects) {
2237 Object *ob = static_cast<Object *>(link->data);
2238
2239 if (!is_link) {
2240 BKE_collection_object_move(bmain, scene, collection, nullptr, ob);
2241 }
2242 else {
2243 BKE_collection_object_add(bmain, collection, ob);
2244 }
2245 }
2246 BLI_freelistN(&objects);
2247
2248 if (is_link) {
2249 if (single_object != nullptr) {
2250 BKE_reportf(op->reports,
2251 RPT_INFO,
2252 "%s linked to %s",
2253 single_object->id.name + 2,
2254 BKE_collection_ui_name_get(collection));
2255 }
2256 else {
2258 op->reports, RPT_INFO, "Objects linked to %s", BKE_collection_ui_name_get(collection));
2259 }
2260 }
2261 else {
2262 if (single_object != nullptr) {
2263 BKE_reportf(op->reports,
2264 RPT_INFO,
2265 "%s moved to %s",
2266 single_object->id.name + 2,
2267 BKE_collection_ui_name_get(collection));
2268 }
2269 else {
2271 op->reports, RPT_INFO, "Objects moved to %s", BKE_collection_ui_name_get(collection));
2272 }
2273 }
2274
2277
2281
2282 return OPERATOR_FINISHED;
2283}
2284
2293
2295{
2296 int index = menu->index;
2298 Collection *collection = child->collection;
2299 MoveToCollectionData *submenu = MEM_new<MoveToCollectionData>(__func__);
2300 BLI_addtail(&menu->submenus, submenu);
2301 submenu->collection = collection;
2302 submenu->index = ++index;
2303 index = move_to_collection_menus_create(op, submenu);
2304 submenu->ot = op->type;
2305 }
2306 return index;
2307}
2308
2310{
2313 MEM_delete(submenu);
2314 }
2316}
2317
2319{
2320 if (*menu == nullptr) {
2321 return;
2322 }
2323
2325 MEM_delete(*menu);
2326 *menu = nullptr;
2327}
2328
2329static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *menu_v)
2330{
2331 MoveToCollectionData *menu = static_cast<MoveToCollectionData *>(menu_v);
2332 const char *name = BKE_collection_ui_name_get(menu->collection);
2333
2334 menu->ptr = layout->op(menu->ot,
2336 ICON_ADD,
2338 UI_ITEM_NONE);
2339 RNA_int_set(&menu->ptr, "collection_index", menu->index);
2340 RNA_boolean_set(&menu->ptr, "is_new", true);
2341
2342 layout->separator();
2343
2344 Scene *scene = CTX_data_scene(C);
2345 const int icon = (menu->collection == scene->master_collection) ?
2346 ICON_SCENE_DATA :
2348 PointerRNA op_ptr = layout->op(menu->ot, name, icon);
2349 RNA_int_set(&op_ptr, "collection_index", menu->index);
2350
2351 LISTBASE_FOREACH (MoveToCollectionData *, submenu, &menu->submenus) {
2352 move_to_collection_menus_items(layout, submenu);
2353 }
2354}
2355
2357{
2358 const int icon = UI_icon_color_from_collection(menu->collection);
2359
2360 if (BLI_listbase_is_empty(&menu->submenus)) {
2361 PointerRNA op_ptr = layout->op(menu->ot, menu->collection->id.name + 2, icon);
2362 RNA_int_set(&op_ptr, "collection_index", menu->index);
2363 }
2364 else {
2365 layout->menu_fn(menu->collection->id.name + 2, icon, move_to_collection_menu_create, menu);
2366 }
2367}
2368
2369/* This is allocated statically because we need this available for the menus creation callback. */
2371
2373 wmOperator *op,
2374 const wmEvent * /*event*/)
2375{
2376 Scene *scene = CTX_data_scene(C);
2377
2378 ListBase objects = selected_objects_get(C);
2379 if (BLI_listbase_is_empty(&objects)) {
2380 BKE_report(op->reports, RPT_ERROR, "No objects selected");
2381 return OPERATOR_CANCELLED;
2382 }
2383 BLI_freelistN(&objects);
2384
2385 /* Reset the menus data for the current master collection, and free previously allocated data. */
2387
2388 PropertyRNA *prop;
2389 prop = RNA_struct_find_property(op->ptr, "collection_index");
2390 if (RNA_property_is_set(op->ptr, prop)) {
2391 int collection_index = RNA_property_int_get(op->ptr, prop);
2392
2393 if (RNA_boolean_get(op->ptr, "is_new")) {
2394 prop = RNA_struct_find_property(op->ptr, "new_collection_name");
2395 if (!RNA_property_is_set(op->ptr, prop)) {
2396 char name[MAX_NAME];
2397 Collection *collection;
2398
2399 collection = BKE_collection_from_index(scene, collection_index);
2400 BKE_collection_new_name_get(collection, name);
2401
2402 RNA_property_string_set(op->ptr, prop, name);
2404 C, op, 200, IFACE_("Move to New Collection"), IFACE_("Create"));
2405 }
2406 }
2407 return move_to_collection_exec(C, op);
2408 }
2409
2410 Collection *master_collection = scene->master_collection;
2411
2412 /* We need the data to be allocated so it's available during menu drawing.
2413 * Technically we could use #wmOperator.customdata. However there is no free callback
2414 * called to an operator that exit with OPERATOR_INTERFACE to launch a menu.
2415 *
2416 * So we are left with a memory that will necessarily leak. It's a small leak though. */
2417 if (master_collection_menu == nullptr) {
2418 master_collection_menu = MEM_new<MoveToCollectionData>(
2419 "MoveToCollectionData menu - expected eventual memleak");
2420 }
2421
2422 master_collection_menu->collection = master_collection;
2423 master_collection_menu->ot = op->type;
2425
2426 uiPopupMenu *pup;
2427 uiLayout *layout;
2428
2429 /* Build the menus. */
2430 const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
2431 pup = UI_popup_menu_begin(C, title, ICON_NONE);
2432 layout = UI_popup_menu_layout(pup);
2433
2435
2437
2438 UI_popup_menu_end(C, pup);
2439
2440 return OPERATOR_INTERFACE;
2441}
2442
2444{
2445 PropertyRNA *prop;
2446
2447 /* identifiers */
2448 ot->name = "Move to Collection";
2449 ot->description = "Move objects to a collection";
2450 ot->idname = "OBJECT_OT_move_to_collection";
2451
2452 /* API callbacks. */
2454 ot->invoke = move_to_collection_invoke;
2456
2457 /* flags */
2458 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2459
2460 prop = RNA_def_int(ot->srna,
2461 "collection_index",
2464 INT_MAX,
2465 "Collection Index",
2466 "Index of the collection to move to",
2467 0,
2468 INT_MAX);
2470 prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
2472 prop = RNA_def_string(ot->srna,
2473 "new_collection_name",
2474 nullptr,
2475 MAX_NAME,
2476 "Name",
2477 "Name of the newly added collection");
2479 ot->prop = prop;
2480}
2481
2483{
2484 PropertyRNA *prop;
2485
2486 /* identifiers */
2487 ot->name = "Link to Collection";
2488 ot->description = "Link objects to a collection";
2489 ot->idname = "OBJECT_OT_link_to_collection";
2490
2491 /* API callbacks. */
2493 ot->invoke = move_to_collection_invoke;
2495
2496 /* flags */
2497 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2498
2499 prop = RNA_def_int(ot->srna,
2500 "collection_index",
2503 INT_MAX,
2504 "Collection Index",
2505 "Index of the collection to move to",
2506 0,
2507 INT_MAX);
2509 prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
2511 prop = RNA_def_string(ot->srna,
2512 "new_collection_name",
2513 nullptr,
2514 MAX_NAME,
2515 "Name",
2516 "Name of the newly added collection");
2518 ot->prop = prop;
2519}
2520
2522
2523} // 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)
Definition armature.cc:2866
Collection * BKE_collection_from_index(Scene *scene, int index)
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)
void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
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:5418
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
#define IDP_Float(prop)
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:766
#define IDP_Double(prop)
#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:2503
void id_us_plus(ID *id)
Definition lib_id.cc:353
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
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
void BKE_scene_object_base_flag_sync_from_base(Base *base)
Definition scene.cc:2870
#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 void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
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)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
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 DATA_(msgid)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
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:962
@ ID_RECALC_SELECT
Definition DNA_ID.h:1009
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:985
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1012
@ 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
@ ASSET_LIBRARY_ESSENTIALS
Object groups, one object can be in many groups at once.
@ COLLECTION_HIDE_VIEWPORT
@ BASE_HIDDEN
@ BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT
@ LAYER_COLLECTION_EXCLUDE
@ LAYER_COLLECTION_HIDE_VIEWPORT
@ LAYER_COLLECTION_HAS_OBJECTS
#define MESH_MAX_VERTS
@ eModifierFlag_PinLast
@ NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR
@ 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.
@ OB_PLAINAXES
@ OB_HIDE_VIEWPORT
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES_LEGACY
@ OB_CURVES
@ PARVERT1
@ PARVERT3
#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:867
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.
void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
Definition MOD_nodes.cc:448
@ PROP_FLOAT
Definition RNA_types.hh:152
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
@ PROP_ANGLE
Definition RNA_types.hh:240
#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)
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
#define NS_EDITMODE_MESH
Definition WM_types.hh:559
#define NS_EDITMODE_TEXT
Definition WM_types.hh:562
#define NC_GEOM
Definition WM_types.hh:390
@ KM_SHIFT
Definition WM_types.hh:275
#define ND_DRAW
Definition WM_types.hh:458
#define ND_OB_ACTIVE
Definition WM_types.hh:437
#define NS_EDITMODE_POINTCLOUD
Definition WM_types.hh:570
#define ND_DATA
Definition WM_types.hh:506
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NS_EDITMODE_CURVES
Definition WM_types.hh:568
#define ND_MODE
Definition WM_types.hh:442
#define ND_OB_SELECT
Definition WM_types.hh:439
#define NC_SCENE
Definition WM_types.hh:375
#define NS_EDITMODE_ARMATURE
Definition WM_types.hh:565
#define ND_OB_VISIBLE
Definition WM_types.hh:440
#define ND_LAYER_CONTENT
Definition WM_types.hh:450
#define ND_MODIFIER
Definition WM_types.hh:459
#define ND_POSE
Definition WM_types.hh:455
#define NS_MODE_OBJECT
Definition WM_types.hh:557
ReportList * reports
Definition WM_types.hh:1025
#define NS_EDITMODE_MBALL
Definition WM_types.hh:563
#define NS_EDITMODE_GREASE_PENCIL
Definition WM_types.hh:569
#define ND_TRANSFORM
Definition WM_types.hh:453
#define NS_EDITMODE_LATTICE
Definition WM_types.hh:564
#define ND_LAYER
Definition WM_types.hh:447
@ WM_OP_INVOKE_REGION_WIN
Definition WM_types.hh:239
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:238
#define ND_DRAW_ANIMVIZ
Definition WM_types.hh:470
#define NC_OBJECT
Definition WM_types.hh:376
#define NS_EDITMODE_CURVE
Definition WM_types.hh:560
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 const char * c_str() const
void append(const T &value)
bool is_empty() const
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:2262
void ED_curve_editfont_load(Object *obedit)
Definition editfont.cc:2301
void ED_curve_editfont_free(Object *obedit)
Definition editfont.cc:2333
uint col
#define input
#define select(A, B, C)
#define MEM_SAFE_FREE(v)
#define ID_IS_EDITABLE(_id)
#define MAX_NAME
#define ID_IS_OVERRIDE_LIBRARY(_id)
#define GS(a)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define G(x, y, z)
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)
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)
bool ensure_selection_domain(ToolSettings *ts, Object *object)
void OBJECT_OT_paths_update_visible(wmOperatorType *ot)
static void move_to_collection_menus_free(MoveToCollectionData **menu)
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:359
static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu)
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 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 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)
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 int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
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 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 void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *menu_v)
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)
static void move_to_collection_menus_free_recursive(MoveToCollectionData *menu)
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)
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)
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
static MoveToCollectionData * master_collection_menu
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:97
bool ED_object_posemode_exit_ex(Main *bmain, Object *ob)
Definition pose_edit.cc:112
bool ED_object_posemode_exit(bContext *C, Object *ob)
Definition pose_edit.cc:125
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)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
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)
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:146
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
struct LibraryWeakReference * library_weak_reference
Definition DNA_ID.h:491
struct EditLatt * editlatt
ListBase layer_collections
unsigned short local_collections_bits
char library_id_name[66]
Definition DNA_ID.h:534
void * first
bool is_memfile_undo_written
Definition BKE_main.hh:180
ListBase objects
Definition BKE_main.hh:247
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
bAnimVizSettings avs
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void menu_fn(blender::StringRefNull name, int icon, uiMenuCreateFunc func, void *arg)
uiLayout & row(bool align)
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)
wmEventModifierFlag modifier
Definition WM_types.hh:771
const char * name
Definition WM_types.hh:1030
const char * translation_context
Definition WM_types.hh:1034
struct ReportList * reports
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_autosave_write(wmWindowManager *wm, Main *bmain)
Definition wm_files.cc:2339
bool WM_autosave_is_scheduled(wmWindowManager *wm)
Definition wm_files.cc:2334
PointerRNA * ptr
Definition wm_files.cc:4226
wmOperatorType * ot
Definition wm_files.cc:4225
#define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_)
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)
void WM_toolsystem_update_from_context_view3d(bContext *C)
uint8_t flag
Definition wm_window.cc:139