Blender V4.3
object_modifier.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
9#include <cmath>
10#include <cstdio>
11#include <cstdlib>
12
13#include "CLG_log.h"
14
15#include "MEM_guardedalloc.h"
16
17#include "DNA_anim_types.h"
18#include "DNA_armature_types.h"
19#include "DNA_array_utils.hh"
20#include "DNA_curve_types.h"
21#include "DNA_defaults.h"
23#include "DNA_fluid_types.h"
24#include "DNA_key_types.h"
25#include "DNA_lattice_types.h"
26#include "DNA_material_types.h"
27#include "DNA_mesh_types.h"
28#include "DNA_meshdata_types.h"
31#include "DNA_scene_types.h"
32#include "DNA_space_types.h"
33
34#include "BLI_bitmap.h"
35#include "BLI_listbase.h"
36#include "BLI_path_utils.hh"
37#include "BLI_string.h"
38#include "BLI_string_utf8.h"
39#include "BLI_string_utils.hh"
40#include "BLI_utildefines.h"
41
42#include "BKE_animsys.h"
43#include "BKE_armature.hh"
44#include "BKE_context.hh"
45#include "BKE_curve.hh"
46#include "BKE_curves.h"
47#include "BKE_curves.hh"
48#include "BKE_displist.h"
49#include "BKE_editmesh.hh"
50#include "BKE_effect.h"
51#include "BKE_geometry_set.hh"
52#include "BKE_global.hh"
53#include "BKE_grease_pencil.hh"
54#include "BKE_idprop.hh"
55#include "BKE_key.hh"
56#include "BKE_lattice.hh"
57#include "BKE_layer.hh"
58#include "BKE_lib_id.hh"
59#include "BKE_main.hh"
60#include "BKE_material.h"
61#include "BKE_mball.hh"
62#include "BKE_mesh.hh"
63#include "BKE_mesh_mapping.hh"
64#include "BKE_mesh_runtime.hh"
65#include "BKE_modifier.hh"
66#include "BKE_multires.hh"
67#include "BKE_object.hh"
68#include "BKE_object_deform.h"
69#include "BKE_object_types.hh"
70#include "BKE_ocean.h"
71#include "BKE_paint.hh"
72#include "BKE_particle.h"
73#include "BKE_pointcloud.hh"
74#include "BKE_report.hh"
75#include "BKE_scene.hh"
76#include "BKE_softbody.h"
77#include "BKE_volume.hh"
78
79#include "BLT_translation.hh"
80
81#include "DEG_depsgraph.hh"
84
85#include "BLT_translation.hh"
86
87#include "RNA_access.hh"
88#include "RNA_define.hh"
89#include "RNA_enum_types.hh"
90#include "RNA_prototypes.hh"
91
92#include "ED_armature.hh"
93#include "ED_object.hh"
94#include "ED_object_vgroup.hh"
95#include "ED_screen.hh"
96
98
99#include "GEO_merge_layers.hh"
100
101#include "UI_interface.hh"
102
103#include "WM_api.hh"
104#include "WM_types.hh"
105
106#include "object_intern.hh"
107
108namespace blender::ed::object {
109
110static CLG_LogRef LOG = {"ed.object"};
111
113
114/* ------------------------------------------------------------------- */
119{
122 BKE_object_eval_reset(ob_eval);
123 if (ob->type == OB_MESH) {
125 depsgraph, scene_eval, ob_eval, &CD_MASK_DERIVEDMESH);
126 BKE_id_free(nullptr, mesh_eval);
127 }
128 else if (ob->type == OB_LATTICE) {
129 BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval);
130 }
131 else if (ob->type == OB_MBALL) {
132 BKE_mball_data_update(depsgraph, scene_eval, ob_eval);
133 }
134 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) {
135 BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false);
136 }
137 else if (ob->type == OB_CURVES) {
138 BKE_curves_data_update(depsgraph, scene_eval, ob);
139 }
140 else if (ob->type == OB_POINTCLOUD) {
141 BKE_pointcloud_data_update(depsgraph, scene_eval, ob);
142 }
143 else if (ob->type == OB_VOLUME) {
144 BKE_volume_data_update(depsgraph, scene_eval, ob);
145 }
146}
147
149 Object *object,
150 ModifierData *md)
151{
153 const int mode = md_eval->mode;
154 md_eval->mode |= eModifierMode_Realtime;
156 md_eval->mode = mode;
157}
158
160 ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
161{
162 ModifierData *new_md = nullptr;
164
165 /* Check compatibility of modifier [#25291, #50373]. */
167 BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
168 return nullptr;
169 }
170
171 if (mti->flags & eModifierTypeFlag_Single) {
173 BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
174 return nullptr;
175 }
176 }
177
178 if (type == eModifierType_ParticleSystem) {
179 /* don't need to worry about the new modifier's name, since that is set to the number
180 * of particle systems which shouldn't have too many duplicates
181 */
182 new_md = object_add_particle_system(bmain, scene, ob, name);
183 }
184 else {
185 /* get new modifier data to add */
186 new_md = BKE_modifier_new(type);
187
188 ModifierData *next_md = nullptr;
190 if (md->flag & eModifierFlag_PinLast) {
191 next_md = md;
192 }
193 else {
194 break;
195 }
196 }
198 next_md = static_cast<ModifierData *>(ob->modifiers.first);
199
200 while (next_md && BKE_modifier_get_info((ModifierType)next_md->type)->type ==
202 {
203 if (next_md->next && (next_md->next->flag & eModifierFlag_PinLast) != 0) {
204 break;
205 }
206 next_md = next_md->next;
207 }
208 }
209 BLI_insertlinkbefore(&ob->modifiers, next_md, new_md);
211
212 if (name) {
213 STRNCPY_UTF8(new_md->name, name);
214 }
215
216 /* make sure modifier data has unique name */
217
219
220 /* special cases */
221 if (type == eModifierType_Softbody) {
222 if (!ob->soft) {
223 ob->soft = sbNew();
225 }
226 }
227 else if (type == eModifierType_Collision) {
228 if (!ob->pd) {
229 ob->pd = BKE_partdeflect_new(0);
230 }
231
232 ob->pd->deflect = 1;
233 }
234 else if (type == eModifierType_Surface) {
235 /* pass */
236 }
237 else if (type == eModifierType_Multires) {
238 /* set totlvl from existing MDISPS layer if object already had it */
240
241 if (ob->mode & OB_MODE_SCULPT) {
242 /* ensure that grid paint mask layer is created */
243 BKE_sculpt_mask_layers_ensure(nullptr, nullptr, ob, (MultiresModifierData *)new_md);
244 }
245 }
246 else if (type == eModifierType_Skin) {
247 /* ensure skin-node customdata exists */
248 BKE_mesh_ensure_skin_customdata(static_cast<Mesh *>(ob->data));
249 }
250 }
251
253
256
257 return new_md;
258}
259
260/* Return true if the object has a modifier of type 'type' other than
261 * the modifier pointed to be 'exclude', otherwise returns false. */
262static bool object_has_modifier(const Object *ob, const ModifierData *exclude, ModifierType type)
263{
265 if ((md != exclude) && (md->type == type)) {
266 return true;
267 }
268 }
269
270 return false;
271}
272
273bool iter_other(Main *bmain,
274 Object *orig_ob,
275 const bool include_orig,
276 bool (*callback)(Object *ob, void *callback_data),
277 void *callback_data)
278{
279 ID *ob_data_id = static_cast<ID *>(orig_ob->data);
280 int users = ob_data_id->us;
281
282 if (ob_data_id->flag & ID_FLAG_FAKEUSER) {
283 users--;
284 }
285
286 /* First check that the object's data has multiple users */
287 if (users > 1) {
288 Object *ob;
289 int totfound = include_orig ? 0 : 1;
290
291 for (ob = static_cast<Object *>(bmain->objects.first); ob && totfound < users;
292 ob = reinterpret_cast<Object *>(ob->id.next))
293 {
294 if (((ob != orig_ob) || include_orig) && (ob->data == orig_ob->data)) {
295 if (callback(ob, callback_data)) {
296 return true;
297 }
298
299 totfound++;
300 }
301 }
302 }
303 else if (include_orig) {
304 return callback(orig_ob, callback_data);
305 }
306
307 return false;
308}
309
310static bool object_has_modifier_cb(Object *ob, void *data)
311{
312 ModifierType type = *((ModifierType *)data);
313
314 return object_has_modifier(ob, nullptr, type);
315}
316
317bool multires_update_totlevels(Object *ob, void *totlevel_v)
318{
319 int totlevel = *((char *)totlevel_v);
320
322 if (md->type == eModifierType_Multires) {
323 multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
325 }
326 }
327 return false;
328}
329
330/* Return true if no modifier of type 'type' other than 'exclude' */
332 Object *ob,
333 ModifierData *exclude,
334 ModifierType type)
335{
336 return (!object_has_modifier(ob, exclude, type) &&
337 !iter_other(bmain, ob, false, object_has_modifier_cb, &type));
338}
339
341 Main *bmain, Scene *scene, Object *ob, ModifierData *md, bool *r_sort_depsgraph)
342{
343 /* It seems on rapid delete it is possible to
344 * get called twice on same modifier, so make
345 * sure it is in list. */
346 if (BLI_findindex(&ob->modifiers, md) == -1) {
347 return false;
348 }
349
350 /* special cases */
352 object_remove_particle_system(bmain, scene, ob, ((ParticleSystemModifierData *)md)->psys);
353 return true;
354 }
355
356 if (md->type == eModifierType_Softbody) {
357 if (ob->soft) {
358 sbFree(ob);
359 ob->softflag = 0; /* TODO(Sybren): this should probably be moved into sbFree() */
360 }
361 }
362 else if (md->type == eModifierType_Collision) {
363 if (ob->pd) {
364 ob->pd->deflect = 0;
365 }
366
367 *r_sort_depsgraph = true;
368 }
369 else if (md->type == eModifierType_Surface) {
370 *r_sort_depsgraph = true;
371 }
372 else if (md->type == eModifierType_Multires) {
373 /* Delete MDisps layer if not used by another multires modifier */
375 multires_customdata_delete(static_cast<Mesh *>(ob->data));
376 }
377 }
378 else if (md->type == eModifierType_Skin) {
379 /* Delete MVertSkin layer if not used by another skin modifier */
382 }
383 }
384
387 {
388 ob->mode &= ~OB_MODE_PARTICLE_EDIT;
389 }
390
394
395 return true;
396}
397
398bool modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
399{
400 bool sort_depsgraph = false;
401
402 bool ok = object_modifier_remove(bmain, scene, ob, md, &sort_depsgraph);
403
404 if (!ok) {
405 BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
406 return false;
407 }
408
411
412 return true;
413}
414
415void modifiers_clear(Main *bmain, Scene *scene, Object *ob)
416{
417 ModifierData *md = static_cast<ModifierData *>(ob->modifiers.first);
418 bool sort_depsgraph = false;
419
420 if (!md) {
421 return;
422 }
423
424 while (md) {
425 ModifierData *next_md = md->next;
426
427 object_modifier_remove(bmain, scene, ob, md, &sort_depsgraph);
428
429 md = next_md;
430 }
431
434}
435
437 eReportType error_type,
438 ModifierData *md,
439 ModifierData *md_prev)
440{
441 if (md_prev) {
442 if (md->flag & eModifierFlag_PinLast && !(md_prev->flag & eModifierFlag_PinLast)) {
443 return false;
444 }
446
449
451 BKE_report(reports, error_type, "Cannot move above a modifier requiring original data");
452 return false;
453 }
454 }
455 }
456 else {
457 BKE_report(reports, error_type, "Cannot move modifier beyond the start of the list");
458 return false;
459 }
460
461 return true;
462}
463
464bool modifier_move_up(ReportList *reports, eReportType error_type, Object *ob, ModifierData *md)
465{
466 if (object_modifier_check_move_before(reports, error_type, md, md->prev)) {
468 return true;
469 }
470
471 return false;
472}
473
475 eReportType error_type,
476 ModifierData *md,
477 ModifierData *md_next)
478{
479 if (md_next) {
480 if (md_next->flag & eModifierFlag_PinLast && !(md->flag & eModifierFlag_PinLast)) {
481 return false;
482 }
484
487
488 if (nmti->type != ModifierTypeType::OnlyDeform) {
489 BKE_report(reports, error_type, "Cannot move beyond a non-deforming modifier");
490 return false;
491 }
492 }
493 }
494 else {
495 BKE_report(reports, error_type, "Cannot move modifier beyond the end of the list");
496 return false;
497 }
498
499 return true;
500}
501
502bool modifier_move_down(ReportList *reports, eReportType error_type, Object *ob, ModifierData *md)
503{
504 if (object_modifier_check_move_after(reports, error_type, md, md->next)) {
506 return true;
507 }
508
509 return false;
510}
511
513 eReportType error_type,
514 Object *ob,
515 ModifierData *md,
516 const int index,
517 bool allow_partial)
518{
519 BLI_assert(md != nullptr);
520
521 if (index < 0 || index >= BLI_listbase_count(&ob->modifiers)) {
522 BKE_report(reports, error_type, "Cannot move modifier beyond the end of the stack");
523 return false;
524 }
525
526 int md_index = BLI_findindex(&ob->modifiers, md);
527 BLI_assert(md_index != -1);
528
529 if (md_index < index) {
530 /* Move modifier down in list. */
531 ModifierData *md_target = md;
532
533 for (; md_index < index; md_index++, md_target = md_target->next) {
534 if (!object_modifier_check_move_after(reports, error_type, md, md_target->next)) {
535 if (!allow_partial || md == md_target) {
536 return false;
537 }
538
539 break;
540 }
541 }
542
543 BLI_assert(md != md_target && md_target);
544
545 BLI_remlink(&ob->modifiers, md);
546 BLI_insertlinkafter(&ob->modifiers, md_target, md);
547 }
548 else if (md_index > index) {
549 /* Move modifier up in list. */
550 ModifierData *md_target = md;
551
552 for (; md_index > index; md_index--, md_target = md_target->prev) {
553 if (!object_modifier_check_move_before(reports, error_type, md, md_target->prev)) {
554 if (!allow_partial || md == md_target) {
555 return false;
556 }
557
558 break;
559 }
560 }
561
562 BLI_assert(md != md_target && md_target);
563
564 BLI_remlink(&ob->modifiers, md);
565 BLI_insertlinkbefore(&ob->modifiers, md_target, md);
566 }
567 else {
568 return true;
569 }
570
571 /* NOTE: Dependency graph only uses modifier nodes for visibility updates, and exact order of
572 * modifier nodes in the graph does not matter. */
573
576
577 return true;
578}
579
580void modifier_link(bContext *C, Object *ob_dst, Object *ob_src)
581{
582 BKE_object_link_modifiers(ob_dst, ob_src);
585
586 Main *bmain = CTX_data_main(C);
588}
589
591 const Scene *scene,
592 const Object *ob_src,
593 const ModifierData *md,
594 Object *ob_dst,
595 ReportList *reports)
596{
598
599 BLI_assert(ob_src != ob_dst);
600
601 /* Checked in #BKE_object_copy_modifier, but check here too so we can give a better message. */
603 BKE_reportf(reports,
605 "Object '%s' does not support %s modifiers",
606 ob_dst->id.name + 2,
607 RPT_(mti->name));
608 return false;
609 }
610
611 if (mti->flags & eModifierTypeFlag_Single) {
612 if (BKE_modifiers_findby_type(ob_dst, (ModifierType)md->type)) {
613 BKE_reportf(reports,
615 "Modifier can only be added once to object '%s'",
616 ob_dst->id.name + 2);
617 return false;
618 }
619 }
620
621 if (!BKE_object_copy_modifier(bmain, scene, ob_dst, ob_src, md)) {
622 BKE_reportf(reports,
623 RPT_ERROR,
624 "Copying modifier '%s' to object '%s' failed",
625 md->name,
626 ob_dst->id.name + 2);
627 return false;
628 }
629
633 return true;
634}
635
637 Main *bmain,
638 Depsgraph *depsgraph,
639 Scene *scene,
640 ViewLayer *view_layer,
641 Object *ob,
642 ModifierData *md)
643{
644 int cvert = 0;
645
647 return false;
648 }
649 if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
650 return false;
651 }
652
653 ParticleSystem *psys_orig = ((ParticleSystemModifierData *)md)->psys;
654 ParticleSettings *part = psys_orig->part;
655
656 if (part->ren_as != PART_DRAW_PATH) {
657 return false;
658 }
659 ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys_orig);
660 if (psys_eval->pathcache == nullptr) {
661 return false;
662 }
663
664 int part_num = psys_eval->totcached;
665 int child_num = psys_eval->totchildcache;
666
667 if (child_num && (part->draw & PART_DRAW_PARENT) == 0) {
668 part_num = 0;
669 }
670
671 /* count */
672 int verts_num = 0, edges_num = 0;
673 ParticleCacheKey **cache = psys_eval->pathcache;
674 for (int a = 0; a < part_num; a++) {
675 ParticleCacheKey *key = cache[a];
676
677 if (key->segments > 0) {
678 verts_num += key->segments + 1;
679 edges_num += key->segments;
680 }
681 }
682
683 cache = psys_eval->childcache;
684 for (int a = 0; a < child_num; a++) {
685 ParticleCacheKey *key = cache[a];
686
687 if (key->segments > 0) {
688 verts_num += key->segments + 1;
689 edges_num += key->segments;
690 }
691 }
692
693 if (verts_num == 0) {
694 return false;
695 }
696
697 /* add new mesh */
698 Object *obn = BKE_object_add(bmain, scene, view_layer, OB_MESH, nullptr);
699 Mesh *mesh = static_cast<Mesh *>(obn->data);
700
701 mesh->verts_num = verts_num;
702 mesh->edges_num = edges_num;
703
705 &mesh->vert_data, CD_PROP_FLOAT3, CD_CONSTRUCT, verts_num, "position");
707 &mesh->edge_data, CD_PROP_INT32_2D, CD_CONSTRUCT, mesh->edges_num, ".edge_verts");
708 CustomData_add_layer(&mesh->fdata_legacy, CD_MFACE, CD_SET_DEFAULT, 0);
709
710 MutableSpan<float3> positions = mesh->vert_positions_for_write();
711 MutableSpan<int2> edges = mesh->edges_for_write();
712
713 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
714 bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
715 ".select_vert", bke::AttrDomain::Point);
716
717 int edge_index = 0;
718
719 /* copy coordinates */
720 int vert_index = 0;
721 cache = psys_eval->pathcache;
722 for (int a = 0; a < part_num; a++) {
723 ParticleCacheKey *key = cache[a];
724 int kmax = key->segments;
725 for (int k = 0; k <= kmax; k++, key++, cvert++, vert_index++) {
726 positions[vert_index] = key->co;
727 if (k) {
728 edges[edge_index] = int2(cvert - 1, cvert);
729 edge_index++;
730 }
731 else {
732 /* cheap trick to select the roots */
733 select_vert.span[vert_index] = true;
734 }
735 }
736 }
737
738 cache = psys_eval->childcache;
739 for (int a = 0; a < child_num; a++) {
740 ParticleCacheKey *key = cache[a];
741 int kmax = key->segments;
742 for (int k = 0; k <= kmax; k++, key++, cvert++, vert_index++) {
743 copy_v3_v3(positions[vert_index], key->co);
744 if (k) {
745 edges[edge_index] = int2(cvert - 1, cvert);
746 edge_index++;
747 }
748 else {
749 /* cheap trick to select the roots */
750 select_vert.span[vert_index] = true;
751 }
752 }
753 }
754
755 select_vert.finish();
756
758
759 return true;
760}
761
762static void add_shapekey_layers(Mesh &mesh_dest, const Mesh &mesh_src)
763{
764 if (!mesh_src.key) {
765 return;
766 }
767 int i;
768 LISTBASE_FOREACH_INDEX (const KeyBlock *, kb, &mesh_src.key->block, i) {
769 void *array;
770 if (mesh_src.verts_num != kb->totelem) {
772 "vertex size mismatch (Mesh '%s':%d != KeyBlock '%s':%d)",
773 mesh_src.id.name + 2,
774 mesh_src.verts_num,
775 kb->name,
776 kb->totelem);
777 array = MEM_calloc_arrayN(size_t(mesh_src.verts_num), sizeof(float[3]), __func__);
778 }
779 else {
780 array = MEM_malloc_arrayN(size_t(mesh_src.verts_num), sizeof(float[3]), __func__);
781 memcpy(array, kb->data, sizeof(float[3]) * size_t(mesh_src.verts_num));
782 }
783
785 &mesh_dest.vert_data, CD_SHAPEKEY, array, mesh_dest.verts_num, nullptr);
786 const int ci = CustomData_get_layer_index_n(&mesh_dest.vert_data, CD_SHAPEKEY, i);
787
788 mesh_dest.vert_data.layers[ci].uid = kb->uid;
789 }
790}
791
798 Scene *scene,
799 Object *ob_eval,
800 ModifierData *md_eval,
801 const bool use_virtual_modifiers,
802 const bool build_shapekey_layers,
803 ReportList *reports)
804{
805 Mesh *mesh = ob_eval->runtime->data_orig ?
806 reinterpret_cast<Mesh *>(ob_eval->runtime->data_orig) :
807 reinterpret_cast<Mesh *>(ob_eval->data);
809 const ModifierEvalContext mectx = {depsgraph, ob_eval, MOD_APPLY_TO_ORIGINAL};
810
811 if (!(md_eval->mode & eModifierMode_Realtime)) {
812 return nullptr;
813 }
814
815 if (mti->is_disabled && mti->is_disabled(scene, md_eval, false)) {
816 return nullptr;
817 }
818
819 if (build_shapekey_layers && mesh->key) {
820 if (KeyBlock *kb = static_cast<KeyBlock *>(
821 BLI_findlink(&mesh->key->block, ob_eval->shapenr - 1)))
822 {
824 kb,
825 reinterpret_cast<float(*)[3]>(mesh->vert_positions_for_write().data()),
826 mesh->verts_num);
827 }
828 }
829
830 Mesh *mesh_temp = reinterpret_cast<Mesh *>(
831 BKE_id_copy_ex(nullptr, &mesh->id, nullptr, LIB_ID_COPY_LOCALIZE));
832 MutableSpan<float3> deformedVerts = mesh_temp->vert_positions_for_write();
833
834 if (use_virtual_modifiers) {
835 VirtualModifierData virtual_modifier_data;
836 for (ModifierData *md_eval_virt =
837 BKE_modifiers_get_virtual_modifierlist(ob_eval, &virtual_modifier_data);
838 md_eval_virt && (md_eval_virt != ob_eval->modifiers.first);
839 md_eval_virt = md_eval_virt->next)
840 {
841 if (!BKE_modifier_is_enabled(scene, md_eval_virt, eModifierMode_Realtime)) {
842 continue;
843 }
844 /* All virtual modifiers are deform modifiers. */
845 const ModifierTypeInfo *mti_virt = BKE_modifier_get_info(ModifierType(md_eval_virt->type));
847 if (mti_virt->type != ModifierTypeType::OnlyDeform) {
848 continue;
849 }
850
851 mti_virt->deform_verts(md_eval_virt, &mectx, mesh_temp, deformedVerts);
852 }
853 }
854
855 Mesh *result = nullptr;
857 result = mesh_temp;
858 mti->deform_verts(md_eval, &mectx, result, deformedVerts);
859 result->tag_positions_changed();
860
861 if (build_shapekey_layers) {
862 add_shapekey_layers(*result, *mesh);
863 }
864 }
865 else {
866 if (build_shapekey_layers) {
867 add_shapekey_layers(*mesh_temp, *mesh);
868 }
869
870 if (mti->modify_geometry_set) {
873 mti->modify_geometry_set(md_eval, &mectx, &geometry_set);
874 if (!geometry_set.has_mesh()) {
875 BKE_report(reports, RPT_ERROR, "Evaluated geometry from modifier does not contain a mesh");
876 return nullptr;
877 }
878 result = geometry_set.get_component_for_write<bke::MeshComponent>().release();
879 }
880 else {
881 result = mti->modify_mesh(md_eval, &mectx, mesh_temp);
882 if (mesh_temp != result) {
883 BKE_id_free(nullptr, mesh_temp);
884 }
885 }
886 }
887
888 return result;
889}
890
891static bool modifier_apply_shape(Main *bmain,
892 ReportList *reports,
893 Depsgraph *depsgraph,
894 Scene *scene,
895 Object *ob,
896 ModifierData *md_eval)
897{
899
900 if (mti->is_disabled && mti->is_disabled(scene, md_eval, false)) {
901 BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
902 return false;
903 }
904
905 /* We could investigate using the #CD_ORIGINDEX layer
906 * to support other kinds of modifiers besides deforming modifiers.
907 * as this is done in many other places, see: #BKE_mesh_foreach_mapped_vert_coords_get.
908 *
909 * This isn't high priority in practice since most modifiers users
910 * want to apply as a shape are deforming modifiers.
911 *
912 * If a compelling use-case comes up where we want to support other kinds of modifiers
913 * we can look into supporting them. */
914
915 if (ob->type == OB_MESH) {
916 Mesh *mesh = static_cast<Mesh *>(ob->data);
917 Key *key = mesh->key;
918
920 BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
921 return false;
922 }
923
927 md_eval,
928 true,
929 false,
930 reports);
931 if (!mesh_applied) {
932 BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
933 return false;
934 }
935
936 if (key == nullptr) {
937 key = mesh->key = BKE_key_add(bmain, (ID *)mesh);
938 key->type = KEY_RELATIVE;
939 /* if that was the first key block added, then it was the basis.
940 * Initialize it with the mesh, and add another for the modifier */
941 KeyBlock *kb = BKE_keyblock_add(key, nullptr);
942 BKE_keyblock_convert_from_mesh(mesh, key, kb);
943 }
944
945 KeyBlock *kb = BKE_keyblock_add(key, md_eval->name);
946 BKE_mesh_nomain_to_meshkey(mesh_applied, mesh, kb);
947
948 BKE_id_free(nullptr, mesh_applied);
949 }
950 else {
951 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
952 return false;
953 }
954 return true;
955}
956
957static bool meta_data_matches(const std::optional<bke::AttributeMetaData> meta_data,
958 const AttrDomainMask domains,
959 const eCustomDataMask types)
960{
961 if (!meta_data) {
962 return false;
963 }
964 if (!(ATTR_DOMAIN_AS_MASK(meta_data->domain) & domains)) {
965 return false;
966 }
967 if (!(CD_TYPE_AS_MASK(meta_data->data_type) & types)) {
968 return false;
969 }
970 return true;
971}
972
974{
975 bke::AttributeAccessor attributes = mesh.attributes();
976 if (!meta_data_matches(attributes.lookup_meta_data(mesh.active_color_attribute),
979 {
980 MEM_SAFE_FREE(mesh.active_color_attribute);
981 }
982 if (!meta_data_matches(attributes.lookup_meta_data(mesh.default_color_attribute),
985 {
986 MEM_SAFE_FREE(mesh.default_color_attribute);
987 }
988}
989
990static void apply_eval_grease_pencil_data(const GreasePencil &src_grease_pencil,
991 const int eval_frame,
992 const IndexMask &orig_layers,
993 GreasePencil &orig_grease_pencil)
994{
995 using namespace bke;
996 using namespace bke::greasepencil;
997 /* Build a set of pointers to the layers that we want to apply. */
998 Set<const Layer *> orig_layers_to_apply;
999 orig_layers.foreach_index([&](const int layer_i) {
1000 const Layer &layer = orig_grease_pencil.layer(layer_i);
1001 orig_layers_to_apply.add(&layer);
1002 });
1003
1004 /* Ensure that the layer names are unique by merging layers with the same name. */
1005 const int old_layers_num = src_grease_pencil.layers().size();
1006 Vector<Vector<int>> layers_map;
1007 Map<StringRef, int> new_layer_index_by_name;
1008 for (const int layer_i : IndexRange(old_layers_num)) {
1009 const Layer &layer = src_grease_pencil.layer(layer_i);
1010 const int new_layer_index = new_layer_index_by_name.lookup_or_add_cb(
1011 layer.name(), [&]() { return layers_map.append_and_get_index_as(); });
1012 layers_map[new_layer_index].append(layer_i);
1013 }
1014 GreasePencil &merged_layers_grease_pencil = *geometry::merge_layers(
1015 src_grease_pencil, layers_map, {});
1016
1017 Map<const Layer *, const Layer *> eval_to_orig_layer_map;
1018 {
1019 /* Keep track of the last layer in each group to ensure layers get added to the same groups in
1020 * the same order as the original. This is better than using the layer cache since it avoids
1021 * updating the cache every time a new layer is added. */
1022 Map<const LayerGroup *, TreeNode *> last_node_by_group;
1023 /* Set of orig layers that require the drawing on `eval_frame` to be cleared. These are layers
1024 * that existed in original geometry but were removed during the modifier evaluation. */
1025 Set<Layer *> orig_layers_to_clear(orig_grease_pencil.layers_for_write());
1026 for (const TreeNode *node_eval : merged_layers_grease_pencil.nodes()) {
1027 /* Check if the original geometry has a layer with the same name. */
1028 TreeNode *node_orig = orig_grease_pencil.find_node_by_name(node_eval->name());
1029
1030 BLI_assert(node_eval != nullptr);
1031 if (node_eval->is_layer()) {
1032 /* If the orig layer isn't valid then a new layer with a unique name will be generated. */
1033 const bool has_valid_orig_layer = (node_orig != nullptr && node_orig->is_layer());
1034 if (!has_valid_orig_layer) {
1035 /* Note: This name might be empty! This has to be resolved at a later stage! */
1036 Layer &layer_orig = orig_grease_pencil.add_layer(node_eval->name(), true);
1037 orig_layers_to_apply.add(&layer_orig);
1038 /* Make sure to add a new keyframe with a new drawing. */
1039 orig_grease_pencil.insert_frame(layer_orig, eval_frame);
1040 node_orig = &layer_orig.as_node();
1041 }
1042 BLI_assert(node_orig != nullptr);
1043 Layer &layer_orig = node_orig->as_layer();
1044 /* This layer has a matching evaluated layer, so don't clear its keyframe. */
1045 orig_layers_to_clear.remove(&layer_orig);
1046 /* Only map layers in `eval_to_orig_layer_map` that we want to apply. */
1047 if (orig_layers_to_apply.contains(&layer_orig)) {
1048 /* Copy layer properties to original geometry. */
1049 const Layer &layer_eval = node_eval->as_layer();
1050 layer_orig.opacity = layer_eval.opacity;
1051 layer_orig.set_local_transform(layer_eval.local_transform());
1052
1053 /* Add new mapping for layer_eval -> layer_orig*/
1054 eval_to_orig_layer_map.add_new(&layer_eval, &layer_orig);
1055 }
1056 }
1057
1058 /* Insert the updated node after the last node in the same group.
1059 * This keeps the layer order consistent. */
1060 if (node_orig && node_orig->parent_group()) {
1061 last_node_by_group.add_or_modify(
1062 node_orig->parent_group(),
1063 [&](TreeNode **node_ptr) {
1064 /* First layer in the group, set the last-layer pointer. */
1065 *node_ptr = node_orig;
1066 },
1067 [&](TreeNode **node_ptr) {
1068 orig_grease_pencil.move_node_after(*node_orig, **node_ptr);
1069 *node_ptr = node_orig;
1070 });
1071 }
1072 }
1073
1074 /* Clear the keyframe of all the original layers that don't have a matching evaluated layer,
1075 * e.g. the ones that were "deleted" in the modifier. */
1076 for (Layer *layer_orig : orig_layers_to_clear) {
1077 /* Try inserting a frame. */
1078 Drawing *drawing_orig = orig_grease_pencil.insert_frame(*layer_orig, eval_frame);
1079 if (drawing_orig == nullptr) {
1080 /* If that fails, get the drawing for this frame. */
1081 drawing_orig = orig_grease_pencil.get_drawing_at(*layer_orig, eval_frame);
1082 }
1083 /* Clear the existing drawing. */
1084 drawing_orig->strokes_for_write() = {};
1085 drawing_orig->tag_topology_changed();
1086 }
1087 }
1088
1089 /* Update the drawings. */
1090 VectorSet<Drawing *> all_updated_drawings;
1091 for (auto [layer_eval, layer_orig] : eval_to_orig_layer_map.items()) {
1092 const Drawing *drawing_eval = merged_layers_grease_pencil.get_drawing_at(*layer_eval,
1093 eval_frame);
1094 Drawing *drawing_orig = orig_grease_pencil.get_drawing_at(*layer_orig, eval_frame);
1095 if (drawing_orig && drawing_eval) {
1096 /* Write the data to the original drawing. */
1097 drawing_orig->strokes_for_write() = std::move(drawing_eval->strokes());
1098 /* Anonymous attributes shouldn't be available on original geometry. */
1100 drawing_orig->tag_topology_changed();
1101 all_updated_drawings.add_new(drawing_orig);
1102 }
1103 }
1104
1105 /* Get the original material pointers from the result geometry. */
1106 VectorSet<Material *> original_materials;
1107 const Span<Material *> eval_materials = Span{merged_layers_grease_pencil.material_array,
1108 merged_layers_grease_pencil.material_array_num};
1109 for (Material *eval_material : eval_materials) {
1110 if (eval_material != nullptr && eval_material->id.orig_id != nullptr) {
1111 original_materials.add_new(reinterpret_cast<Material *>(eval_material->id.orig_id));
1112 }
1113 }
1114
1115 /* Build material indices mapping. This maps the materials indices on the original geometry to
1116 * the material indices used in the result geometry. The material indices for the drawings in the
1117 * result geometry are already correct, but this might not be the case for all drawings in the
1118 * original geometry (like for drawings that are not visible on the frame that the modifier is
1119 * being applied on). */
1120 Array<int> material_indices_map(orig_grease_pencil.material_array_num);
1121 for (const int mat_i : IndexRange(orig_grease_pencil.material_array_num)) {
1122 Material *material = orig_grease_pencil.material_array[mat_i];
1123 const int map_index = original_materials.index_of_try(material);
1124 if (map_index != -1) {
1125 material_indices_map[mat_i] = map_index;
1126 }
1127 }
1128
1129 /* Remap material indices for all other drawings. */
1130 if (!material_indices_map.is_empty() &&
1131 !array_utils::indices_are_range(material_indices_map,
1132 IndexRange(orig_grease_pencil.material_array_num)))
1133 {
1134 for (GreasePencilDrawingBase *base : orig_grease_pencil.drawings()) {
1135 if (base->type != GP_DRAWING) {
1136 continue;
1137 }
1138 Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
1139 if (all_updated_drawings.contains(&drawing)) {
1140 /* Skip remapping drawings that already have been updated. */
1141 continue;
1142 }
1143 MutableAttributeAccessor attributes = drawing.strokes_for_write().attributes_for_write();
1144 if (!attributes.contains("material_index")) {
1145 continue;
1146 }
1147 SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
1148 "material_index", AttrDomain::Curve);
1149 for (int &material_index : material_indices.span) {
1150 if (material_index >= 0 && material_index < material_indices_map.size()) {
1151 material_index = material_indices_map[material_index];
1152 }
1153 }
1154 material_indices.finish();
1155 }
1156 }
1157
1158 /* Convert the layer map into an index mapping. */
1159 Map<int, int> eval_to_orig_layer_indices_map;
1160 for (const int layer_eval_i : merged_layers_grease_pencil.layers().index_range()) {
1161 const Layer *layer_eval = &merged_layers_grease_pencil.layer(layer_eval_i);
1162 if (eval_to_orig_layer_map.contains(layer_eval)) {
1163 const Layer *layer_orig = eval_to_orig_layer_map.lookup(layer_eval);
1164 const int layer_orig_index = *orig_grease_pencil.get_layer_index(*layer_orig);
1165 eval_to_orig_layer_indices_map.add(layer_eval_i, layer_orig_index);
1166 }
1167 }
1168
1169 /* Propagate layer attributes. */
1170 AttributeAccessor src_attributes = merged_layers_grease_pencil.attributes();
1171 MutableAttributeAccessor dst_attributes = orig_grease_pencil.attributes_for_write();
1172 src_attributes.foreach_attribute([&](const bke::AttributeIter &iter) {
1173 /* Anonymous attributes shouldn't be available on original geometry. */
1174 if (attribute_name_is_anonymous(iter.name)) {
1175 return;
1176 }
1177 if (iter.data_type == CD_PROP_STRING) {
1178 return;
1179 }
1180 const GVArraySpan src = *iter.get(AttrDomain::Layer);
1181 GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
1182 iter.name, AttrDomain::Layer, iter.data_type);
1183 if (!dst) {
1184 return;
1185 }
1186 attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
1187 using T = decltype(dummy);
1188 Span<T> src_span = src.typed<T>();
1189 MutableSpan<T> dst_span = dst.span.typed<T>();
1190 for (const auto [src_i, dst_i] : eval_to_orig_layer_indices_map.items()) {
1191 dst_span[dst_i] = src_span[src_i];
1192 }
1193 });
1194 dst.finish();
1195 });
1196
1197 /* Free temporary grease pencil struct. */
1198 BKE_id_free(nullptr, &merged_layers_grease_pencil);
1199}
1200
1202 Object *ob,
1203 GreasePencil &grease_pencil_orig,
1204 ModifierData *md_eval)
1205{
1206 using namespace bke;
1207 using namespace bke::greasepencil;
1210 GreasePencil *grease_pencil_for_eval = ob_eval->runtime->data_orig ?
1211 reinterpret_cast<GreasePencil *>(
1212 ob_eval->runtime->data_orig) :
1213 &grease_pencil_orig;
1214 const int eval_frame = int(DEG_get_ctime(depsgraph));
1215 GreasePencil *grease_pencil_temp = reinterpret_cast<GreasePencil *>(
1216 BKE_id_copy_ex(nullptr, &grease_pencil_for_eval->id, nullptr, LIB_ID_COPY_LOCALIZE));
1217 grease_pencil_temp->runtime->eval_frame = eval_frame;
1218 GeometrySet eval_geometry_set = GeometrySet::from_grease_pencil(grease_pencil_temp,
1219 GeometryOwnershipType::Owned);
1220
1222 mti->modify_geometry_set(md_eval, &mectx, &eval_geometry_set);
1223 if (!eval_geometry_set.has_grease_pencil()) {
1224
1225 return false;
1226 }
1227 GreasePencil &grease_pencil_result =
1228 *eval_geometry_set.get_component_for_write<GreasePencilComponent>().get_for_write();
1229
1230 apply_eval_grease_pencil_data(grease_pencil_result,
1231 eval_frame,
1232 grease_pencil_orig.layers().index_range(),
1233 grease_pencil_orig);
1234
1235 Main *bmain = DEG_get_bmain(depsgraph);
1236 /* There might be layers with empty names after evaluation. Make sure to rename them. */
1237 for (Layer *layer : grease_pencil_orig.layers_for_write()) {
1238 if (layer->name().is_empty()) {
1239 grease_pencil_orig.rename_node(*bmain, layer->as_node(), DATA_("Layer"));
1240 }
1241 }
1242 BKE_object_material_from_eval_data(bmain, ob, &grease_pencil_result.id);
1243 return true;
1244}
1245
1247 Scene *scene,
1248 Object *ob,
1249 GreasePencil &grease_pencil_orig,
1250 ModifierData *md)
1251{
1252 using namespace bke;
1253 using namespace bke::greasepencil;
1254 Main *bmain = DEG_get_bmain(depsgraph);
1255
1257
1258 WM_cursor_wait(true);
1259
1260 Map<int, Vector<int>> layer_indices_to_apply_per_frame;
1261 {
1262 for (const int layer_i : grease_pencil_orig.layers().index_range()) {
1263 const Layer &layer = grease_pencil_orig.layer(layer_i);
1264 for (const auto &[key, value] : layer.frames().items()) {
1265 if (value.is_end()) {
1266 continue;
1267 }
1268 layer_indices_to_apply_per_frame.lookup_or_add(key, {}).append(layer_i);
1269 }
1270 }
1271 }
1272
1273 Array<int> sorted_frame_times(layer_indices_to_apply_per_frame.size());
1274 int i = 0;
1275 for (const int key : layer_indices_to_apply_per_frame.keys()) {
1276 sorted_frame_times[i++] = key;
1277 }
1278 std::sort(sorted_frame_times.begin(), sorted_frame_times.end());
1279
1280 const int prev_frame = int(DEG_get_ctime(depsgraph));
1281 bool changed = false;
1282 for (const int eval_frame : sorted_frame_times) {
1283 const Span<int> layer_indices = layer_indices_to_apply_per_frame.lookup(eval_frame).as_span();
1284 scene->r.cfra = eval_frame;
1286
1288 GreasePencil *grease_pencil_for_eval = ob_eval->runtime->data_orig ?
1289 reinterpret_cast<GreasePencil *>(
1290 ob_eval->runtime->data_orig) :
1291 &grease_pencil_orig;
1292
1293 GreasePencil *grease_pencil_temp = reinterpret_cast<GreasePencil *>(
1294 BKE_id_copy_ex(nullptr, &grease_pencil_for_eval->id, nullptr, LIB_ID_COPY_LOCALIZE));
1295 grease_pencil_temp->runtime->eval_frame = eval_frame;
1296 GeometrySet eval_geometry_set = GeometrySet::from_grease_pencil(grease_pencil_temp,
1297 GeometryOwnershipType::Owned);
1298
1301 mti->modify_geometry_set(md_eval, &mectx, &eval_geometry_set);
1302 if (!eval_geometry_set.has_grease_pencil()) {
1303 continue;
1304 }
1305 GreasePencil &grease_pencil_result =
1306 *eval_geometry_set.get_component_for_write<GreasePencilComponent>().get_for_write();
1307
1308 IndexMaskMemory memory;
1309 const IndexMask orig_layers_to_apply = IndexMask::from_indices(layer_indices, memory);
1311 grease_pencil_result, eval_frame, orig_layers_to_apply, grease_pencil_orig);
1312
1313 BKE_object_material_from_eval_data(bmain, ob, &grease_pencil_result.id);
1314 changed = true;
1315 }
1316
1317 scene->r.cfra = prev_frame;
1319
1320 /* There might be layers with empty names after evaluation. Make sure to rename them. */
1321 for (Layer *layer : grease_pencil_orig.layers_for_write()) {
1322 if (layer->name().is_empty()) {
1323 grease_pencil_orig.rename_node(*bmain, layer->as_node(), DATA_("Layer"));
1324 }
1325 }
1326
1327 WM_cursor_wait(false);
1328 return changed;
1329}
1330
1332 Depsgraph *depsgraph,
1333 Scene *scene,
1334 Object *ob,
1335 ModifierData *md_eval,
1336 const bool do_all_keyframes)
1337{
1339
1340 if (mti->is_disabled && mti->is_disabled(scene, md_eval, false)) {
1341 BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
1342 return false;
1343 }
1344
1345 if (ob->type == OB_MESH) {
1346 Mesh *mesh = static_cast<Mesh *>(ob->data);
1348
1349 if (mesh->key && mti->type != ModifierTypeType::NonGeometrical) {
1350 BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys");
1351 return false;
1352 }
1353
1354 /* Multires: ensure that recent sculpting is applied */
1355 if (md_eval->type == eModifierType_Multires) {
1357 }
1358
1359 if (mmd && mmd->totlvl && mti->type == ModifierTypeType::OnlyDeform) {
1360 if (!multiresModifier_reshapeFromDeformModifier(depsgraph, ob, mmd, md_eval)) {
1361 BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
1362 return false;
1363 }
1364 }
1365 else {
1366 Mesh *mesh_applied = create_applied_mesh_for_modifier(
1367 depsgraph,
1370 md_eval,
1371 /* It's important not to apply virtual modifiers (e.g. shape-keys) because they're kept,
1372 * causing them to be applied twice, see: #97758. */
1373 false,
1374 true,
1375 reports);
1376 if (!mesh_applied) {
1377 return false;
1378 }
1379
1380 Main *bmain = DEG_get_bmain(depsgraph);
1381 BKE_object_material_from_eval_data(bmain, ob, &mesh_applied->id);
1382 BKE_mesh_nomain_to_mesh(mesh_applied, mesh, ob);
1383
1384 /* Anonymous attributes shouldn't be available on the applied geometry. */
1385 mesh->attributes_for_write().remove_anonymous();
1386
1387 /* Remove strings referring to attributes if they no longer exist. */
1389
1390 if (md_eval->type == eModifierType_Multires) {
1392 }
1393 }
1394 }
1395 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
1396 Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
1397 Curve *curve = static_cast<Curve *>(ob->data);
1398 Curve *curve_eval = static_cast<Curve *>(object_eval->data);
1399 ModifierEvalContext mectx = {depsgraph, object_eval, MOD_APPLY_TO_ORIGINAL};
1400
1402 BKE_report(
1403 reports,
1404 RPT_ERROR,
1405 "Cannot apply constructive modifiers on curve. Convert curve to mesh in order to apply");
1406 return false;
1407 }
1408
1409 BKE_report(reports,
1410 RPT_INFO,
1411 "Applied modifier only changed CV points, not tessellated/bevel vertices");
1412
1413 int verts_num;
1414 float(*vertexCos)[3] = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &verts_num);
1415 mti->deform_verts(
1416 md_eval, &mectx, nullptr, {reinterpret_cast<float3 *>(vertexCos), verts_num});
1417 BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos, false);
1418
1419 MEM_freeN(vertexCos);
1420
1422 }
1423 else if (ob->type == OB_LATTICE) {
1424 Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
1425 Lattice *lattice = static_cast<Lattice *>(ob->data);
1426 ModifierEvalContext mectx = {depsgraph, object_eval, MOD_APPLY_TO_ORIGINAL};
1427
1429 BKE_report(reports, RPT_ERROR, "Constructive modifiers cannot be applied");
1430 return false;
1431 }
1432
1433 int verts_num;
1434 float(*vertexCos)[3] = BKE_lattice_vert_coords_alloc(lattice, &verts_num);
1435 mti->deform_verts(
1436 md_eval, &mectx, nullptr, {reinterpret_cast<float3 *>(vertexCos), verts_num});
1438
1439 MEM_freeN(vertexCos);
1440
1442 }
1443 else if (ob->type == OB_CURVES) {
1444 Curves &curves = *static_cast<Curves *>(ob->data);
1445 if (mti->modify_geometry_set == nullptr) {
1447 return false;
1448 }
1449
1450 bke::GeometrySet geometry_set = bke::GeometrySet::from_curves(
1451 &curves, bke::GeometryOwnershipType::ReadOnly);
1452
1454 mti->modify_geometry_set(md_eval, &mectx, &geometry_set);
1455 if (!geometry_set.has_curves()) {
1456 BKE_report(reports, RPT_ERROR, "Evaluated geometry from modifier does not contain curves");
1457 return false;
1458 }
1459 Curves &curves_eval = *geometry_set.get_curves_for_write();
1460
1461 /* Anonymous attributes shouldn't be available on original geometry. */
1462 curves_eval.geometry.wrap().attributes_for_write().remove_anonymous();
1463
1464 curves.geometry.wrap() = std::move(curves_eval.geometry.wrap());
1465 Main *bmain = DEG_get_bmain(depsgraph);
1466 BKE_object_material_from_eval_data(bmain, ob, &curves_eval.id);
1467 }
1468 else if (ob->type == OB_POINTCLOUD) {
1469 PointCloud &points = *static_cast<PointCloud *>(ob->data);
1470 if (mti->modify_geometry_set == nullptr) {
1472 return false;
1473 }
1474
1475 bke::GeometrySet geometry_set = bke::GeometrySet::from_pointcloud(
1476 &points, bke::GeometryOwnershipType::ReadOnly);
1477
1479 mti->modify_geometry_set(md_eval, &mectx, &geometry_set);
1480 if (!geometry_set.has_pointcloud()) {
1481 BKE_report(
1482 reports, RPT_ERROR, "Evaluated geometry from modifier does not contain a point cloud");
1483 return false;
1484 }
1485 PointCloud *pointcloud_eval =
1486 geometry_set.get_component_for_write<bke::PointCloudComponent>().release();
1487
1488 /* Anonymous attributes shouldn't be available on original geometry. */
1489 pointcloud_eval->attributes_for_write().remove_anonymous();
1490
1491 Main *bmain = DEG_get_bmain(depsgraph);
1492 BKE_object_material_from_eval_data(bmain, ob, &pointcloud_eval->id);
1493 BKE_pointcloud_nomain_to_pointcloud(pointcloud_eval, &points);
1494 }
1495 else if (ob->type == OB_GREASE_PENCIL) {
1496 if (mti->modify_geometry_set == nullptr) {
1497 BKE_report(reports, RPT_ERROR, "Cannot apply this modifier to grease pencil geometry");
1498 return false;
1499 }
1500 GreasePencil &grease_pencil_orig = *static_cast<GreasePencil *>(ob->data);
1501 bool success = false;
1502 if (do_all_keyframes) {
1503 /* The function #apply_grease_pencil_for_modifier_all_keyframes will retrieve
1504 * the evaluated modifier for each keyframe. The original modifier is passed
1505 * to ensure the evaluated modifier is not used, as it will be invalid when
1506 * the scene graph is updated for the next keyframe. */
1507 ModifierData *md = BKE_modifier_get_original(ob, md_eval);
1509 depsgraph, scene, ob, grease_pencil_orig, md);
1510 }
1511 else {
1512 success = apply_grease_pencil_for_modifier(depsgraph, ob, grease_pencil_orig, md_eval);
1513 }
1514 if (!success) {
1515 BKE_report(reports,
1516 RPT_ERROR,
1517 "Evaluated geometry from modifier does not contain grease pencil geometry");
1518 return false;
1519 }
1520 }
1521 else {
1522 /* TODO: implement for volumes. */
1523 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
1524 return false;
1525 }
1526
1527 /* lattice modifier can be applied to particle system too */
1528 if (ob->particlesystem.first) {
1530 if (psys->part->type != PART_HAIR) {
1531 continue;
1532 }
1533
1534 psys_apply_hair_lattice(depsgraph, scene, ob, psys);
1535 }
1536 }
1537
1538 return true;
1539}
1540
1542 ReportList *reports,
1543 Depsgraph *depsgraph,
1544 Scene *scene,
1545 Object *ob,
1546 ModifierData *md,
1547 int mode,
1548 bool keep_modifier,
1549 const bool do_all_keyframes)
1550{
1551 if (BKE_object_is_in_editmode(ob)) {
1552 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
1553 return false;
1554 }
1555 if (mode != MODIFIER_APPLY_SHAPE && ID_REAL_USERS(ob->data) > 1) {
1556 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
1557 return false;
1558 }
1559 if ((ob->mode & OB_MODE_SCULPT) && find_multires_modifier_before(scene, md) &&
1560 (BKE_modifier_is_same_topology(md) == false))
1561 {
1562 BKE_report(reports,
1563 RPT_ERROR,
1564 "Constructive modifier cannot be applied to multi-res data in sculpt mode");
1565 return false;
1566 }
1567
1568 if (md != ob->modifiers.first) {
1569 BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
1570 }
1571
1572 /* Get evaluated modifier, so object links pointer to evaluated data,
1573 * but still use original object it is applied to the original mesh. */
1575 ModifierData *md_eval = (ob_eval) ? BKE_modifiers_findby_name(ob_eval, md->name) : md;
1576
1577 Depsgraph *apply_depsgraph = depsgraph;
1578 Depsgraph *local_depsgraph = nullptr;
1579
1580 /* If the object is hidden or the modifier is not enabled for the viewport is disabled a special
1581 * handling is required. This is because the viewport dependency graph optimizes out evaluation
1582 * of objects which are used by hidden objects and disabled modifiers.
1583 *
1584 * The idea is to create a dependency graph which does not perform those optimizations. */
1585 if ((ob_eval->base_flag & BASE_ENABLED_VIEWPORT) == 0 ||
1586 (md_eval->mode & eModifierMode_Realtime) == 0)
1587 {
1589
1590 local_depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_VIEWPORT);
1591 DEG_disable_visibility_optimization(local_depsgraph);
1592
1593 DEG_graph_build_from_ids(local_depsgraph, {&ob->id});
1594 DEG_evaluate_on_refresh(local_depsgraph);
1595
1596 apply_depsgraph = local_depsgraph;
1597
1598 /* The evaluated object and modifier are now from the different dependency graph. */
1599 ob_eval = DEG_get_evaluated_object(local_depsgraph, ob);
1600 md_eval = BKE_modifiers_findby_name(ob_eval, md->name);
1601
1602 /* Force mode on the evaluated modifier, enforcing the modifier evaluation in the apply()
1603 * functions. */
1604 md_eval->mode |= eModifierMode_Realtime;
1605 }
1606
1607 bool did_apply = false;
1608 if (mode == MODIFIER_APPLY_SHAPE) {
1609 did_apply = modifier_apply_shape(bmain, reports, apply_depsgraph, scene, ob, md_eval);
1610 }
1611 else {
1612 did_apply = modifier_apply_obdata(
1613 reports, apply_depsgraph, scene, ob, md_eval, do_all_keyframes);
1614 }
1615
1616 if (did_apply) {
1617 if (!keep_modifier) {
1620 }
1622 }
1623
1624 if (local_depsgraph != nullptr) {
1625 DEG_graph_free(local_depsgraph);
1626 }
1627
1628 return true;
1629}
1630
1632 ReportList * /*reports*/, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
1633{
1636 bmain, scene, ob, ((ParticleSystemModifierData *)md)->psys);
1637 BLI_remlink(&ob->modifiers, nmd);
1638 BLI_insertlinkafter(&ob->modifiers, md, nmd);
1640 return true;
1641 }
1642
1644 BKE_modifier_copydata(md, nmd);
1645 BLI_insertlinkafter(&ob->modifiers, md, nmd);
1649
1651
1652 return true;
1653}
1654
1658{
1659 Vector<PointerRNA> objects;
1660 if (RNA_boolean_get(op.ptr, "use_selected_objects")) {
1662 }
1663 else {
1664 if (Object *object = context_active_object(&C)) {
1665 objects.append(RNA_id_pointer_create(&object->id));
1666 }
1667 }
1668 return objects;
1669}
1670
1672{
1674 ot->srna,
1675 "use_selected_objects",
1676 false,
1677 "Selected Objects",
1678 "Affect all selected objects instead of just the active object");
1680}
1681
1682/* ------------------------------------------------------------------- */
1687{
1688 Main *bmain = CTX_data_main(C);
1689 Scene *scene = CTX_data_scene(C);
1690 int type = RNA_enum_get(op->ptr, "type");
1691
1692 bool changed = false;
1693 for (const PointerRNA &ptr : modifier_get_edit_objects(*C, *op)) {
1694 Object *ob = static_cast<Object *>(ptr.data);
1695 if (!modifier_add(op->reports, bmain, scene, ob, nullptr, type)) {
1696 continue;
1697 }
1698 changed = true;
1700 }
1701 if (!changed) {
1702 return OPERATOR_CANCELLED;
1703 }
1704
1705 return OPERATOR_FINISHED;
1706}
1707
1708static int modifier_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1709{
1710 if (event->modifier & KM_ALT || CTX_wm_view3d(C)) {
1711 RNA_boolean_set(op->ptr, "use_selected_objects", true);
1712 }
1713 if (!RNA_struct_property_is_set(op->ptr, "type")) {
1714 return WM_menu_invoke(C, op, event);
1715 }
1716 return modifier_add_exec(C, op);
1717}
1718
1720 PointerRNA * /*ptr*/,
1721 PropertyRNA * /*prop*/,
1722 bool *r_free)
1723{
1725
1726 if (!ob) {
1728 }
1729
1730 EnumPropertyItem *items = nullptr;
1731 int totitem = 0;
1732
1733 const EnumPropertyItem *group_item = nullptr;
1734 for (int a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) {
1736
1737 if (md_item->identifier[0]) {
1739
1741 continue;
1742 }
1743
1744 if (!BKE_object_support_modifier_type_check(ob, md_item->value)) {
1745 continue;
1746 }
1747 }
1748 else {
1749 group_item = md_item;
1750 continue;
1751 }
1752
1753 if (group_item) {
1754 RNA_enum_item_add(&items, &totitem, group_item);
1755 group_item = nullptr;
1756 }
1757
1758 RNA_enum_item_add(&items, &totitem, md_item);
1759 }
1760
1761 RNA_enum_item_end(&items, &totitem);
1762 *r_free = true;
1763
1764 return items;
1765}
1766
1768{
1769 PropertyRNA *prop;
1770
1771 /* identifiers */
1772 ot->name = "Add Modifier";
1773 ot->description = "Add a procedural operation/effect to the active object";
1774 ot->idname = "OBJECT_OT_modifier_add";
1775
1776 /* api callbacks */
1780
1781 /* flags */
1783
1784 /* properties */
1785 prop = RNA_def_enum(
1788 ot->prop = prop;
1790}
1791
1794/* ------------------------------------------------------------------- */
1801 StructRNA *rna_type,
1802 int obtype_flag,
1803 const bool is_editmode_allowed,
1804 const bool is_liboverride_allowed)
1805{
1806 Main *bmain = CTX_data_main(C);
1807 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
1809 ModifierData *mod = static_cast<ModifierData *>(ptr.data); /* May be nullptr. */
1810
1811 if (mod == nullptr && ob != nullptr) {
1813 }
1814
1815 if (!ob || !BKE_id_is_editable(bmain, &ob->id)) {
1816 return false;
1817 }
1818 if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
1819 return false;
1820 }
1821 if (ptr.owner_id && !BKE_id_is_editable(bmain, ptr.owner_id)) {
1822 return false;
1823 }
1824
1825 if (!is_liboverride_allowed && BKE_modifier_is_nonlocal_in_liboverride(ob, mod)) {
1827 C, "Cannot edit modifiers coming from linked data in a library override");
1828 return false;
1829 }
1830
1831 if (!is_editmode_allowed && CTX_data_edit_object(C) != nullptr) {
1832 CTX_wm_operator_poll_msg_set(C, "This modifier operation is not allowed from Edit mode");
1833 return false;
1834 }
1835
1836 return true;
1837}
1838
1840{
1841 return edit_modifier_poll_generic(C, &RNA_Modifier, 0, true, false);
1842}
1843
1844/* Used by operators performing actions allowed also on modifiers from the overridden linked object
1845 * (not only from added 'local' ones). */
1847{
1848 return edit_modifier_poll_generic(C, &RNA_Modifier, 0, true, true);
1849}
1850
1852{
1854 ot->srna, "modifier", nullptr, MAX_NAME, "Modifier", "Name of the modifier to edit");
1856}
1857
1859{
1861 ot->srna, "report", false, "Report", "Create a notification after the operation");
1863}
1864
1867/* ------------------------------------------------------------------- */
1874{
1875 if (RNA_struct_property_is_set(op->ptr, "modifier")) {
1876 return true;
1877 }
1878
1879 PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
1880 if (ctx_ptr.data != nullptr) {
1881 ModifierData *md = static_cast<ModifierData *>(ctx_ptr.data);
1882 RNA_string_set(op->ptr, "modifier", md->name);
1883 return true;
1884 }
1885
1886 return false;
1887}
1888
1895 wmOperator *op,
1896 const wmEvent *event,
1897 int *r_retval)
1898{
1899 if (RNA_struct_find_property(op->ptr, "use_selected_objects")) {
1900 if (event->modifier & KM_ALT) {
1901 RNA_boolean_set(op->ptr, "use_selected_objects", true);
1902 }
1903 }
1904
1905 if (RNA_struct_property_is_set(op->ptr, "modifier")) {
1906 return true;
1907 }
1908
1909 /* Note that the context pointer is *not* the active modifier, it is set in UI layouts. */
1910 PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
1911 if (ctx_ptr.data != nullptr) {
1912 ModifierData *md = static_cast<ModifierData *>(ctx_ptr.data);
1913 RNA_string_set(op->ptr, "modifier", md->name);
1914 return true;
1915 }
1916
1918 if (panel_ptr == nullptr || RNA_pointer_is_null(panel_ptr)) {
1919 *r_retval = OPERATOR_CANCELLED;
1920 return false;
1921 }
1922
1923 if (!RNA_struct_is_a(panel_ptr->type, &RNA_Modifier)) {
1924 /* Work around multiple operators using the same shortcut. The operators for the other
1925 * stacks in the property editor use the same key, and will not run after these return
1926 * OPERATOR_CANCELLED. */
1928 return false;
1929 }
1930
1931 const ModifierData *md = static_cast<const ModifierData *>(panel_ptr->data);
1932 RNA_string_set(op->ptr, "modifier", md->name);
1933 return true;
1934}
1935
1937{
1938 char modifier_name[MAX_NAME];
1939 RNA_string_get(op->ptr, "modifier", modifier_name);
1940
1942
1943 if (md && type != 0 && md->type != type) {
1944 md = nullptr;
1945 }
1946
1947 return md;
1948}
1949
1952/* ------------------------------------------------------------------- */
1957{
1958 Main *bmain = CTX_data_main(C);
1959 Scene *scene = CTX_data_scene(C);
1960 ViewLayer *view_layer = CTX_data_view_layer(C);
1961
1962 char name[MAX_NAME];
1963 RNA_string_get(op->ptr, "modifier", name);
1964
1965 bool changed = false;
1966 for (const PointerRNA &ptr : modifier_get_edit_objects(*C, *op)) {
1967 Object *ob = static_cast<Object *>(ptr.data);
1969 if (md == nullptr) {
1970 continue;
1971 }
1972
1973 int mode_orig = ob->mode;
1974 if (!modifier_remove(op->reports, bmain, scene, ob, md)) {
1975 continue;
1976 }
1977
1978 changed = true;
1979
1981
1982 /* if cloth/softbody was removed, particle mode could be cleared */
1983 if (mode_orig & OB_MODE_PARTICLE_EDIT) {
1984 if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
1985 BKE_view_layer_synced_ensure(scene, view_layer);
1986 if (ob == BKE_view_layer_active_object_get(view_layer)) {
1988 }
1989 }
1990 }
1991 }
1992
1993 if (!changed) {
1994 return OPERATOR_CANCELLED;
1995 }
1996
1997 if (RNA_boolean_get(op->ptr, "report")) {
1998 BKE_reportf(op->reports, RPT_INFO, "Removed modifier: %s", name);
1999 }
2000
2001 return OPERATOR_FINISHED;
2002}
2003
2004static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2005{
2006 int retval;
2007 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2008 return modifier_remove_exec(C, op);
2009 }
2010 return retval;
2011}
2012
2014{
2015 ot->name = "Remove Modifier";
2016 ot->description = "Remove a modifier from the active object";
2017 ot->idname = "OBJECT_OT_modifier_remove";
2018
2022
2023 /* flags */
2028}
2029
2031{
2032 Main *bmain = CTX_data_main(C);
2033 Scene *scene = CTX_data_scene(C);
2034
2035 CTX_DATA_BEGIN (C, Object *, object, selected_editable_objects) {
2036 modifiers_clear(bmain, scene, object);
2038 }
2040
2041 return OPERATOR_FINISHED;
2042}
2043
2045{
2047 return false;
2048 }
2049 const Object *object = context_active_object(C);
2050 if (!BKE_object_supports_modifiers(object)) {
2051 return false;
2052 }
2053 return true;
2054}
2055
2057{
2058 ot->name = "Clear Object Modifiers";
2059 ot->description = "Clear all modifiers from the selected objects";
2060 ot->idname = "OBJECT_OT_modifiers_clear";
2061
2064
2066}
2067
2070/* ------------------------------------------------------------------- */
2075{
2078
2079 if (!md || !modifier_move_up(op->reports, RPT_WARNING, ob, md)) {
2080 return OPERATOR_CANCELLED;
2081 }
2082
2085
2086 return OPERATOR_FINISHED;
2087}
2088
2089static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2090{
2091 int retval;
2092 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2093 return modifier_move_up_exec(C, op);
2094 }
2095 return retval;
2096}
2097
2099{
2100 ot->name = "Move Up Modifier";
2101 ot->description = "Move modifier up in the stack";
2102 ot->idname = "OBJECT_OT_modifier_move_up";
2103
2107
2108 /* flags */
2111}
2112
2115/* ------------------------------------------------------------------- */
2120{
2123
2124 if (!md || !modifier_move_down(op->reports, RPT_WARNING, ob, md)) {
2125 return OPERATOR_CANCELLED;
2126 }
2127
2130
2131 return OPERATOR_FINISHED;
2132}
2133
2134static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2135{
2136 int retval;
2137 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2138 return modifier_move_down_exec(C, op);
2139 }
2140 return retval;
2141}
2142
2144{
2145 ot->name = "Move Down Modifier";
2146 ot->description = "Move modifier down in the stack";
2147 ot->idname = "OBJECT_OT_modifier_move_down";
2148
2152
2153 /* flags */
2156}
2157
2160/* ------------------------------------------------------------------- */
2165{
2166 char name[MAX_NAME];
2167 RNA_string_get(op->ptr, "modifier", name);
2168
2169 const int index = RNA_int_get(op->ptr, "index");
2170
2171 bool changed = false;
2172 for (const PointerRNA &ptr : modifier_get_edit_objects(*C, *op)) {
2173 Object *ob = static_cast<Object *>(ptr.data);
2175 if (!md) {
2176 continue;
2177 }
2178
2179 if (!modifier_move_to_index(op->reports, RPT_WARNING, ob, md, index, true)) {
2180 continue;
2181 }
2182 changed = true;
2183 }
2184
2185 if (!changed) {
2186 return OPERATOR_CANCELLED;
2187 }
2188
2189 return OPERATOR_FINISHED;
2190}
2191
2193{
2194 int retval;
2195 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2196 return modifier_move_to_index_exec(C, op);
2197 }
2198 return retval;
2199}
2200
2202{
2203 ot->name = "Move Active Modifier to Index";
2204 ot->description =
2205 "Change the modifier's index in the stack so it evaluates after the set number of others";
2206 ot->idname = "OBJECT_OT_modifier_move_to_index";
2207
2211
2212 /* flags */
2216 ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the modifier to", 0, INT_MAX);
2218}
2219
2222/* ------------------------------------------------------------------- */
2227{
2228 if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false, false)) {
2229 return false;
2230 }
2231
2232 Scene *scene = CTX_data_scene(C);
2233 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
2234 Object *ob = (ptr.owner_id != nullptr) ? (Object *)ptr.owner_id : context_active_object(C);
2235 ModifierData *md = static_cast<ModifierData *>(ptr.data); /* May be nullptr. */
2236
2237 if (ID_IS_OVERRIDE_LIBRARY(ob) || ((ob->data != nullptr) && ID_IS_OVERRIDE_LIBRARY(ob->data))) {
2238 CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied on override data");
2239 return false;
2240 }
2241 if (md != nullptr) {
2242 if ((ob->mode & OB_MODE_SCULPT) && find_multires_modifier_before(scene, md) &&
2243 (BKE_modifier_is_same_topology(md) == false))
2244 {
2246 C, "Constructive modifier cannot be applied to multi-res data in sculpt mode");
2247 return false;
2248 }
2249 }
2250 return true;
2251}
2252
2253static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, bool keep_modifier)
2254{
2255 Main *bmain = CTX_data_main(C);
2257 Scene *scene = CTX_data_scene(C);
2259
2260 char name[MAX_NAME];
2261 RNA_string_get(op->ptr, "modifier", name);
2262
2263 const bool do_report = RNA_boolean_get(op->ptr, "report");
2264 const int reports_len = do_report ? BLI_listbase_count(&op->reports->list) : 0;
2265
2266 const bool do_single_user = (apply_as == MODIFIER_APPLY_DATA) ?
2267 RNA_boolean_get(op->ptr, "single_user") :
2268 false;
2269 const bool do_merge_customdata = (apply_as == MODIFIER_APPLY_DATA) ?
2270 RNA_boolean_get(op->ptr, "merge_customdata") :
2271 false;
2272 const bool do_all_keyframes = (apply_as == MODIFIER_APPLY_DATA) ?
2273 RNA_boolean_get(op->ptr, "all_keyframes") :
2274 false;
2275
2276 bool changed = false;
2277 for (const PointerRNA &ptr : objects) {
2278 Object *ob = static_cast<Object *>(ptr.data);
2280 if (md == nullptr) {
2281 continue;
2282 }
2283
2285
2286 if (do_single_user && ID_REAL_USERS(ob->data) > 1) {
2287 single_obdata_user_make(bmain, scene, ob);
2289 WM_event_add_notifier(C, NC_WINDOW, nullptr);
2291 }
2292
2293 if (!modifier_apply(bmain,
2294 op->reports,
2295 depsgraph,
2296 scene,
2297 ob,
2298 md,
2299 apply_as,
2300 keep_modifier,
2301 do_all_keyframes))
2302 {
2303 continue;
2304 }
2305 changed = true;
2306
2307 if (ob->type == OB_MESH && do_merge_customdata &&
2309 {
2311 }
2312
2316 }
2317
2318 if (!changed) {
2319 return OPERATOR_CANCELLED;
2320 }
2321
2322 if (do_report) {
2323 /* Only add this report if the operator didn't cause another one. The purpose here is
2324 * to alert that something happened, and the previous report will do that anyway. */
2325 if (BLI_listbase_count(&op->reports->list) == reports_len) {
2326 BKE_reportf(op->reports, RPT_INFO, "Applied modifier: %s", name);
2327 }
2328 }
2329
2330 return OPERATOR_FINISHED;
2331}
2332
2334{
2335 return modifier_apply_exec_ex(C, op, MODIFIER_APPLY_DATA, false);
2336}
2337
2338static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2339{
2340 int retval;
2341 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2342 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
2343 Object *ob = (ptr.owner_id != nullptr) ? (Object *)ptr.owner_id : context_active_object(C);
2344
2345 if ((ob->data != nullptr) && ID_REAL_USERS(ob->data) > 1) {
2346 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "single_user");
2347 if (!RNA_property_is_set(op->ptr, prop)) {
2348 RNA_property_boolean_set(op->ptr, prop, true);
2349 }
2350 if (RNA_property_boolean_get(op->ptr, prop)) {
2352 C,
2353 op,
2354 IFACE_("Apply Modifier"),
2355 IFACE_("Make data single-user, apply modifier, and remove it from the list."),
2356 IFACE_("Apply"),
2358 false);
2359 }
2360 }
2361 return modifier_apply_exec(C, op);
2362 }
2363 return retval;
2364}
2365
2367{
2368 PropertyRNA *prop;
2369
2370 ot->name = "Apply Modifier";
2371 ot->description = "Apply modifier and remove from the stack";
2372 ot->idname = "OBJECT_OT_modifier_apply";
2373
2377
2378 /* flags */
2380
2383
2385 "merge_customdata",
2386 true,
2387 "Merge UVs",
2388 "For mesh objects, merge UV coordinates that share a vertex to account for "
2389 "imprecision in some modifiers");
2390 prop = RNA_def_boolean(ot->srna,
2391 "single_user",
2392 false,
2393 "Make Data Single User",
2394 "Make the object's data single user if needed");
2396 prop = RNA_def_boolean(ot->srna,
2397 "all_keyframes",
2398 false,
2399 "Apply to all keyframes",
2400 "For Grease Pencil objects, apply the modifier to all the keyframes");
2403}
2404
2407/* ------------------------------------------------------------------- */
2412{
2413 return modifier_apply_poll(C);
2414}
2415
2417{
2418 bool keep = RNA_boolean_get(op->ptr, "keep_modifier");
2419
2420 return modifier_apply_exec_ex(C, op, MODIFIER_APPLY_SHAPE, keep);
2421}
2422
2424{
2425 int retval;
2426 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2427 return modifier_apply_as_shapekey_exec(C, op);
2428 }
2429 return retval;
2430}
2431
2433 wmOperatorType * /*ot*/,
2434 PointerRNA *ptr)
2435{
2436 bool keep = RNA_boolean_get(ptr, "keep_modifier");
2437 if (keep) {
2438 return TIP_("Apply modifier as a new shapekey and keep it in the stack");
2439 }
2440
2441 return "";
2442}
2443
2445{
2446 ot->name = "Apply Modifier as Shape Key";
2447 ot->description = "Apply modifier as a new shape key and remove from the stack";
2448 ot->idname = "OBJECT_OT_modifier_apply_as_shapekey";
2449
2454
2455 /* flags */
2457
2459 ot->srna, "keep_modifier", false, "Keep Modifier", "Do not remove the modifier from stack");
2463}
2464
2467/* ------------------------------------------------------------------- */
2472{
2473 Main *bmain = CTX_data_main(C);
2475 Scene *scene = CTX_data_scene(C);
2476 ViewLayer *view_layer = CTX_data_view_layer(C);
2479
2480 if (!md || !convert_psys_to_mesh(op->reports, bmain, depsgraph, scene, view_layer, ob, md)) {
2481 return OPERATOR_CANCELLED;
2482 }
2483
2486
2487 return OPERATOR_FINISHED;
2488}
2489
2490static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
2491{
2493 return modifier_convert_exec(C, op);
2494 }
2495 return OPERATOR_CANCELLED;
2496}
2497
2499{
2500 ot->name = "Convert Particles to Mesh";
2501 ot->description = "Convert particles to a mesh object";
2502 ot->idname = "OBJECT_OT_modifier_convert";
2503
2507
2508 /* flags */
2511}
2512
2515/* ------------------------------------------------------------------- */
2520{
2521 Main *bmain = CTX_data_main(C);
2522 Scene *scene = CTX_data_scene(C);
2523 char name[MAX_NAME];
2524 RNA_string_get(op->ptr, "modifier", name);
2525
2526 bool changed = false;
2527 for (const PointerRNA &ptr : modifier_get_edit_objects(*C, *op)) {
2528 Object *ob = static_cast<Object *>(ptr.data);
2530 if (!md) {
2531 continue;
2532 }
2533
2534 if (!modifier_copy(op->reports, bmain, scene, ob, md)) {
2535 continue;
2536 }
2537 changed = true;
2541 }
2542
2543 if (!changed) {
2544 return OPERATOR_CANCELLED;
2545 }
2546
2547 return OPERATOR_FINISHED;
2548}
2549
2550static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2551{
2552 int retval;
2553 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2554 return modifier_copy_exec(C, op);
2555 }
2556 return retval;
2557}
2558
2560{
2561 ot->name = "Copy Modifier";
2562 ot->description = "Duplicate modifier at the same position in the stack";
2563 ot->idname = "OBJECT_OT_modifier_copy";
2564
2568
2569 /* flags */
2573}
2574
2577/* ------------------------------------------------------------------- */
2582{
2585
2586 /* If there is no modifier set for this operator, clear the active modifier field. */
2588
2590
2591 return OPERATOR_FINISHED;
2592}
2593
2595{
2596 int retval;
2597 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2598 return modifier_set_active_exec(C, op);
2599 }
2600 return retval;
2601}
2602
2604{
2605 ot->name = "Set Active Modifier";
2606 ot->description = "Activate the modifier to use as the context";
2607 ot->idname = "OBJECT_OT_modifier_set_active";
2608
2612
2613 /* flags */
2616}
2617
2620/* ------------------------------------------------------------------- */
2625{
2626 Main *bmain = CTX_data_main(C);
2627 const Scene *scene = CTX_data_scene(C);
2628 Object *obact = context_active_object(C);
2629 ModifierData *md = edit_modifier_property_get(op, obact, 0);
2630 if (!md) {
2631 return OPERATOR_CANCELLED;
2632 }
2633
2634 int num_copied = 0;
2635
2636 Vector<PointerRNA> selected_objects;
2637 CTX_data_selected_objects(C, &selected_objects);
2638 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2639 if (ob == obact) {
2640 continue;
2641 }
2642 if (!ID_IS_EDITABLE(ob)) {
2643 continue;
2644 }
2645 if (modifier_copy_to_object(bmain, scene, obact, md, ob, op->reports)) {
2647 num_copied++;
2648 }
2649 }
2651
2652 if (num_copied > 0) {
2654 }
2655 else {
2656 BKE_reportf(op->reports, RPT_ERROR, "Modifier '%s' was not copied to any objects", md->name);
2657 return OPERATOR_CANCELLED;
2658 }
2659
2660 return OPERATOR_FINISHED;
2661}
2662
2664{
2665 int retval;
2666 if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
2667 return modifier_copy_to_selected_exec(C, op);
2668 }
2669 return retval;
2670}
2671
2673{
2674 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
2676 ModifierData *md = static_cast<ModifierData *>(ptr.data);
2677
2678 /* This just mirrors the check in #BKE_object_copy_modifier,
2679 * but there is no reasoning for it there. */
2681 CTX_wm_operator_poll_msg_set(C, R"(Not supported for "Collision" or "Hook" modifiers)");
2682 return false;
2683 }
2684
2685 if (!obact) {
2686 CTX_wm_operator_poll_msg_set(C, "No selected object is active");
2687 return false;
2688 }
2689
2690 if (!BKE_object_supports_modifiers(obact)) {
2691 CTX_wm_operator_poll_msg_set(C, "Object type of source object is not supported");
2692 return false;
2693 }
2694
2695 /* This could have a performance impact in the worst case, where there are many objects selected
2696 * and none of them pass either of the checks. But that should be uncommon, and this operator is
2697 * only exposed in a drop-down menu anyway. */
2698 bool found_supported_objects = false;
2699 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2700 if (ob == obact) {
2701 continue;
2702 }
2703
2704 if (!md) {
2705 /* Skip type check if modifier could not be found ("modifier" context variable not set). */
2707 found_supported_objects = true;
2708 break;
2709 }
2710 }
2711 else if (BKE_object_support_modifier_type_check(ob, md->type)) {
2712 found_supported_objects = true;
2713 break;
2714 }
2715 }
2717
2718 if (!found_supported_objects) {
2719 CTX_wm_operator_poll_msg_set(C, "No supported objects were selected");
2720 return false;
2721 }
2722 return true;
2723}
2724
2726{
2727 ot->name = "Copy Modifier to Selected";
2728 ot->description = "Copy the modifier from the active object to all selected objects";
2729 ot->idname = "OBJECT_OT_modifier_copy_to_selected";
2730
2734
2735 /* flags */
2738}
2739
2741{
2742 Main *bmain = CTX_data_main(C);
2743 const Scene *scene = CTX_data_scene(C);
2744 Object *active_object = context_active_object(C);
2745
2746 Vector<PointerRNA> selected_objects;
2747 CTX_data_selected_objects(C, &selected_objects);
2748 CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
2749 if (object == active_object) {
2750 continue;
2751 }
2752 LISTBASE_FOREACH (const ModifierData *, md, &active_object->modifiers) {
2753 if (modifier_copy_to_object(bmain, scene, active_object, md, object, op->reports)) {
2755 }
2756 }
2757 }
2759
2760 return OPERATOR_FINISHED;
2761
2763
2765
2766 return OPERATOR_FINISHED;
2767}
2768
2770{
2772 return false;
2773 }
2774 const Object *active_object = context_active_object(C);
2775 if (!BKE_object_supports_modifiers(active_object)) {
2776 return false;
2777 }
2778 if (BLI_listbase_is_empty(&active_object->modifiers)) {
2779 CTX_wm_operator_poll_msg_set(C, "Active object has no modifiers");
2780 return false;
2781 }
2782 return true;
2783}
2784
2786{
2787 ot->name = "Copy Modifiers to Selected Objects";
2788 ot->idname = "OBJECT_OT_modifiers_copy_to_selected";
2789 ot->description = "Copy modifiers to other selected objects";
2790
2793
2795}
2796
2799/* ------------------------------------------------------------------- */
2804{
2805 Mesh *mesh = static_cast<Mesh *>(ob->data);
2806 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
2807 BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
2808 }
2809 else {
2810 CustomData_free_layer_active(&mesh->vert_data, CD_MVERT_SKIN, mesh->verts_num);
2811 }
2812}
2813
2814static bool skin_poll(bContext *C)
2815{
2816 return edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), false, false);
2817}
2818
2820{
2822 return (ob != nullptr &&
2823 edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), true, false) &&
2825}
2826
2827static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset)
2828{
2829 BMEdge *bm_edge;
2830 BMIter bm_iter;
2831
2832 BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) {
2833 BMVert *v2 = BM_edge_other_vert(bm_edge, bm_vert);
2834
2835 if (BLI_gset_add(visited, v2)) {
2836 MVertSkin *vs = static_cast<MVertSkin *>(BM_ELEM_CD_GET_VOID_P(v2, cd_vert_skin_offset));
2837
2838 /* clear vertex root flag and add to visited set */
2839 vs->flag &= ~MVERT_SKIN_ROOT;
2840
2841 skin_root_clear(v2, visited, cd_vert_skin_offset);
2842 }
2843 }
2844}
2845
2847{
2850 BMesh *bm = em->bm;
2851
2852 GSet *visited = BLI_gset_ptr_new(__func__);
2853
2854 BKE_mesh_ensure_skin_customdata(static_cast<Mesh *>(ob->data));
2855
2856 const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
2857
2858 BMVert *bm_vert;
2859 BMIter bm_iter;
2860 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
2861 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) && BLI_gset_add(visited, bm_vert)) {
2862 MVertSkin *vs = static_cast<MVertSkin *>(
2863 BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset));
2864
2865 /* mark vertex as root and add to visited set */
2866 vs->flag |= MVERT_SKIN_ROOT;
2867
2868 /* clear root flag from all connected vertices (recursively) */
2869 skin_root_clear(bm_vert, visited, cd_vert_skin_offset);
2870 }
2871 }
2872
2873 BLI_gset_free(visited, nullptr);
2874
2877
2878 return OPERATOR_FINISHED;
2879}
2880
2882{
2883 ot->name = "Skin Root Mark";
2884 ot->description = "Mark selected vertices as roots";
2885 ot->idname = "OBJECT_OT_skin_root_mark";
2886
2889
2890 /* flags */
2892}
2893
2898
2900{
2903 BMesh *bm = em->bm;
2904 SkinLooseAction action = static_cast<SkinLooseAction>(RNA_enum_get(op->ptr, "action"));
2905
2907 return OPERATOR_CANCELLED;
2908 }
2909
2910 BMVert *bm_vert;
2911 BMIter bm_iter;
2912 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
2913 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
2914 MVertSkin *vs = static_cast<MVertSkin *>(
2916
2917 switch (action) {
2918 case SKIN_LOOSE_MARK:
2919 vs->flag |= MVERT_SKIN_LOOSE;
2920 break;
2921 case SKIN_LOOSE_CLEAR:
2922 vs->flag &= ~MVERT_SKIN_LOOSE;
2923 break;
2924 }
2925 }
2926 }
2927
2930
2931 return OPERATOR_FINISHED;
2932}
2933
2935{
2936 static const EnumPropertyItem action_items[] = {
2937 {SKIN_LOOSE_MARK, "MARK", 0, "Mark", "Mark selected vertices as loose"},
2938 {SKIN_LOOSE_CLEAR, "CLEAR", 0, "Clear", "Set selected vertices as not loose"},
2939 {0, nullptr, 0, nullptr, nullptr},
2940 };
2941
2942 ot->name = "Skin Mark/Clear Loose";
2943 ot->description = "Mark/clear selected vertices as loose";
2944 ot->idname = "OBJECT_OT_skin_loose_mark_clear";
2945
2948
2949 /* flags */
2951
2952 RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", nullptr);
2953}
2954
2956{
2959 BMesh *bm = em->bm;
2960
2962 return OPERATOR_CANCELLED;
2963 }
2964
2965 BMVert *bm_vert;
2966 BMIter bm_iter;
2967 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
2968 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
2969 MVertSkin *vs = static_cast<MVertSkin *>(
2971 float avg = (vs->radius[0] + vs->radius[1]) * 0.5f;
2972
2973 vs->radius[0] = vs->radius[1] = avg;
2974 }
2975 }
2976
2979
2980 return OPERATOR_FINISHED;
2981}
2982
2984{
2985 ot->name = "Skin Radii Equalize";
2986 ot->description = "Make skin radii of selected vertices equal on each axis";
2987 ot->idname = "OBJECT_OT_skin_radii_equalize";
2988
2991
2992 /* flags */
2994}
2995
2997 const Span<float3> positions,
2998 const int2 *edges,
2999 bArmature *arm,
3000 BLI_bitmap *edges_visited,
3001 const GroupedSpan<int> emap,
3002 EditBone *parent_bone,
3003 int parent_v)
3004{
3005 for (int i = 0; i < emap[parent_v].size(); i++) {
3006 int endx = emap[parent_v][i];
3007 const int2 &edge = edges[endx];
3008
3009 /* ignore edge if already visited */
3010 if (BLI_BITMAP_TEST(edges_visited, endx)) {
3011 continue;
3012 }
3013 BLI_BITMAP_ENABLE(edges_visited, endx);
3014
3015 int v = bke::mesh::edge_other_vert(edge, parent_v);
3016
3017 EditBone *bone = ED_armature_ebone_add(arm, "Bone");
3018
3019 bone->parent = parent_bone;
3020 if (parent_bone != nullptr) {
3021 bone->flag |= BONE_CONNECTED;
3022 }
3023
3024 copy_v3_v3(bone->head, positions[parent_v]);
3025 copy_v3_v3(bone->tail, positions[v]);
3026 bone->rad_head = bone->rad_tail = 0.25;
3027 SNPRINTF(bone->name, "Bone.%.2d", endx);
3028
3029 /* add bDeformGroup */
3030 bDeformGroup *dg = BKE_object_defgroup_add_name(skin_ob, bone->name);
3031 if (dg != nullptr) {
3032 blender::ed::object::vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
3034 }
3035
3036 skin_armature_bone_create(skin_ob, positions, edges, arm, edges_visited, emap, bone, v);
3037 }
3038}
3039
3040static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Object *skin_ob)
3041{
3042 Mesh *mesh = static_cast<Mesh *>(skin_ob->data);
3043 const Span<float3> me_positions = mesh->vert_positions();
3044 const Span<int2> me_edges = mesh->edges();
3045
3047 Object *ob_eval = DEG_get_evaluated_object(depsgraph, skin_ob);
3048
3049 const Mesh *me_eval_deform = blender::bke::mesh_get_eval_deform(
3050 depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
3051 const Span<float3> positions_eval = me_eval_deform->vert_positions();
3052
3053 /* add vertex weights to original mesh */
3054 CustomData_add_layer(&mesh->vert_data, CD_MDEFORMVERT, CD_SET_DEFAULT, mesh->verts_num);
3055
3058 Object *arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, nullptr);
3059 BKE_object_transform_copy(arm_ob, skin_ob);
3060 bArmature *arm = static_cast<bArmature *>(arm_ob->data);
3062 arm_ob->dtx |= OB_DRAW_IN_FRONT;
3063 arm->drawtype = ARM_LINE;
3064 arm->edbo = MEM_cnew<ListBase>("edbo armature");
3065
3066 MVertSkin *mvert_skin = static_cast<MVertSkin *>(
3067 CustomData_get_layer_for_write(&mesh->vert_data, CD_MVERT_SKIN, mesh->verts_num));
3068
3069 Array<int> vert_to_edge_offsets;
3070 Array<int> vert_to_edge_indices;
3071 const GroupedSpan<int> emap = bke::mesh::build_vert_to_edge_map(
3072 me_edges, mesh->verts_num, vert_to_edge_offsets, vert_to_edge_indices);
3073
3074 BLI_bitmap *edges_visited = BLI_BITMAP_NEW(mesh->edges_num, "edge_visited");
3075
3076 /* NOTE: we use EditBones here, easier to set them up and use
3077 * edit-armature functions to convert back to regular bones */
3078 for (int v = 0; v < mesh->verts_num; v++) {
3079 if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
3080 EditBone *bone = nullptr;
3081
3082 /* Unless the skin root has just one adjacent edge, create
3083 * a fake root bone (have it going off in the Y direction
3084 * (arbitrary) */
3085 if (emap[v].size() > 1) {
3086 bone = ED_armature_ebone_add(arm, "Bone");
3087
3088 copy_v3_v3(bone->head, me_positions[v]);
3089 copy_v3_v3(bone->tail, me_positions[v]);
3090
3091 bone->head[1] = 1.0f;
3092 bone->rad_head = bone->rad_tail = 0.25;
3093 }
3094
3095 if (emap[v].size() >= 1) {
3097 skin_ob, positions_eval, me_edges.data(), arm, edges_visited, emap, bone, v);
3098 }
3099 }
3100 }
3101
3102 MEM_freeN(edges_visited);
3103
3104 ED_armature_from_edit(bmain, arm);
3106
3107 return arm_ob;
3108}
3109
3111{
3112 Main *bmain = CTX_data_main(C);
3115 Mesh *mesh = static_cast<Mesh *>(ob->data);
3116 ModifierData *skin_md;
3117
3118 if (!CustomData_has_layer(&mesh->vert_data, CD_MVERT_SKIN)) {
3119 BKE_reportf(op->reports, RPT_WARNING, "Mesh '%s' has no skin vertex data", mesh->id.name + 2);
3120 return OPERATOR_CANCELLED;
3121 }
3122
3123 /* create new armature */
3124 Object *arm_ob = modifier_skin_armature_create(depsgraph, bmain, ob);
3125
3126 /* add a modifier to connect the new armature to the mesh */
3128 if (arm_md) {
3130 BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md);
3132
3133 arm_md->object = arm_ob;
3137 }
3138
3140
3141 return OPERATOR_FINISHED;
3142}
3143
3144static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
3145{
3147 return skin_armature_create_exec(C, op);
3148 }
3149 return OPERATOR_CANCELLED;
3150}
3151
3153{
3154 ot->name = "Skin Armature Create";
3155 ot->description = "Create an armature that parallels the skin layout";
3156 ot->idname = "OBJECT_OT_skin_armature_create";
3157
3158 ot->poll = skin_poll;
3161
3162 /* flags */
3165}
3166
3169/* ------------------------------------------------------------------- */
3174{
3175 return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0, true, false);
3176}
3177
3179{
3181 Scene *scene = CTX_data_scene(C);
3185
3186 if (!csmd) {
3187 return OPERATOR_CANCELLED;
3188 }
3189
3191 BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
3192 return OPERATOR_CANCELLED;
3193 }
3194
3195 const bool is_bind = (csmd->bind_coords != nullptr);
3196
3199
3200 if (is_bind) {
3201 /* toggle off */
3202 csmd->bind_coords_num = 0;
3203 }
3204 else {
3205 /* Signal to modifier to recalculate. */
3208 csmd_eval->bind_coords_num = uint(-1);
3209
3210 /* Force modifier to run, it will call binding routine
3211 * (this has to happen outside of depsgraph evaluation). */
3213 }
3214
3217
3218 return OPERATOR_FINISHED;
3219}
3220
3221static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
3222{
3224 return correctivesmooth_bind_exec(C, op);
3225 }
3226 return OPERATOR_CANCELLED;
3227}
3228
3230{
3231 /* identifiers */
3232 ot->name = "Corrective Smooth Bind";
3233 ot->description = "Bind base pose in Corrective Smooth modifier";
3234 ot->idname = "OBJECT_OT_correctivesmooth_bind";
3235
3236 /* api callbacks */
3240
3241 /* flags */
3244}
3245
3248/* ------------------------------------------------------------------- */
3253{
3254 return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0, true, false);
3255}
3256
3258{
3262 op, ob, eModifierType_MeshDeform);
3263
3264 if (mmd == nullptr) {
3265 return OPERATOR_CANCELLED;
3266 }
3267
3268 if (mmd->bindcagecos != nullptr) {
3270 MEM_SAFE_FREE(mmd->dyngrid);
3274 MEM_SAFE_FREE(mmd->dynverts);
3275 MEM_SAFE_FREE(mmd->bindweights); /* Deprecated */
3276 MEM_SAFE_FREE(mmd->bindcos); /* Deprecated */
3277 mmd->verts_num = 0;
3278 mmd->cage_verts_num = 0;
3279 mmd->influences_num = 0;
3280 }
3281 else {
3282 /* Force modifier to run, it will call binding routine
3283 * (this has to happen outside of depsgraph evaluation). */
3285 depsgraph, ob, &mmd->modifier);
3288 mmd_eval->bindfunc = nullptr;
3289 }
3290
3293 return OPERATOR_FINISHED;
3294}
3295
3296static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
3297{
3299 return meshdeform_bind_exec(C, op);
3300 }
3301 return OPERATOR_CANCELLED;
3302}
3303
3305{
3306 /* identifiers */
3307 ot->name = "Mesh Deform Bind";
3308 ot->description = "Bind mesh to cage in mesh deform modifier";
3309 ot->idname = "OBJECT_OT_meshdeform_bind";
3310
3311 /* api callbacks */
3315
3316 /* flags */
3319}
3320
3323/* ------------------------------------------------------------------- */
3327static bool explode_poll(bContext *C)
3328{
3329 return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0, true, false);
3330}
3331
3333{
3336 op, ob, eModifierType_Explode);
3337
3338 if (!emd) {
3339 return OPERATOR_CANCELLED;
3340 }
3341
3343
3346
3347 return OPERATOR_FINISHED;
3348}
3349
3350static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
3351{
3353 return explode_refresh_exec(C, op);
3354 }
3355 return OPERATOR_CANCELLED;
3356}
3357
3359{
3360 ot->name = "Explode Refresh";
3361 ot->description = "Refresh data in the Explode modifier";
3362 ot->idname = "OBJECT_OT_explode_refresh";
3363
3364 ot->poll = explode_poll;
3367
3368 /* flags */
3371}
3372
3375/* ------------------------------------------------------------------- */
3380{
3381 return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0, true, false);
3382}
3383
3394
3395static void oceanbake_free(void *customdata)
3396{
3397 OceanBakeJob *oj = static_cast<OceanBakeJob *>(customdata);
3398 MEM_delete(oj);
3399}
3400
3401/* called by oceanbake, only to check job 'stop' value */
3402static int oceanbake_breakjob(void * /*customdata*/)
3403{
3404 // OceanBakeJob *ob = (OceanBakeJob *)customdata;
3405 // return *(ob->stop);
3406
3407 /* this is not nice yet, need to make the jobs list template better
3408 * for identifying/acting upon various different jobs */
3409 /* but for now we'll reuse the render break... */
3410 return (G.is_break);
3411}
3412
3413/* called by oceanbake, wmJob sends notifier */
3414static void oceanbake_update(void *customdata, float progress, int *cancel)
3415{
3416 OceanBakeJob *oj = static_cast<OceanBakeJob *>(customdata);
3417
3418 if (oceanbake_breakjob(oj)) {
3419 *cancel = 1;
3420 }
3421
3422 *(oj->do_update) = true;
3423 *(oj->progress) = progress;
3424}
3425
3426static void oceanbake_startjob(void *customdata, wmJobWorkerStatus *worker_status)
3427{
3428 OceanBakeJob *oj = static_cast<OceanBakeJob *>(customdata);
3429
3430 oj->stop = &worker_status->stop;
3431 oj->do_update = &worker_status->do_update;
3432 oj->progress = &worker_status->progress;
3433
3434 G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
3435
3436 BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
3437
3438 worker_status->do_update = true;
3439 worker_status->stop = false;
3440}
3441
3442static void oceanbake_endjob(void *customdata)
3443{
3444 OceanBakeJob *oj = static_cast<OceanBakeJob *>(customdata);
3445
3446 if (oj->ocean) {
3447 BKE_ocean_free(oj->ocean);
3448 oj->ocean = nullptr;
3449 }
3450
3451 oj->omd->oceancache = oj->och;
3452 oj->omd->cached = true;
3453
3454 Object *ob = oj->owner;
3456}
3457
3459{
3460 Main *bmain = CTX_data_main(C);
3463 op, ob, eModifierType_Ocean);
3464 Scene *scene = CTX_data_scene(C);
3465 const bool free = RNA_boolean_get(op->ptr, "free");
3466
3467 if (!omd) {
3468 return OPERATOR_CANCELLED;
3469 }
3470
3471 if (free) {
3475 return OPERATOR_FINISHED;
3476 }
3477
3479 BKE_modifier_path_relbase(bmain, ob),
3480 omd->bakestart,
3481 omd->bakeend,
3482 omd->wave_scale,
3483 omd->chop_amount,
3484 omd->foam_coverage,
3485 omd->foam_fade,
3486 omd->resolution);
3487
3488 och->time = static_cast<float *>(MEM_mallocN(och->duration * sizeof(float), "foam bake time"));
3489
3490 int cfra = scene->r.cfra;
3491
3492 /* precalculate time variable before baking */
3493 int i = 0;
3494 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
3495 for (int f = omd->bakestart; f <= omd->bakeend; f++) {
3496 /* For now only simple animation of time value is supported, nothing else.
3497 * No drivers or other modifier parameters. */
3498 /* TODO(sergey): This operates on an original data, so no flush is needed. However, baking
3499 * usually should happen on an evaluated objects, so this seems to be deeper issue here. */
3500
3502 f);
3503 BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, &anim_eval_context, ADT_RECALC_ANIM, false);
3504
3505 och->time[i] = omd->time;
3506 i++;
3507 }
3508
3509 /* Make a copy of ocean to use for baking - thread-safety. */
3510 Ocean *ocean = BKE_ocean_add();
3511 BKE_ocean_init_from_modifier(ocean, omd, omd->resolution);
3512
3513#if 0
3514 BKE_ocean_bake(ocean, och);
3515
3516 omd->oceancache = och;
3517 omd->cached = true;
3518
3519 scene->r.cfra = cfra;
3520
3523#endif
3524
3525 /* job stuff */
3526
3527 scene->r.cfra = cfra;
3528
3529 /* setup job */
3530 wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
3531 CTX_wm_window(C),
3532 scene,
3533 "Ocean Simulation",
3536 OceanBakeJob *oj = MEM_cnew<OceanBakeJob>("ocean bake job");
3537 oj->owner = ob;
3538 oj->ocean = ocean;
3539 oj->och = och;
3540 oj->omd = omd;
3541
3544 WM_jobs_callbacks(wm_job, oceanbake_startjob, nullptr, nullptr, oceanbake_endjob);
3545
3546 WM_jobs_start(CTX_wm_manager(C), wm_job);
3547
3548 return OPERATOR_FINISHED;
3549}
3550
3551static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
3552{
3554 return ocean_bake_exec(C, op);
3555 }
3556 return OPERATOR_CANCELLED;
3557}
3558
3560{
3561 ot->name = "Bake Ocean";
3562 ot->description = "Bake an image sequence of ocean data";
3563 ot->idname = "OBJECT_OT_ocean_bake";
3564
3568
3569 /* flags */
3572
3573 RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
3574}
3575
3578/* ------------------------------------------------------------------- */
3583{
3584 return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0, false, false);
3585}
3586
3588{
3593
3594 if (lmd == nullptr) {
3595 return OPERATOR_CANCELLED;
3596 }
3597
3598 if (lmd->flag & MOD_LAPLACIANDEFORM_BIND) {
3599 lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
3600 }
3601 else {
3603 }
3604
3607 lmd_eval->flag = lmd->flag;
3608
3609 /* Force modifier to run, it will call binding routine
3610 * (this has to happen outside of depsgraph evaluation). */
3612
3613 /* This is hard to know from the modifier itself whether the evaluation is
3614 * happening for binding or not. So we copy all the required data here. */
3615 lmd->verts_num = lmd_eval->verts_num;
3616 if (lmd_eval->vertexco == nullptr) {
3617 MEM_SAFE_FREE(lmd->vertexco);
3618 }
3619 else {
3620 lmd->vertexco = static_cast<float *>(MEM_dupallocN(lmd_eval->vertexco));
3621 }
3622
3625 return OPERATOR_FINISHED;
3626}
3627
3628static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
3629{
3631 return laplaciandeform_bind_exec(C, op);
3632 }
3633 return OPERATOR_CANCELLED;
3634}
3635
3637{
3638 /* identifiers */
3639 ot->name = "Laplacian Deform Bind";
3640 ot->description = "Bind mesh to system in laplacian deform modifier";
3641 ot->idname = "OBJECT_OT_laplaciandeform_bind";
3642
3643 /* api callbacks */
3647
3648 /* flags */
3651}
3652
3655/* ------------------------------------------------------------------- */
3660{
3661 return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0, true, false);
3662}
3663
3665{
3670
3671 if (smd == nullptr) {
3672 return OPERATOR_CANCELLED;
3673 }
3674
3675 if (smd->flags & MOD_SDEF_BIND) {
3676 smd->flags &= ~MOD_SDEF_BIND;
3677 }
3678 else if (smd->target) {
3679 smd->flags |= MOD_SDEF_BIND;
3680 }
3681
3683 depsgraph, ob, &smd->modifier);
3684 smd_eval->flags = smd->flags;
3685
3686 /* Force modifier to run, it will call binding routine
3687 * (this has to happen outside of depsgraph evaluation). */
3689
3692 return OPERATOR_FINISHED;
3693}
3694
3695static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
3696{
3698 return surfacedeform_bind_exec(C, op);
3699 }
3700 return OPERATOR_CANCELLED;
3701}
3702
3704{
3705 /* identifiers */
3706 ot->name = "Surface Deform Bind";
3707 ot->description = "Bind mesh to target in surface deform modifier";
3708 ot->idname = "OBJECT_OT_surfacedeform_bind";
3709
3710 /* api callbacks */
3714
3715 /* flags */
3718}
3719
3722/* ------------------------------------------------------------------- */
3731{
3733
3734 char modifier_name[MAX_NAME];
3735 RNA_string_get(op->ptr, "modifier_name", modifier_name);
3737 if (nmd == nullptr) {
3738 return OPERATOR_CANCELLED;
3739 }
3740
3741 char input_name[MAX_NAME];
3742 RNA_string_get(op->ptr, "input_name", input_name);
3743
3744 IDProperty *use_attribute = IDP_GetPropertyFromGroup(
3745 nmd->settings.properties, std::string(input_name + std::string("_use_attribute")).c_str());
3746 if (!use_attribute) {
3747 return OPERATOR_CANCELLED;
3748 }
3749
3750 if (use_attribute->type == IDP_INT) {
3751 IDP_Int(use_attribute) = !IDP_Int(use_attribute);
3752 }
3753 else if (use_attribute->type == IDP_BOOLEAN) {
3754 IDP_Bool(use_attribute) = !IDP_Bool(use_attribute);
3755 }
3756 else {
3757 return OPERATOR_CANCELLED;
3758 }
3759
3762 return OPERATOR_FINISHED;
3763}
3764
3766{
3767 ot->name = "Input Attribute Toggle";
3768 ot->description =
3769 "Switch between an attribute and a single value to define the data for every element";
3770 ot->idname = "OBJECT_OT_geometry_nodes_input_attribute_toggle";
3771
3774
3776
3777 RNA_def_string(ot->srna, "input_name", nullptr, 0, "Input Name", "");
3778 RNA_def_string(ot->srna, "modifier_name", nullptr, MAX_NAME, "Modifier Name", "");
3779}
3780
3783/* ------------------------------------------------------------------- */
3788{
3789 Main *bmain = CTX_data_main(C);
3792 if (!(md && md->type == eModifierType_Nodes)) {
3793 return OPERATOR_CANCELLED;
3794 }
3795
3797 bNodeTree *tree = nmd->node_group;
3798 if (tree == nullptr) {
3799 return OPERATOR_CANCELLED;
3800 }
3801
3802 bNodeTree *new_tree = (bNodeTree *)BKE_id_copy_ex(
3803 bmain, &tree->id, nullptr, LIB_ID_COPY_ACTIONS | LIB_ID_COPY_DEFAULT);
3804
3805 nmd->flag &= ~NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR;
3806
3807 if (new_tree == nullptr) {
3808 return OPERATOR_CANCELLED;
3809 }
3810
3811 nmd->node_group = new_tree;
3812 id_us_min(&tree->id);
3813
3817 return OPERATOR_FINISHED;
3818}
3819
3821{
3822 ot->name = "Copy Geometry Node Group";
3823 ot->description = "Copy the active geometry node group and assign it to the active modifier";
3824 ot->idname = "OBJECT_OT_geometry_node_tree_copy_assign";
3825
3828
3830}
3831
3834/* ------------------------------------------------------------------- */
3839{
3840 return edit_modifier_poll_generic(C, &RNA_GreasePencilDashModifierData, 0, false, false);
3841}
3842
3844{
3846 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(
3848
3849 if (dmd == nullptr) {
3850 return OPERATOR_CANCELLED;
3851 }
3852
3854 MEM_malloc_arrayN(dmd->segments_num + 1, sizeof(GreasePencilDashModifierSegment), __func__));
3855
3856 const int new_active_index = std::clamp(dmd->segment_active_index + 1, 0, dmd->segments_num);
3857 if (dmd->segments_num != 0) {
3858 /* Copy the segments before the new segment. */
3859 memcpy(new_segments,
3860 dmd->segments_array,
3861 sizeof(GreasePencilDashModifierSegment) * new_active_index);
3862 /* Copy the segments after the new segment. */
3863 memcpy(new_segments + new_active_index + 1,
3864 dmd->segments_array + new_active_index,
3865 sizeof(GreasePencilDashModifierSegment) * (dmd->segments_num - new_active_index));
3866 }
3867
3868 /* Create the new segment. */
3869 GreasePencilDashModifierSegment *ds = &new_segments[new_active_index];
3870 memcpy(ds,
3874 [&](const StringRef name) {
3875 for (const GreasePencilDashModifierSegment &ds : dmd->segments()) {
3876 if (STREQ(ds.name, name.data())) {
3877 return true;
3878 }
3879 }
3880 return false;
3881 },
3882 '.',
3883 ds->name);
3884
3885 MEM_SAFE_FREE(dmd->segments_array);
3886 dmd->segments_array = new_segments;
3887 dmd->segments_num++;
3888 dmd->segment_active_index = new_active_index;
3889
3892
3893 return OPERATOR_FINISHED;
3894}
3895
3896static int dash_modifier_segment_add_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
3897{
3899 return dash_modifier_segment_add_exec(C, op);
3900 }
3901 return OPERATOR_CANCELLED;
3902}
3903
3905{
3906 /* identifiers */
3907 ot->name = "Add Segment";
3908 ot->description = "Add a segment to the dash modifier";
3909 ot->idname = "OBJECT_OT_grease_pencil_dash_modifier_segment_add";
3910
3911 /* api callbacks */
3915
3916 /* flags */
3919}
3920
3922
3924{
3926 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(
3928
3929 if (dmd == nullptr) {
3930 return OPERATOR_CANCELLED;
3931 }
3932
3933 if (!dmd->segments().index_range().contains(dmd->segment_active_index)) {
3934 return OPERATOR_CANCELLED;
3935 }
3936
3937 dna::array::remove_index(&dmd->segments_array,
3938 &dmd->segments_num,
3939 &dmd->segment_active_index,
3940 dmd->segment_active_index,
3942
3945
3946 return OPERATOR_FINISHED;
3947}
3948
3950 wmOperator *op,
3951 const wmEvent * /*event*/)
3952{
3955 }
3956 return OPERATOR_CANCELLED;
3957}
3958
3960{
3961 /* identifiers */
3962 ot->name = "Remove Dash Segment";
3963 ot->description = "Remove the active segment from the dash modifier";
3964 ot->idname = "OBJECT_OT_grease_pencil_dash_modifier_segment_remove";
3965
3966 /* api callbacks */
3970
3971 /* flags */
3974
3976 ot->srna, "index", 0, 0, INT_MAX, "Index", "Index of the segment to remove", 0, INT_MAX);
3977}
3978
3980 Up = -1,
3981 Down = 1,
3982};
3983
3985{
3987 auto *dmd = reinterpret_cast<GreasePencilDashModifierData *>(
3989
3990 if (dmd == nullptr) {
3991 return OPERATOR_CANCELLED;
3992 }
3993
3994 if (dmd->segments_num < 2) {
3995 return OPERATOR_CANCELLED;
3996 }
3997
3999 RNA_enum_get(op->ptr, "type"));
4000 switch (direction) {
4001 case DashSegmentMoveDirection::Up:
4002 if (dmd->segment_active_index == 0) {
4003 return OPERATOR_CANCELLED;
4004 }
4005
4006 std::swap(dmd->segments_array[dmd->segment_active_index],
4007 dmd->segments_array[dmd->segment_active_index - 1]);
4008
4009 dmd->segment_active_index--;
4010 break;
4011 case DashSegmentMoveDirection::Down:
4012 if (dmd->segment_active_index == dmd->segments_num - 1) {
4013 return OPERATOR_CANCELLED;
4014 }
4015
4016 std::swap(dmd->segments_array[dmd->segment_active_index],
4017 dmd->segments_array[dmd->segment_active_index + 1]);
4018
4019 dmd->segment_active_index++;
4020 break;
4021 default:
4022 return OPERATOR_CANCELLED;
4023 }
4024
4027
4028 return OPERATOR_FINISHED;
4029}
4030
4032 wmOperator *op,
4033 const wmEvent * /*event*/)
4034{
4036 return dash_modifier_segment_move_exec(C, op);
4037 }
4038 return OPERATOR_CANCELLED;
4039}
4040
4042{
4043 static const EnumPropertyItem segment_move[] = {
4044 {int(DashSegmentMoveDirection::Up), "UP", 0, "Up", ""},
4045 {int(DashSegmentMoveDirection::Down), "DOWN", 0, "Down", ""},
4046 {0, nullptr, 0, nullptr, nullptr},
4047 };
4048
4049 /* identifiers */
4050 ot->name = "Move Dash Segment";
4051 ot->description = "Move the active dash segment up or down";
4052 ot->idname = "OBJECT_OT_grease_pencil_dash_modifier_segment_move";
4053
4054 /* api callbacks */
4058
4059 /* flags */
4062
4063 ot->prop = RNA_def_enum(ot->srna, "type", segment_move, 0, "Type", "");
4064}
4065
4068/* ------------------------------------------------------------------- */
4073{
4074 return edit_modifier_poll_generic(C, &RNA_GreasePencilTimeModifier, 0, false, false);
4075}
4076
4078{
4080 auto *tmd = reinterpret_cast<GreasePencilTimeModifierData *>(
4082
4083 if (tmd == nullptr) {
4084 return OPERATOR_CANCELLED;
4085 }
4086
4088 MEM_malloc_arrayN(tmd->segments_num + 1, sizeof(GreasePencilTimeModifierSegment), __func__));
4089
4090 const int new_active_index = std::clamp(tmd->segment_active_index + 1, 0, tmd->segments_num);
4091 if (tmd->segments_num != 0) {
4092 /* Copy the segments before the new segment. */
4093 memcpy(new_segments,
4094 tmd->segments_array,
4095 sizeof(GreasePencilTimeModifierSegment) * new_active_index);
4096 /* Copy the segments after the new segment. */
4097 memcpy(new_segments + new_active_index + 1,
4098 tmd->segments_array + new_active_index,
4099 sizeof(GreasePencilTimeModifierSegment) * (tmd->segments_num - new_active_index));
4100 }
4101
4102 /* Create the new segment. */
4103 GreasePencilTimeModifierSegment *segment = &new_segments[new_active_index];
4104 memcpy(segment,
4108 [&](const StringRef name) {
4109 for (const GreasePencilTimeModifierSegment &segment : tmd->segments()) {
4110 if (STREQ(segment.name, name.data())) {
4111 return true;
4112 }
4113 }
4114 return false;
4115 },
4116 '.',
4117 segment->name);
4118
4119 MEM_SAFE_FREE(tmd->segments_array);
4120 tmd->segments_array = new_segments;
4121 tmd->segments_num++;
4122 tmd->segment_active_index++;
4123
4126
4127 return OPERATOR_FINISHED;
4128}
4129
4130static int time_modifier_segment_add_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
4131{
4133 return time_modifier_segment_add_exec(C, op);
4134 }
4135 return OPERATOR_CANCELLED;
4136}
4137
4139{
4140 /* identifiers */
4141 ot->name = "Add Segment";
4142 ot->description = "Add a segment to the time modifier";
4143 ot->idname = "OBJECT_OT_grease_pencil_time_modifier_segment_add";
4144
4145 /* api callbacks */
4149
4150 /* flags */
4153}
4154
4156
4158{
4160 auto *tmd = reinterpret_cast<GreasePencilTimeModifierData *>(
4162
4163 if (tmd == nullptr) {
4164 return OPERATOR_CANCELLED;
4165 }
4166
4167 if (!tmd->segments().index_range().contains(tmd->segment_active_index)) {
4168 return OPERATOR_CANCELLED;
4169 }
4170
4171 dna::array::remove_index(&tmd->segments_array,
4172 &tmd->segments_num,
4173 &tmd->segment_active_index,
4174 tmd->segment_active_index,
4176
4179
4180 return OPERATOR_FINISHED;
4181}
4182
4184 wmOperator *op,
4185 const wmEvent * /*event*/)
4186{
4189 }
4190 return OPERATOR_CANCELLED;
4191}
4192
4194{
4195 /* identifiers */
4196 ot->name = "Remove Segment";
4197 ot->description = "Remove the active segment from the time modifier";
4198 ot->idname = "OBJECT_OT_grease_pencil_time_modifier_segment_remove";
4199
4200 /* api callbacks */
4204
4205 /* flags */
4208
4210 ot->srna, "index", 0, 0, INT_MAX, "Index", "Index of the segment to remove", 0, INT_MAX);
4211}
4212
4214 Up = -1,
4215 Down = 1,
4216};
4217
4219{
4221 auto *tmd = reinterpret_cast<GreasePencilTimeModifierData *>(
4223
4224 if (tmd == nullptr) {
4225 return OPERATOR_CANCELLED;
4226 }
4227
4228 if (tmd->segments_num < 2) {
4229 return OPERATOR_CANCELLED;
4230 }
4231
4233 RNA_enum_get(op->ptr, "type"));
4234 switch (direction) {
4235 case TimeSegmentMoveDirection::Up:
4236 if (tmd->segment_active_index == 0) {
4237 return OPERATOR_CANCELLED;
4238 }
4239
4240 std::swap(tmd->segments_array[tmd->segment_active_index],
4241 tmd->segments_array[tmd->segment_active_index - 1]);
4242
4243 tmd->segment_active_index--;
4244 break;
4245 case TimeSegmentMoveDirection::Down:
4246 if (tmd->segment_active_index == tmd->segments_num - 1) {
4247 return OPERATOR_CANCELLED;
4248 }
4249
4250 std::swap(tmd->segments_array[tmd->segment_active_index],
4251 tmd->segments_array[tmd->segment_active_index + 1]);
4252
4253 tmd->segment_active_index++;
4254 break;
4255 default:
4256 return OPERATOR_CANCELLED;
4257 }
4258
4261
4262 return OPERATOR_FINISHED;
4263}
4264
4266 wmOperator *op,
4267 const wmEvent * /*event*/)
4268{
4270 return time_modifier_segment_move_exec(C, op);
4271 }
4272 return OPERATOR_CANCELLED;
4273}
4274
4276{
4277 static const EnumPropertyItem segment_move[] = {
4278 {int(TimeSegmentMoveDirection::Up), "UP", 0, "Up", ""},
4279 {int(TimeSegmentMoveDirection::Down), "DOWN", 0, "Down", ""},
4280 {0, nullptr, 0, nullptr, nullptr},
4281 };
4282
4283 /* identifiers */
4284 ot->name = "Move Segment";
4285 ot->description = "Move the active time segment up or down";
4286 ot->idname = "OBJECT_OT_grease_pencil_time_modifier_segment_move";
4287
4288 /* api callbacks */
4292
4293 /* flags */
4296
4297 ot->prop = RNA_def_enum(ot->srna, "type", segment_move, 0, "Type", "");
4298}
4299
4302} // namespace blender::ed::object
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
void ANIM_armature_bonecoll_show_all(bArmature *armature)
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time) ATTR_WARN_UNUSED_RESULT
Definition anim_sys.cc:734
@ ADT_RECALC_ANIM
void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, bool flush_to_original)
AttrDomainMask
#define ATTR_DOMAIN_MASK_COLOR
#define ATTR_DOMAIN_AS_MASK(domain)
#define CTX_DATA_BEGIN(C, Type, instance, member)
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(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)
bool CTX_data_selected_objects(const bContext *C, blender::Vector< PointerRNA > *list)
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
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_curve_nurbs_vert_coords_apply(ListBase *lb, const float(*vert_coords)[3], bool constrain_2d)
Definition curve.cc:4602
float(* BKE_curve_nurbs_vert_coords_alloc(const ListBase *lb, int *r_vert_len))[3]
Definition curve.cc:4555
Low-level operations for curves that cannot be defined in the C++ header yet.
void BKE_curves_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object)
Low-level operations for curves.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
int CustomData_get_layer_index_n(const CustomData *data, eCustomDataType type, int n)
@ CD_SET_DEFAULT
@ CD_CONSTRUCT
void * CustomData_add_layer_named(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem, blender::StringRef name)
bool CustomData_free_layer_active(CustomData *data, eCustomDataType type, int totelem)
void * CustomData_bmesh_get(const CustomData *data, void *block, eCustomDataType type)
const CustomData_MeshMasks CD_MASK_BAREMESH
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
const void * CustomData_add_layer_with_data(CustomData *data, eCustomDataType type, void *layer_data, int totelem, const blender::ImplicitSharingInfo *sharing_info)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
const CustomData_MeshMasks CD_MASK_DERIVEDMESH
#define CD_TYPE_AS_MASK(_type)
display list (or rather multi purpose list) stuff.
void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, bool for_render)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:63
struct PartDeflect * BKE_partdeflect_new(int type)
Definition effect.cc:71
Low-level operations for grease pencil.
#define IDP_Int(prop)
#define IDP_Bool(prop)
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:763
Key * BKE_key_add(Main *bmain, ID *id)
Definition key.cc:256
KeyBlock * BKE_keyblock_add(Key *key, const char *name)
Definition key.cc:1831
void BKE_keyblock_convert_to_mesh(const KeyBlock *kb, float(*vert_positions)[3], int totvert)
Definition key.cc:2202
void BKE_keyblock_convert_from_mesh(const Mesh *mesh, const Key *key, KeyBlock *kb)
Definition key.cc:2186
void BKE_lattice_vert_coords_apply(Lattice *lt, const float(*vert_coords)[3])
Definition lattice.cc:508
float(* BKE_lattice_vert_coords_alloc(const Lattice *lt, int *r_vert_len))[3]
Definition lattice.cc:489
void BKE_lattice_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
Definition lattice.cc:516
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2456
@ LIB_ID_COPY_ACTIONS
@ LIB_ID_COPY_LOCALIZE
@ LIB_ID_COPY_DEFAULT
void BKE_id_free(Main *bmain, void *idv)
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:1947
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:760
void id_us_min(ID *id)
Definition lib_id.cc:359
General operations, lookup, etc. for materials.
void BKE_object_material_from_eval_data(struct Main *bmain, struct Object *ob_orig, const struct ID *data_eval)
void BKE_mball_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
Definition mball.cc:625
void BKE_mesh_ensure_skin_customdata(Mesh *mesh)
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *mesh)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
@ eModifierTypeFlag_Single
@ eModifierTypeFlag_NoUserAdd
@ eModifierTypeFlag_RequiresOriginalData
ModifierData * BKE_modifier_get_original(const Object *object, ModifierData *md)
ModifierData * BKE_modifiers_findby_name(const Object *ob, const char *name)
const char * BKE_modifier_path_relbase(Main *bmain, Object *ob)
bool BKE_modifier_is_same_topology(ModifierData *md)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
void BKE_modifier_free(ModifierData *md)
bool BKE_modifier_is_nonlocal_in_liboverride(const Object *ob, const ModifierData *md)
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md)
ModifierData * BKE_modifier_get_evaluated(Depsgraph *depsgraph, Object *object, ModifierData *md)
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data)
ModifierData * BKE_modifier_new(int type)
@ MOD_APPLY_TO_ORIGINAL
void BKE_modifier_copydata(const ModifierData *md, ModifierData *target)
void multires_customdata_delete(Mesh *mesh)
Definition multires.cc:64
bool multiresModifier_reshapeFromDeformModifier(Depsgraph *depsgraph, Object *ob, MultiresModifierData *mmd, ModifierData *deform_md)
MultiresModifierData * find_multires_modifier_before(Scene *scene, ModifierData *lastmd)
Definition multires.cc:289
void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
Definition multires.cc:509
void multires_force_sculpt_rebuild(Object *object)
Definition multires.cc:451
void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl)
Definition multires.cc:351
General operations, lookup, etc. for blender objects.
void BKE_object_eval_reset(Object *ob_eval)
void BKE_object_modifier_set_active(Object *ob, ModifierData *md)
bool BKE_object_is_in_editmode(const Object *ob)
bool BKE_object_supports_modifiers(const Object *ob)
Object * BKE_object_add(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
ModifierData * BKE_object_active_modifier(const Object *ob)
void BKE_object_link_modifiers(Object *ob_dst, const Object *ob_src)
bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
bool BKE_object_copy_modifier(Main *bmain, const Scene *scene, Object *ob_dst, const Object *ob_src, const ModifierData *md)
void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
void BKE_object_free_derived_caches(Object *ob)
Functions for dealing with objects and deform verts, used by painting and tools.
struct bDeformGroup * BKE_object_defgroup_add_name(struct Object *ob, const char *name)
struct Ocean * BKE_ocean_add(void)
Definition ocean.cc:1577
void BKE_ocean_bake(struct Ocean *o, struct OceanCache *och, void(*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
Definition ocean.cc:1658
void BKE_ocean_free_modifier_cache(struct OceanModifierData *omd)
Definition ocean.cc:1676
bool BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd, int resolution)
void BKE_ocean_free(struct Ocean *oc)
Definition ocean.cc:1612
struct OceanCache * BKE_ocean_init_cache(const char *bakepath, const char *relbase, int start, int end, float wave_scale, float chop_amount, float foam_coverage, float foam_fade, int resolution)
Definition ocean.cc:1641
void BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, Main *bmain, Object *ob, MultiresModifierData *mmd)
Definition paint.cc:2610
struct ModifierData * object_add_particle_system(struct Main *bmain, const struct Scene *scene, struct Object *ob, const char *name)
void object_remove_particle_system(struct Main *bmain, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys)
Definition particle.cc:3991
struct ParticleSystem * psys_eval_get(struct Depsgraph *depsgraph, struct Object *object, struct ParticleSystem *psys)
Definition particle.cc:664
void psys_apply_hair_lattice(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys)
Definition particle.cc:5253
struct ModifierData * object_copy_particle_system(struct Main *bmain, const struct Scene *scene, struct Object *ob, const struct ParticleSystem *psys_orig)
General operations for point clouds.
void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src, PointCloud *pointcloud_dst)
void BKE_pointcloud_data_update(Depsgraph *depsgraph, Scene *scene, Object *object)
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:125
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2647
struct SoftBody * sbNew(void)
Definition softbody.cc:3117
void sbFree(struct Object *ob)
Definition softbody.cc:3168
Volume data-block.
void BKE_volume_data_update(Depsgraph *depsgraph, Scene *scene, Object *object)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition BLI_bitmap.h:41
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition BLI_bitmap.h:65
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition BLI_bitmap.h:82
unsigned int BLI_bitmap
Definition BLI_bitmap.h:17
struct GSet GSet
Definition BLI_ghash.h:341
GSet * BLI_gset_ptr_new(const char *info)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.c:1034
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.c:966
void BLI_kdtree_nd_ free(KDTree *tree)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:331
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:370
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_listbase_swaplinks(struct ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
#define STRNCPY_UTF8(dst, src)
size_t void BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_maxncpy) ATTR_NONNULL(1
unsigned int uint
#define ELEM(...)
#define STREQ(a, b)
#define RPT_(msgid)
#define TIP_(msgid)
#define IFACE_(msgid)
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_disable_visibility_optimization(Depsgraph *depsgraph)
Definition depsgraph.cc:344
@ DAG_EVAL_VIEWPORT
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:273
void DEG_evaluate_on_refresh(Depsgraph *graph, DepsgraphEvaluateSyncWriteback sync_writeback=DEG_EVALUATE_SYNC_WRITEBACK_NO)
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:301
void DEG_relations_tag_update(Main *bmain)
void DEG_graph_build_from_ids(Depsgraph *graph, blender::Span< ID * > ids)
float DEG_get_ctime(const Depsgraph *graph)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
Main * DEG_get_bmain(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1044
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
@ ID_FLAG_FAKEUSER
Definition DNA_ID.h:720
#define ID_REAL_USERS(id)
Definition DNA_ID.h:637
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
@ IDP_BOOLEAN
@ IDP_INT
@ ARM_DEF_VGROUP
@ ARM_DEF_QUATERNION
@ BONE_CONNECTED
#define CD_MASK_COLOR_ALL
@ CD_MVERT_SKIN
@ CD_PROP_FLOAT3
@ CD_PROP_INT32_2D
@ CD_MDEFORMVERT
@ CD_PROP_STRING
#define DNA_struct_default_get(struct_name)
#define MAX_NAME
Definition DNA_defs.h:50
@ KEY_RELATIVE
@ BASE_ENABLED_VIEWPORT
@ MVERT_SKIN_LOOSE
@ MVERT_SKIN_ROOT
@ eModifierFlag_PinLast
@ eModifierFlag_OverrideLibrary_Local
@ eModifierMode_Realtime
@ eModifierType_ParticleSystem
@ eModifierType_MeshDeform
@ eModifierType_Explode
@ eModifierType_Subsurf
@ eModifierType_Surface
@ eModifierType_Skin
@ eModifierType_Cloth
@ eModifierType_Hook
@ eModifierType_GreasePencilTime
@ eModifierType_Ocean
@ eModifierType_LaplacianDeform
@ eModifierType_GreasePencilDash
@ eModifierType_Armature
@ eModifierType_SurfaceDeform
@ eModifierType_CorrectiveSmooth
@ eModifierType_Nodes
@ eModifierType_Collision
@ eModifierType_Softbody
@ eModifierType_Multires
@ MOD_SDEF_BIND
@ eExplodeFlag_CalcFaces
@ MOD_LAPLACIANDEFORM_BIND
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_SCULPT
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_DRAW_IN_FRONT
@ PART_DRAW_PATH
@ PART_HAIR
@ PART_DRAW_PARENT
@ OPERATOR_PASS_THROUGH
#define WEIGHT_REPLACE
bool ED_operator_object_active_local_editable(bContext *C)
bool ED_operator_object_active(bContext *C)
bool ED_operator_object_active_editable(bContext *C)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
PropertyFlag
Definition RNA_types.hh:201
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
PointerRNA * UI_region_panel_custom_data_under_cursor(const bContext *C, const wmEvent *event)
@ ALERT_ICON_WARNING
@ WM_JOB_TYPE_OBJECT_SIM_OCEAN
Definition WM_api.hh:1582
@ WM_JOB_PROGRESS
Definition WM_api.hh:1566
@ OPTYPE_INTERNAL
Definition WM_types.hh:182
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_WINDOW
Definition WM_types.hh:342
#define ND_MODE
Definition WM_types.hh:412
#define NC_SCENE
Definition WM_types.hh:345
#define NA_ADDED
Definition WM_types.hh:552
#define ND_MODIFIER
Definition WM_types.hh:429
#define NS_MODE_OBJECT
Definition WM_types.hh:526
#define NA_REMOVED
Definition WM_types.hh:553
@ KM_ALT
Definition WM_types.hh:257
#define NC_OBJECT
Definition WM_types.hh:346
EditBone * ED_armature_ebone_add(bArmature *arm, const char *name)
void ED_armature_edit_free(bArmature *arm)
void ED_armature_from_edit(Main *bmain, bArmature *arm)
@ BM_ELEM_SELECT
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_elem_flag_test(ele, hflag)
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
@ BM_EDGES_OF_VERT
ATTR_WARN_UNUSED_RESULT BMesh * bm
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int64_t size() const
Definition BLI_array.hh:245
const T * end() const
Definition BLI_array.hh:314
const T * begin() const
Definition BLI_array.hh:310
bool is_empty() const
Definition BLI_array.hh:253
const CPPType & type() const
KeyIterator keys() const
Definition BLI_map.hh:837
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
const Value & lookup(const Key &key) const
Definition BLI_map.hh:506
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:582
int64_t size() const
Definition BLI_map.hh:927
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition BLI_map.hh:457
Value & lookup_or_add(const Key &key, const Value &value)
Definition BLI_map.hh:551
bool contains(const Key &key) const
Definition BLI_set.hh:291
bool add(const Key &key)
Definition BLI_set.hh:248
bool remove(const Key &key)
Definition BLI_set.hh:366
constexpr const T * data() const
Definition BLI_span.hh:216
void add_new(const Key &key)
int64_t index_of_try(const Key &key) const
bool contains(const Key &key) const
void append(const T &value)
int64_t append_and_get_index_as(ForwardValue &&...value)
GAttributeReader get() const
MutableAttributeAccessor attributes_for_write()
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void set_local_transform(const float4x4 &transform)
void foreach_index(Fn &&fn) const
const Depsgraph * depsgraph
Lattice lattice
append
Set< ComponentNode * > visited
DEGForeachIDComponentCallback callback
int users
KDTree_3d * tree
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static const char * modifier_name[LS_MODIFIER_NUM]
Definition linestyle.cc:680
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:43
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
#define G(x, y, z)
void ED_mesh_deform_bind_callback(Object *object, MeshDeformModifierData *mmd, Mesh *cagemesh, float *vertexcos, int verts_num, float cagemat[4][4])
bool indices_are_range(Span< int > indices, IndexRange range)
Mesh * mesh_get_eval_deform(Depsgraph *depsgraph, const Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
Mesh * mesh_create_eval_final(Depsgraph *depsgraph, const Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
static int modifier_apply_exec(bContext *C, wmOperator *op)
void modifier_register_use_selected_objects_prop(wmOperatorType *ot)
static void skin_armature_bone_create(Object *skin_ob, const Span< float3 > positions, const int2 *edges, bArmature *arm, BLI_bitmap *edges_visited, const GroupedSpan< int > emap, EditBone *parent_bone, int parent_v)
ModifierData * modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
static int modifier_convert_exec(bContext *C, wmOperator *op)
void single_obdata_user_make(Main *bmain, Scene *scene, Object *ob)
static int modifier_copy_to_selected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int skin_radii_equalize_exec(bContext *C, wmOperator *)
bool modifier_apply(Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md, int mode, bool keep_modifier, bool do_all_keyframes)
static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void apply_eval_grease_pencil_data(const GreasePencil &src_grease_pencil, const int eval_frame, const IndexMask &orig_layers, GreasePencil &orig_grease_pencil)
static int modifier_move_up_exec(bContext *C, wmOperator *op)
static bool object_modifier_remove(Main *bmain, Scene *scene, Object *ob, ModifierData *md, bool *r_sort_depsgraph)
static int oceanbake_breakjob(void *)
static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
static int modifier_set_active_exec(bContext *C, wmOperator *op)
static int time_modifier_segment_remove_invoke(bContext *C, wmOperator *op, const wmEvent *)
static bool modifier_apply_shape(Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md_eval)
void OBJECT_OT_geometry_node_tree_copy_assign(wmOperatorType *ot)
bool modifier_copy_to_object(Main *bmain, const Scene *scene, const Object *ob_src, const ModifierData *md, Object *ob_dst, ReportList *reports)
static bool object_modifier_safe_to_delete(Main *bmain, Object *ob, ModifierData *exclude, ModifierType type)
static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *)
static std::string modifier_apply_as_shapekey_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
static bool correctivesmooth_poll(bContext *C)
static bool object_modifier_check_move_after(ReportList *reports, eReportType error_type, ModifierData *md, ModifierData *md_next)
static const EnumPropertyItem * modifier_add_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static bool edit_modifier_poll(bContext *C)
static void oceanbake_startjob(void *customdata, wmJobWorkerStatus *worker_status)
bool edit_modifier_invoke_properties(bContext *C, wmOperator *op)
static void edit_modifier_report_property(wmOperatorType *ot)
static int modifier_set_active_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_grease_pencil_dash_modifier_segment_add(wmOperatorType *ot)
static int time_modifier_segment_add_exec(bContext *C, wmOperator *op)
static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void oceanbake_endjob(void *customdata)
bool iter_other(Main *bmain, Object *orig_ob, bool include_orig, bool(*callback)(Object *ob, void *callback_data), void *callback_data)
static bool ocean_bake_poll(bContext *C)
static int modifier_copy_to_selected_exec(bContext *C, wmOperator *op)
bool modifier_move_up(ReportList *reports, eReportType error_type, Object *ob, ModifierData *md)
static int dash_modifier_segment_add_invoke(bContext *C, wmOperator *op, const wmEvent *)
void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
static int time_modifier_segment_add_invoke(bContext *C, wmOperator *op, const wmEvent *)
void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot)
static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph, Object *object, ModifierData *md)
bool multires_update_totlevels(Object *ob, void *totlevel_v)
static int modifier_add_exec(bContext *C, wmOperator *op)
void OBJECT_OT_explode_refresh(wmOperatorType *ot)
void OBJECT_OT_ocean_bake(wmOperatorType *ot)
void OBJECT_OT_skin_root_mark(wmOperatorType *ot)
static int meshdeform_bind_exec(bContext *C, wmOperator *op)
static bool apply_grease_pencil_for_modifier(Depsgraph *depsgraph, Object *ob, GreasePencil &grease_pencil_orig, ModifierData *md_eval)
static int geometry_nodes_input_attribute_toggle_exec(bContext *C, wmOperator *op)
static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int modifiers_clear_exec(bContext *C, wmOperator *)
static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *)
static bool edit_modifier_liboverride_allowed_poll(bContext *C)
static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset)
static int skin_armature_create_exec(bContext *C, wmOperator *op)
static bool modifier_apply_as_shapekey_poll(bContext *C)
void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
static bool surfacedeform_bind_poll(bContext *C)
static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_modifier_remove(wmOperatorType *ot)
void OBJECT_OT_grease_pencil_dash_modifier_segment_remove(wmOperatorType *ot)
static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
void OBJECT_OT_modifier_apply(wmOperatorType *ot)
static void oceanbake_update(void *customdata, float progress, int *cancel)
bool edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag, bool is_editmode_allowed, bool is_liboverride_allowed)
static int dash_modifier_segment_move_exec(bContext *C, wmOperator *op)
static void dash_modifier_segment_free(GreasePencilDashModifierSegment *)
static Mesh * create_applied_mesh_for_modifier(Depsgraph *depsgraph, Scene *scene, Object *ob_eval, ModifierData *md_eval, const bool use_virtual_modifiers, const bool build_shapekey_layers, ReportList *reports)
void OBJECT_OT_modifier_apply_as_shapekey(wmOperatorType *ot)
static bool modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md_eval, const bool do_all_keyframes)
static int modifier_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ModifierData * edit_modifier_property_get(wmOperator *op, Object *ob, int type)
static bool time_modifier_segment_poll(bContext *C)
static bool skin_edit_poll(bContext *C)
void OBJECT_OT_modifier_convert(wmOperatorType *ot)
void OBJECT_OT_grease_pencil_time_modifier_segment_move(wmOperatorType *ot)
bool modifier_copy(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
static bool meshdeform_poll(bContext *C)
static bool apply_grease_pencil_for_modifier_all_keyframes(Depsgraph *depsgraph, Scene *scene, Object *ob, GreasePencil &grease_pencil_orig, ModifierData *md)
static bool modifiers_copy_to_selected_poll(bContext *C)
Object * context_active_object(const bContext *C)
static bool modifiers_clear_poll(bContext *C)
static int explode_refresh_exec(bContext *C, wmOperator *op)
static int modifier_remove_exec(bContext *C, wmOperator *op)
bool modifier_move_down(ReportList *reports, eReportType error_type, Object *ob, ModifierData *md)
static int object_modifiers_copy_exec(bContext *C, wmOperator *op)
static void add_shapekey_layers(Mesh &mesh_dest, const Mesh &mesh_src)
static int dash_modifier_segment_move_invoke(bContext *C, wmOperator *op, const wmEvent *)
static Object * modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Object *skin_ob)
static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int dash_modifier_segment_remove_exec(bContext *C, wmOperator *op)
void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
void OBJECT_OT_geometry_nodes_input_attribute_toggle(wmOperatorType *ot)
static int skin_root_mark_exec(bContext *C, wmOperator *)
static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *)
void OBJECT_OT_modifiers_copy_to_selected(wmOperatorType *ot)
static bool laplaciandeform_poll(bContext *C)
static bool object_modifier_check_move_before(ReportList *reports, eReportType error_type, ModifierData *md, ModifierData *md_prev)
static bool skin_poll(bContext *C)
static void oceanbake_free(void *customdata)
static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
static int modifier_move_down_exec(bContext *C, wmOperator *op)
static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int time_modifier_segment_remove_exec(bContext *C, wmOperator *op)
static int ocean_bake_exec(bContext *C, wmOperator *op)
void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot)
static void remove_invalid_attribute_strings(Mesh &mesh)
static int dash_modifier_segment_add_exec(bContext *C, wmOperator *op)
void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot)
static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op)
void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot)
static int time_modifier_segment_move_invoke(bContext *C, wmOperator *op, const wmEvent *)
static bool modifier_apply_poll(bContext *C)
bool convert_psys_to_mesh(ReportList *reports, Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Object *ob, ModifierData *md)
bool modifier_move_to_index(ReportList *reports, eReportType error_type, Object *ob, ModifierData *md, int index, bool allow_partial)
void OBJECT_OT_modifier_add(wmOperatorType *ot)
void OBJECT_OT_modifier_copy(wmOperatorType *ot)
void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
static bool object_has_modifier(const Object *ob, const ModifierData *exclude, ModifierType type)
void vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
static int modifier_move_to_index_exec(bContext *C, wmOperator *op)
void OBJECT_OT_skin_loose_mark_clear(wmOperatorType *ot)
static bool meta_data_matches(const std::optional< bke::AttributeMetaData > meta_data, const AttrDomainMask domains, const eCustomDataMask types)
static bool object_has_modifier_cb(Object *ob, void *data)
static bool dash_modifier_segment_poll(bContext *C)
void OBJECT_OT_modifier_copy_to_selected(wmOperatorType *ot)
void OBJECT_OT_modifier_set_active(wmOperatorType *ot)
static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int dash_modifier_segment_remove_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void time_modifier_segment_free(GreasePencilTimeModifierSegment *)
static int geometry_node_tree_copy_assign_exec(bContext *C, wmOperator *)
void OBJECT_OT_modifiers_clear(wmOperatorType *ot)
static bool modifier_copy_to_selected_poll(bContext *C)
void OBJECT_OT_grease_pencil_time_modifier_segment_remove(wmOperatorType *ot)
static int modifier_copy_exec(bContext *C, wmOperator *op)
Vector< PointerRNA > modifier_get_edit_objects(const bContext &C, const wmOperator &op)
void modifier_link(bContext *C, Object *ob_dst, Object *ob_src)
static CLG_LogRef LOG
static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, bool keep_modifier)
static int modifier_apply_as_shapekey_exec(bContext *C, wmOperator *op)
static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *)
void modifiers_clear(Main *bmain, Scene *scene, Object *ob)
void OBJECT_OT_grease_pencil_time_modifier_segment_add(wmOperatorType *ot)
void OBJECT_OT_grease_pencil_dash_modifier_segment_move(wmOperatorType *ot)
static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *ob)
static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int time_modifier_segment_move_exec(bContext *C, wmOperator *op)
void edit_modifier_properties(wmOperatorType *ot)
static void modifier_skin_customdata_delete(Object *ob)
static bool edit_modifier_invoke_properties_with_hover(bContext *C, wmOperator *op, const wmEvent *event, int *r_retval)
void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
static bool explode_poll(bContext *C)
static int modifier_apply_as_shapekey_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
GreasePencil * merge_layers(const GreasePencil &src_grease_pencil, Span< Vector< int > > layers_to_merge, const bke::AttributeFilter &attribute_filter)
VecBase< int32_t, 2 > int2
float wrap(float value, float max, float min)
Definition node_math.h:71
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
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)
bool RNA_property_boolean_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)
bool RNA_pointer_is_null(const PointerRNA *ptr)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_id_pointer_create(ID *id)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_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_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)
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_modifier_type_items[]
void * data
BMHeader head
CustomData vdata
CorrectiveSmoothDeltaCache delta_cache
ListBase nurb
CurvesGeometry geometry
CustomDataLayer * layers
char name[64]
float tail[3]
EditBone * parent
float rad_tail
float rad_head
float head[3]
const char * identifier
Definition RNA_types.hh:506
struct Material ** material_array
GreasePencilRuntimeHandle * runtime
char type
Definition DNA_ID.h:154
Definition DNA_ID.h:413
int us
Definition DNA_ID.h:435
short flag
Definition DNA_ID.h:430
void * next
Definition DNA_ID.h:416
char name[66]
Definition DNA_ID.h:425
char type
ListBase block
void * first
ListBase objects
Definition BKE_main.hh:212
void(* bindfunc)(struct Object *object, struct MeshDeformModifierData *mmd, struct Mesh *cagemesh, float *vertexcos, int verts_num, float cagemat[4][4])
CustomData vert_data
struct Key * key
int verts_num
struct ModifierData * next
struct ModifierData * prev
void(* modify_geometry_set)(ModifierData *md, const ModifierEvalContext *ctx, blender::bke::GeometrySet *geometry_set)
void(* deform_verts)(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
bool(* is_disabled)(const Scene *scene, ModifierData *md, bool use_render_params)
ModifierTypeFlag flags
ModifierTypeType type
Mesh *(* modify_mesh)(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
struct bNodeTree * node_group
struct NodesModifierSettings settings
struct IDProperty * properties
ListBase particlesystem
short base_flag
ObjectRuntimeHandle * runtime
ListBase modifiers
struct PartDeflect * pd
struct SoftBody * soft
float * time
Definition BKE_ocean.h:44
int duration
Definition BKE_ocean.h:54
struct OceanCache * oceancache
ParticleSettings * part
struct ParticleCacheKey ** childcache
struct ParticleCacheKey ** pathcache
ID * owner_id
Definition RNA_types.hh:40
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
ListBase * edbo
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
uint8_t modifier
Definition WM_types.hh:739
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
std::string(* get_description)(bContext *C, wmOperatorType *ot, PointerRNA *ptr)
Definition WM_types.hh:1074
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct ReportList * reports
struct PointerRNA * ptr
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520
void WM_cursor_wait(bool val)
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:352
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:455
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:189
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:364
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:336
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
int WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)
uint8_t flag
Definition wm_window.cc:138