2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation, 2009
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/object/object_modifier.c
35 #include "MEM_guardedalloc.h"
37 #include "DNA_anim_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_key_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_object_force.h"
44 #include "DNA_scene_types.h"
46 #include "BLI_bitmap.h"
48 #include "BLI_listbase.h"
49 #include "BLI_string.h"
50 #include "BLI_string_utf8.h"
51 #include "BLI_path_util.h"
52 #include "BLI_utildefines.h"
54 #include "BKE_animsys.h"
55 #include "BKE_curve.h"
56 #include "BKE_context.h"
57 #include "BKE_displist.h"
58 #include "BKE_DerivedMesh.h"
59 #include "BKE_effect.h"
60 #include "BKE_global.h"
62 #include "BKE_lattice.h"
65 #include "BKE_mesh_mapping.h"
66 #include "BKE_modifier.h"
67 #include "BKE_multires.h"
68 #include "BKE_report.h"
69 #include "BKE_object.h"
70 #include "BKE_object_deform.h"
71 #include "BKE_ocean.h"
72 #include "BKE_paint.h"
73 #include "BKE_particle.h"
74 #include "BKE_softbody.h"
75 #include "BKE_editmesh.h"
77 #include "DEG_depsgraph.h"
78 #include "DEG_depsgraph_build.h"
80 #include "RNA_access.h"
81 #include "RNA_define.h"
82 #include "RNA_enum_types.h"
84 #include "ED_armature.h"
85 #include "ED_object.h"
86 #include "ED_screen.h"
92 #include "object_intern.h"
94 static void modifier_skin_customdata_delete(struct Object *ob);
96 /******************************** API ****************************/
98 ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
100 ModifierData *md = NULL, *new_md = NULL;
101 const ModifierTypeInfo *mti = modifierType_getInfo(type);
103 /* Check compatibility of modifier [T25291, T50373]. */
104 if (!BKE_object_support_modifier_type_check(ob, type)) {
105 BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
109 if (mti->flags & eModifierTypeFlag_Single) {
110 if (modifiers_findByType(ob, type)) {
111 BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
116 if (type == eModifierType_ParticleSystem) {
117 /* don't need to worry about the new modifier's name, since that is set to the number
118 * of particle systems which shouldn't have too many duplicates
120 new_md = object_add_particle_system(scene, ob, name);
123 /* get new modifier data to add */
124 new_md = modifier_new(type);
126 if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
127 md = ob->modifiers.first;
129 while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
132 BLI_insertlinkbefore(&ob->modifiers, md, new_md);
135 BLI_addtail(&ob->modifiers, new_md);
138 BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
141 /* make sure modifier data has unique name */
143 modifier_unique_name(&ob->modifiers, new_md);
146 if (type == eModifierType_Softbody) {
148 ob->soft = sbNew(scene);
149 ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
152 else if (type == eModifierType_Collision) {
154 ob->pd = object_add_collision_fields(0);
158 else if (type == eModifierType_Surface) {
161 else if (type == eModifierType_Multires) {
162 /* set totlvl from existing MDISPS layer if object already had it */
163 multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
165 if (ob->mode & OB_MODE_SCULPT) {
166 /* ensure that grid paint mask layer is created */
167 BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md);
170 else if (type == eModifierType_Skin) {
171 /* ensure skin-node customdata exists */
172 BKE_mesh_ensure_skin_customdata(ob->data);
176 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
177 DEG_relations_tag_update(bmain);
182 /* Return true if the object has a modifier of type 'type' other than
183 * the modifier pointed to be 'exclude', otherwise returns false. */
184 static bool object_has_modifier(const Object *ob, const ModifierData *exclude,
189 for (md = ob->modifiers.first; md; md = md->next) {
190 if ((md != exclude) && (md->type == type))
197 /* If the object data of 'orig_ob' has other users, run 'callback' on
200 * If include_orig is true, the callback will run on 'orig_ob' too.
202 * If the callback ever returns true, iteration will stop and the
203 * function value will be true. Otherwise the function returns false.
205 bool ED_object_iter_other(Main *bmain, Object *orig_ob, const bool include_orig,
206 bool (*callback)(Object *ob, void *callback_data),
209 ID *ob_data_id = orig_ob->data;
210 int users = ob_data_id->us;
212 if (ob_data_id->flag & LIB_FAKEUSER)
215 /* First check that the object's data has multiple users */
218 int totfound = include_orig ? 0 : 1;
220 for (ob = bmain->object.first; ob && totfound < users;
223 if (((ob != orig_ob) || include_orig) &&
224 (ob->data == orig_ob->data))
226 if (callback(ob, callback_data))
233 else if (include_orig) {
234 return callback(orig_ob, callback_data);
240 static bool object_has_modifier_cb(Object *ob, void *data)
242 ModifierType type = *((ModifierType *)data);
244 return object_has_modifier(ob, NULL, type);
247 /* Use with ED_object_iter_other(). Sets the total number of levels
248 * for any multires modifiers on the object to the int pointed to by
250 bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
253 int totlevel = *((char *)totlevel_v);
255 for (md = ob->modifiers.first; md; md = md->next) {
256 if (md->type == eModifierType_Multires) {
257 multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
258 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
264 /* Return true if no modifier of type 'type' other than 'exclude' */
265 static bool object_modifier_safe_to_delete(Main *bmain, Object *ob,
266 ModifierData *exclude,
269 return (!object_has_modifier(ob, exclude, type) &&
270 !ED_object_iter_other(bmain, ob, false,
271 object_has_modifier_cb, &type));
274 static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
275 bool *r_sort_depsgraph)
277 /* It seems on rapid delete it is possible to
278 * get called twice on same modifier, so make
279 * sure it is in list. */
280 if (BLI_findindex(&ob->modifiers, md) == -1) {
285 if (md->type == eModifierType_ParticleSystem) {
286 ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
288 BLI_remlink(&ob->particlesystem, psmd->psys);
289 psys_free(ob, psmd->psys);
292 else if (md->type == eModifierType_Softbody) {
299 else if (md->type == eModifierType_Collision) {
303 *r_sort_depsgraph = true;
305 else if (md->type == eModifierType_Surface) {
306 *r_sort_depsgraph = true;
308 else if (md->type == eModifierType_Multires) {
309 /* Delete MDisps layer if not used by another multires modifier */
310 if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Multires))
311 multires_customdata_delete(ob->data);
313 else if (md->type == eModifierType_Skin) {
314 /* Delete MVertSkin layer if not used by another skin modifier */
315 if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin))
316 modifier_skin_customdata_delete(ob);
319 if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
320 BLI_listbase_is_empty(&ob->particlesystem))
322 ob->mode &= ~OB_MODE_PARTICLE_EDIT;
325 DEG_relations_tag_update(bmain);
327 BLI_remlink(&ob->modifiers, md);
329 BKE_object_free_derived_caches(ob);
334 bool ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, ModifierData *md)
336 bool sort_depsgraph = false;
339 ok = object_modifier_remove(bmain, ob, md, &sort_depsgraph);
342 BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
346 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
347 DEG_relations_tag_update(bmain);
352 void ED_object_modifier_clear(Main *bmain, Object *ob)
354 ModifierData *md = ob->modifiers.first;
355 bool sort_depsgraph = false;
361 ModifierData *next_md;
365 object_modifier_remove(bmain, ob, md, &sort_depsgraph);
370 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
371 DEG_relations_tag_update(bmain);
374 int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
377 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
379 if (mti->type != eModifierTypeType_OnlyDeform) {
380 const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
382 if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) {
383 BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
388 BLI_remlink(&ob->modifiers, md);
389 BLI_insertlinkbefore(&ob->modifiers, md->prev, md);
395 int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
398 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
400 if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
401 const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
403 if (nmti->type != eModifierTypeType_OnlyDeform) {
404 BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
409 BLI_remlink(&ob->modifiers, md);
410 BLI_insertlinkafter(&ob->modifiers, md->next, md);
416 int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, ModifierData *md)
419 ParticleSystem *psys;
420 ParticleCacheKey *key, **cache;
421 ParticleSettings *part;
426 int totvert = 0, totedge = 0, cvert = 0;
427 int totpart = 0, totchild = 0;
429 if (md->type != eModifierType_ParticleSystem) return 0;
430 if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
432 psys = ((ParticleSystemModifierData *)md)->psys;
435 if (part->ren_as != PART_DRAW_PATH || psys->pathcache == NULL)
438 totpart = psys->totcached;
439 totchild = psys->totchildcache;
441 if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
445 cache = psys->pathcache;
446 for (a = 0; a < totpart; a++) {
449 if (key->segments > 0) {
450 totvert += key->segments + 1;
451 totedge += key->segments;
455 cache = psys->childcache;
456 for (a = 0; a < totchild; a++) {
459 if (key->segments > 0) {
460 totvert += key->segments + 1;
461 totedge += key->segments;
465 if (totvert == 0) return 0;
468 obn = BKE_object_add(bmain, scene, sl, OB_MESH, NULL);
471 me->totvert = totvert;
472 me->totedge = totedge;
474 me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
475 me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
476 me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
481 /* copy coordinates */
482 cache = psys->pathcache;
483 for (a = 0; a < totpart; a++) {
485 kmax = key->segments;
486 for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
487 copy_v3_v3(mvert->co, key->co);
489 medge->v1 = cvert - 1;
491 medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
495 /* cheap trick to select the roots */
496 mvert->flag |= SELECT;
501 cache = psys->childcache;
502 for (a = 0; a < totchild; a++) {
504 kmax = key->segments;
505 for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
506 copy_v3_v3(mvert->co, key->co);
508 medge->v1 = cvert - 1;
510 medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
514 /* cheap trick to select the roots */
515 mvert->flag |= SELECT;
520 DEG_relations_tag_update(bmain);
525 static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
527 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
531 if (mti->isDisabled && mti->isDisabled(md, 0)) {
532 BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
537 * It should be ridiculously easy to extract the original verts that we want
538 * and form the shape data. We can probably use the CD KEYINDEX layer (or
539 * whatever I ended up calling it, too tired to check now), though this would
540 * by necessity have to make some potentially ugly assumptions about the order
541 * of the mesh data :-/ you can probably assume in 99% of cases that the first
542 * element of a given index is the original, and any subsequent duplicates are
543 * copies/interpolates, but that's an assumption that would need to be tested
544 * and then predominantly stated in comments in a half dozen headers.
547 if (ob->type == OB_MESH) {
553 if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) {
554 BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
558 dm = mesh_create_derived_for_modifier(scene, ob, md, 0);
560 BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
565 key = me->key = BKE_key_add((ID *)me);
566 key->type = KEY_RELATIVE;
567 /* if that was the first key block added, then it was the basis.
568 * Initialize it with the mesh, and add another for the modifier */
569 kb = BKE_keyblock_add(key, NULL);
570 BKE_keyblock_convert_from_mesh(me, kb);
573 kb = BKE_keyblock_add(key, md->name);
574 DM_to_meshkey(dm, me, kb);
579 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
585 static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
587 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
591 if (mti->isDisabled && mti->isDisabled(md, 0)) {
592 BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
596 if (ob->type == OB_MESH) {
599 MultiresModifierData *mmd = find_multires_modifier_before(scene, md);
601 if (me->key && mti->type != eModifierTypeType_NonGeometrical) {
602 BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys");
606 /* Multires: ensure that recent sculpting is applied */
607 if (md->type == eModifierType_Multires)
608 multires_force_update(ob);
610 if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
611 if (!multiresModifier_reshapeFromDeformMod(scene, mmd, ob, md)) {
612 BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
617 dm = mesh_create_derived_for_modifier(scene, ob, md, 1);
619 BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
623 DM_to_mesh(dm, me, ob, CD_MASK_MESH, true);
625 if (md->type == eModifierType_Multires)
626 multires_customdata_delete(me);
629 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
632 float (*vertexCos)[3];
634 if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
635 BKE_report(reports, RPT_ERROR, "Cannot apply constructive modifiers on curve");
640 BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
642 vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
643 mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
644 BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
646 MEM_freeN(vertexCos);
648 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
651 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
655 /* lattice modifier can be applied to particle system too */
656 if (ob->particlesystem.first) {
658 ParticleSystem *psys = ob->particlesystem.first;
660 for (; psys; psys = psys->next) {
662 if (psys->part->type != PART_HAIR)
665 psys_apply_hair_lattice(scene, ob, psys);
672 int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
677 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
680 else if (((ID *) ob->data)->us > 1) {
681 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
684 else if ((ob->mode & OB_MODE_SCULPT) &&
685 (find_multires_modifier_before(scene, md)) &&
686 (modifier_isSameTopology(md) == false))
688 BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode");
692 if (md != ob->modifiers.first)
693 BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
695 /* allow apply of a not-realtime modifier, by first re-enabling realtime. */
696 prev_mode = md->mode;
697 md->mode |= eModifierMode_Realtime;
699 if (mode == MODIFIER_APPLY_SHAPE) {
700 if (!modifier_apply_shape(reports, scene, ob, md)) {
701 md->mode = prev_mode;
706 if (!modifier_apply_obdata(reports, scene, ob, md)) {
707 md->mode = prev_mode;
712 BLI_remlink(&ob->modifiers, md);
715 BKE_object_free_derived_caches(ob);
720 int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
724 nmd = modifier_new(md->type);
725 modifier_copyData(md, nmd);
726 BLI_insertlinkafter(&ob->modifiers, md, nmd);
727 modifier_unique_name(&ob->modifiers, nmd);
732 /************************ add modifier operator *********************/
734 static int modifier_add_exec(bContext *C, wmOperator *op)
736 Main *bmain = CTX_data_main(C);
737 Scene *scene = CTX_data_scene(C);
738 Object *ob = ED_object_active_context(C);
739 int type = RNA_enum_get(op->ptr, "type");
741 if (!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
742 return OPERATOR_CANCELLED;
744 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
746 return OPERATOR_FINISHED;
749 static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
751 Object *ob = ED_object_active_context(C);
752 EnumPropertyItem *item = NULL, *md_item, *group_item = NULL;
753 const ModifierTypeInfo *mti;
757 return rna_enum_object_modifier_type_items;
759 for (a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) {
760 md_item = &rna_enum_object_modifier_type_items[a];
762 if (md_item->identifier[0]) {
763 mti = modifierType_getInfo(md_item->value);
765 if (mti->flags & eModifierTypeFlag_NoUserAdd)
768 if (!BKE_object_support_modifier_type_check(ob, md_item->value))
772 group_item = md_item;
779 RNA_enum_item_add(&item, &totitem, group_item);
783 RNA_enum_item_add(&item, &totitem, md_item);
786 RNA_enum_item_end(&item, &totitem);
792 void OBJECT_OT_modifier_add(wmOperatorType *ot)
797 ot->name = "Add Modifier";
798 ot->description = "Add a procedural operation/effect to the active object";
799 ot->idname = "OBJECT_OT_modifier_add";
802 ot->invoke = WM_menu_invoke;
803 ot->exec = modifier_add_exec;
804 ot->poll = ED_operator_object_active_editable;
807 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
810 prop = RNA_def_enum(ot->srna, "type", rna_enum_object_modifier_type_items, eModifierType_Subsurf, "Type", "");
811 RNA_def_enum_funcs(prop, modifier_add_itemf);
815 /************************ generic functions for operators using mod names and data context *********************/
817 int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
819 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
820 Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
822 if (!ob || ID_IS_LINKED_DATABLOCK(ob)) return 0;
823 if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
824 if (ptr.id.data && ID_IS_LINKED_DATABLOCK(ptr.id.data)) return 0;
829 int edit_modifier_poll(bContext *C)
831 return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
834 void edit_modifier_properties(wmOperatorType *ot)
836 RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
839 int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
843 if (RNA_struct_property_is_set(op->ptr, "modifier")) {
847 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
850 RNA_string_set(op->ptr, "modifier", md->name);
858 ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
860 char modifier_name[MAX_NAME];
862 RNA_string_get(op->ptr, "modifier", modifier_name);
864 md = modifiers_findByName(ob, modifier_name);
866 if (md && type != 0 && md->type != type)
872 /************************ remove modifier operator *********************/
874 static int modifier_remove_exec(bContext *C, wmOperator *op)
876 Main *bmain = CTX_data_main(C);
877 SceneLayer *sl = CTX_data_scene_layer(C);
878 Object *ob = ED_object_active_context(C);
879 ModifierData *md = edit_modifier_property_get(op, ob, 0);
880 int mode_orig = ob->mode;
882 if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md))
883 return OPERATOR_CANCELLED;
885 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
887 /* if cloth/softbody was removed, particle mode could be cleared */
888 if (mode_orig & OB_MODE_PARTICLE_EDIT)
889 if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0)
890 if (sl->basact && sl->basact->object == ob)
891 WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
893 return OPERATOR_FINISHED;
896 static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
898 if (edit_modifier_invoke_properties(C, op))
899 return modifier_remove_exec(C, op);
901 return OPERATOR_CANCELLED;
904 void OBJECT_OT_modifier_remove(wmOperatorType *ot)
906 ot->name = "Remove Modifier";
907 ot->description = "Remove a modifier from the active object";
908 ot->idname = "OBJECT_OT_modifier_remove";
910 ot->invoke = modifier_remove_invoke;
911 ot->exec = modifier_remove_exec;
912 ot->poll = edit_modifier_poll;
915 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
916 edit_modifier_properties(ot);
919 /************************ move up modifier operator *********************/
921 static int modifier_move_up_exec(bContext *C, wmOperator *op)
923 Object *ob = ED_object_active_context(C);
924 ModifierData *md = edit_modifier_property_get(op, ob, 0);
926 if (!md || !ED_object_modifier_move_up(op->reports, ob, md))
927 return OPERATOR_CANCELLED;
929 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
930 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
932 return OPERATOR_FINISHED;
935 static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
937 if (edit_modifier_invoke_properties(C, op))
938 return modifier_move_up_exec(C, op);
940 return OPERATOR_CANCELLED;
943 void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
945 ot->name = "Move Up Modifier";
946 ot->description = "Move modifier up in the stack";
947 ot->idname = "OBJECT_OT_modifier_move_up";
949 ot->invoke = modifier_move_up_invoke;
950 ot->exec = modifier_move_up_exec;
951 ot->poll = edit_modifier_poll;
954 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
955 edit_modifier_properties(ot);
958 /************************ move down modifier operator *********************/
960 static int modifier_move_down_exec(bContext *C, wmOperator *op)
962 Object *ob = ED_object_active_context(C);
963 ModifierData *md = edit_modifier_property_get(op, ob, 0);
965 if (!md || !ED_object_modifier_move_down(op->reports, ob, md))
966 return OPERATOR_CANCELLED;
968 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
969 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
971 return OPERATOR_FINISHED;
974 static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
976 if (edit_modifier_invoke_properties(C, op))
977 return modifier_move_down_exec(C, op);
979 return OPERATOR_CANCELLED;
982 void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
984 ot->name = "Move Down Modifier";
985 ot->description = "Move modifier down in the stack";
986 ot->idname = "OBJECT_OT_modifier_move_down";
988 ot->invoke = modifier_move_down_invoke;
989 ot->exec = modifier_move_down_exec;
990 ot->poll = edit_modifier_poll;
993 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
994 edit_modifier_properties(ot);
997 /************************ apply modifier operator *********************/
999 static int modifier_apply_exec(bContext *C, wmOperator *op)
1001 Scene *scene = CTX_data_scene(C);
1002 Object *ob = ED_object_active_context(C);
1003 ModifierData *md = edit_modifier_property_get(op, ob, 0);
1004 int apply_as = RNA_enum_get(op->ptr, "apply_as");
1006 if (!md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
1007 return OPERATOR_CANCELLED;
1010 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1011 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1013 return OPERATOR_FINISHED;
1016 static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1018 if (edit_modifier_invoke_properties(C, op))
1019 return modifier_apply_exec(C, op);
1021 return OPERATOR_CANCELLED;
1024 static EnumPropertyItem modifier_apply_as_items[] = {
1025 {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
1026 {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
1027 {0, NULL, 0, NULL, NULL}
1030 void OBJECT_OT_modifier_apply(wmOperatorType *ot)
1032 ot->name = "Apply Modifier";
1033 ot->description = "Apply modifier and remove from the stack";
1034 ot->idname = "OBJECT_OT_modifier_apply";
1036 ot->invoke = modifier_apply_invoke;
1037 ot->exec = modifier_apply_exec;
1038 ot->poll = edit_modifier_poll;
1041 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1043 RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
1044 edit_modifier_properties(ot);
1047 /************************ convert modifier operator *********************/
1049 static int modifier_convert_exec(bContext *C, wmOperator *op)
1051 Main *bmain = CTX_data_main(C);
1052 Scene *scene = CTX_data_scene(C);
1053 SceneLayer *sl = CTX_data_scene_layer(C);
1054 Object *ob = ED_object_active_context(C);
1055 ModifierData *md = edit_modifier_property_get(op, ob, 0);
1057 if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, sl, ob, md))
1058 return OPERATOR_CANCELLED;
1060 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1061 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1063 return OPERATOR_FINISHED;
1066 static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1068 if (edit_modifier_invoke_properties(C, op))
1069 return modifier_convert_exec(C, op);
1071 return OPERATOR_CANCELLED;
1074 void OBJECT_OT_modifier_convert(wmOperatorType *ot)
1076 ot->name = "Convert Modifier";
1077 ot->description = "Convert particles to a mesh object";
1078 ot->idname = "OBJECT_OT_modifier_convert";
1080 ot->invoke = modifier_convert_invoke;
1081 ot->exec = modifier_convert_exec;
1082 ot->poll = edit_modifier_poll;
1085 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1086 edit_modifier_properties(ot);
1089 /************************ copy modifier operator *********************/
1091 static int modifier_copy_exec(bContext *C, wmOperator *op)
1093 Object *ob = ED_object_active_context(C);
1094 ModifierData *md = edit_modifier_property_get(op, ob, 0);
1096 if (!md || !ED_object_modifier_copy(op->reports, ob, md))
1097 return OPERATOR_CANCELLED;
1099 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1100 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1102 return OPERATOR_FINISHED;
1105 static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1107 if (edit_modifier_invoke_properties(C, op))
1108 return modifier_copy_exec(C, op);
1110 return OPERATOR_CANCELLED;
1113 void OBJECT_OT_modifier_copy(wmOperatorType *ot)
1115 ot->name = "Copy Modifier";
1116 ot->description = "Duplicate modifier at the same position in the stack";
1117 ot->idname = "OBJECT_OT_modifier_copy";
1119 ot->invoke = modifier_copy_invoke;
1120 ot->exec = modifier_copy_exec;
1121 ot->poll = edit_modifier_poll;
1124 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1125 edit_modifier_properties(ot);
1128 /************* multires delete higher levels operator ****************/
1130 static int multires_poll(bContext *C)
1132 return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH));
1135 static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
1137 Object *ob = ED_object_active_context(C);
1138 MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1141 return OPERATOR_CANCELLED;
1143 multiresModifier_del_levels(mmd, ob, 1);
1145 ED_object_iter_other(CTX_data_main(C), ob, true,
1146 ED_object_multires_update_totlevels_cb,
1149 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1151 return OPERATOR_FINISHED;
1154 static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1156 if (edit_modifier_invoke_properties(C, op))
1157 return multires_higher_levels_delete_exec(C, op);
1159 return OPERATOR_CANCELLED;
1162 void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
1164 ot->name = "Delete Higher Levels";
1165 ot->description = "Deletes the higher resolution mesh, potential loss of detail";
1166 ot->idname = "OBJECT_OT_multires_higher_levels_delete";
1168 ot->poll = multires_poll;
1169 ot->invoke = multires_higher_levels_delete_invoke;
1170 ot->exec = multires_higher_levels_delete_exec;
1173 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1174 edit_modifier_properties(ot);
1177 /****************** multires subdivide operator *********************/
1179 static int multires_subdivide_exec(bContext *C, wmOperator *op)
1181 Object *ob = ED_object_active_context(C);
1182 MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1185 return OPERATOR_CANCELLED;
1187 multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
1189 ED_object_iter_other(CTX_data_main(C), ob, true,
1190 ED_object_multires_update_totlevels_cb,
1193 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1194 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1196 if (ob->mode & OB_MODE_SCULPT) {
1197 /* ensure that grid paint mask layer is created */
1198 BKE_sculpt_mask_layers_ensure(ob, mmd);
1201 return OPERATOR_FINISHED;
1204 static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1206 if (edit_modifier_invoke_properties(C, op))
1207 return multires_subdivide_exec(C, op);
1209 return OPERATOR_CANCELLED;
1212 void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
1214 ot->name = "Multires Subdivide";
1215 ot->description = "Add a new level of subdivision";
1216 ot->idname = "OBJECT_OT_multires_subdivide";
1218 ot->poll = multires_poll;
1219 ot->invoke = multires_subdivide_invoke;
1220 ot->exec = multires_subdivide_exec;
1223 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1224 edit_modifier_properties(ot);
1227 /****************** multires reshape operator *********************/
1229 static int multires_reshape_exec(bContext *C, wmOperator *op)
1231 Object *ob = ED_object_active_context(C), *secondob = NULL;
1232 Scene *scene = CTX_data_scene(C);
1233 MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1236 return OPERATOR_CANCELLED;
1238 if (mmd->lvl == 0) {
1239 BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
1240 return OPERATOR_CANCELLED;
1243 CTX_DATA_BEGIN(C, Object *, selob, selected_editable_objects)
1245 if (selob->type == OB_MESH && selob != ob) {
1253 BKE_report(op->reports, RPT_ERROR, "Second selected mesh object required to copy shape from");
1254 return OPERATOR_CANCELLED;
1257 if (!multiresModifier_reshape(scene, mmd, ob, secondob)) {
1258 BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
1259 return OPERATOR_CANCELLED;
1262 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1263 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1265 return OPERATOR_FINISHED;
1268 static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1270 if (edit_modifier_invoke_properties(C, op))
1271 return multires_reshape_exec(C, op);
1273 return OPERATOR_CANCELLED;
1276 void OBJECT_OT_multires_reshape(wmOperatorType *ot)
1278 ot->name = "Multires Reshape";
1279 ot->description = "Copy vertex coordinates from other object";
1280 ot->idname = "OBJECT_OT_multires_reshape";
1282 ot->poll = multires_poll;
1283 ot->invoke = multires_reshape_invoke;
1284 ot->exec = multires_reshape_exec;
1287 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1288 edit_modifier_properties(ot);
1293 /****************** multires save external operator *********************/
1295 static int multires_external_save_exec(bContext *C, wmOperator *op)
1297 Object *ob = ED_object_active_context(C);
1298 Mesh *me = (ob) ? ob->data : op->customdata;
1299 char path[FILE_MAX];
1300 const bool relative = RNA_boolean_get(op->ptr, "relative_path");
1303 return OPERATOR_CANCELLED;
1305 if (CustomData_external_test(&me->ldata, CD_MDISPS))
1306 return OPERATOR_CANCELLED;
1308 RNA_string_get(op->ptr, "filepath", path);
1311 BLI_path_rel(path, G.main->name);
1313 CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
1314 CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH, me->totloop, 0);
1316 return OPERATOR_FINISHED;
1319 static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1321 Object *ob = ED_object_active_context(C);
1322 MultiresModifierData *mmd;
1323 Mesh *me = ob->data;
1324 char path[FILE_MAX];
1326 if (!edit_modifier_invoke_properties(C, op))
1327 return OPERATOR_CANCELLED;
1329 mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1332 return OPERATOR_CANCELLED;
1334 if (CustomData_external_test(&me->ldata, CD_MDISPS))
1335 return OPERATOR_CANCELLED;
1337 if (RNA_struct_property_is_set(op->ptr, "filepath"))
1338 return multires_external_save_exec(C, op);
1340 op->customdata = me;
1342 BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name + 2);
1343 RNA_string_set(op->ptr, "filepath", path);
1345 WM_event_add_fileselect(C, op);
1347 return OPERATOR_RUNNING_MODAL;
1350 void OBJECT_OT_multires_external_save(wmOperatorType *ot)
1352 ot->name = "Multires Save External";
1353 ot->description = "Save displacements to an external file";
1354 ot->idname = "OBJECT_OT_multires_external_save";
1356 /* XXX modifier no longer in context after file browser .. ot->poll = multires_poll; */
1357 ot->exec = multires_external_save_exec;
1358 ot->invoke = multires_external_save_invoke;
1359 ot->poll = multires_poll;
1362 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1364 WM_operator_properties_filesel(
1365 ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE,
1366 WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
1367 edit_modifier_properties(ot);
1370 /****************** multires pack operator *********************/
1372 static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
1374 Object *ob = ED_object_active_context(C);
1375 Mesh *me = ob->data;
1377 if (!CustomData_external_test(&me->ldata, CD_MDISPS))
1378 return OPERATOR_CANCELLED;
1380 /* XXX don't remove.. */
1381 CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
1383 return OPERATOR_FINISHED;
1386 void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
1388 ot->name = "Multires Pack External";
1389 ot->description = "Pack displacements from an external file";
1390 ot->idname = "OBJECT_OT_multires_external_pack";
1392 ot->poll = multires_poll;
1393 ot->exec = multires_external_pack_exec;
1396 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1399 /********************* multires apply base ***********************/
1400 static int multires_base_apply_exec(bContext *C, wmOperator *op)
1402 Object *ob = ED_object_active_context(C);
1403 MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1406 return OPERATOR_CANCELLED;
1408 multiresModifier_base_apply(mmd, ob);
1410 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1411 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1413 return OPERATOR_FINISHED;
1416 static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1418 if (edit_modifier_invoke_properties(C, op))
1419 return multires_base_apply_exec(C, op);
1421 return OPERATOR_CANCELLED;
1425 void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
1427 ot->name = "Multires Apply Base";
1428 ot->description = "Modify the base mesh to conform to the displaced mesh";
1429 ot->idname = "OBJECT_OT_multires_base_apply";
1431 ot->poll = multires_poll;
1432 ot->invoke = multires_base_apply_invoke;
1433 ot->exec = multires_base_apply_exec;
1436 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1437 edit_modifier_properties(ot);
1441 /************************** skin modifier ***********************/
1443 static void modifier_skin_customdata_delete(Object *ob)
1445 Mesh *me = ob->data;
1446 BMEditMesh *em = me->edit_btmesh;
1449 BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
1451 CustomData_free_layer_active(&me->vdata, CD_MVERT_SKIN, me->totvert);
1454 static int skin_poll(bContext *C)
1456 return (!CTX_data_edit_object(C) &&
1457 edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
1460 static int skin_edit_poll(bContext *C)
1462 return (CTX_data_edit_object(C) &&
1463 edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
1466 static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset)
1471 BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) {
1472 BMVert *v2 = BM_edge_other_vert(bm_edge, bm_vert);
1474 if (BLI_gset_add(visited, v2)) {
1475 MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(v2, cd_vert_skin_offset);
1477 /* clear vertex root flag and add to visited set */
1478 vs->flag &= ~MVERT_SKIN_ROOT;
1480 skin_root_clear(v2, visited, cd_vert_skin_offset);
1485 static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
1487 Object *ob = CTX_data_edit_object(C);
1488 BMEditMesh *em = BKE_editmesh_from_object(ob);
1494 visited = BLI_gset_ptr_new(__func__);
1496 BKE_mesh_ensure_skin_customdata(ob->data);
1498 const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
1500 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
1501 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) &&
1502 BLI_gset_add(visited, bm_vert))
1504 MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset);
1506 /* mark vertex as root and add to visited set */
1507 vs->flag |= MVERT_SKIN_ROOT;
1509 /* clear root flag from all connected vertices (recursively) */
1510 skin_root_clear(bm_vert, visited, cd_vert_skin_offset);
1514 BLI_gset_free(visited, NULL);
1516 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1517 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1519 return OPERATOR_FINISHED;
1522 void OBJECT_OT_skin_root_mark(wmOperatorType *ot)
1524 ot->name = "Skin Root Mark";
1525 ot->description = "Mark selected vertices as roots";
1526 ot->idname = "OBJECT_OT_skin_root_mark";
1528 ot->poll = skin_edit_poll;
1529 ot->exec = skin_root_mark_exec;
1532 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1540 static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op)
1542 Object *ob = CTX_data_edit_object(C);
1543 BMEditMesh *em = BKE_editmesh_from_object(ob);
1547 SkinLooseAction action = RNA_enum_get(op->ptr, "action");
1549 if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
1550 return OPERATOR_CANCELLED;
1553 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
1554 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
1555 MVertSkin *vs = CustomData_bmesh_get(&bm->vdata,
1561 case SKIN_LOOSE_MARK:
1562 vs->flag |= MVERT_SKIN_LOOSE;
1564 case SKIN_LOOSE_CLEAR:
1565 vs->flag &= ~MVERT_SKIN_LOOSE;
1571 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1572 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1574 return OPERATOR_FINISHED;
1577 void OBJECT_OT_skin_loose_mark_clear(wmOperatorType *ot)
1579 static EnumPropertyItem action_items[] = {
1580 {SKIN_LOOSE_MARK, "MARK", 0, "Mark", "Mark selected vertices as loose"},
1581 {SKIN_LOOSE_CLEAR, "CLEAR", 0, "Clear", "Set selected vertices as not loose"},
1582 {0, NULL, 0, NULL, NULL}
1585 ot->name = "Skin Mark/Clear Loose";
1586 ot->description = "Mark/clear selected vertices as loose";
1587 ot->idname = "OBJECT_OT_skin_loose_mark_clear";
1589 ot->poll = skin_edit_poll;
1590 ot->exec = skin_loose_mark_clear_exec;
1593 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1595 RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", NULL);
1598 static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op))
1600 Object *ob = CTX_data_edit_object(C);
1601 BMEditMesh *em = BKE_editmesh_from_object(ob);
1606 if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
1607 return OPERATOR_CANCELLED;
1610 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
1611 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
1612 MVertSkin *vs = CustomData_bmesh_get(&bm->vdata,
1615 float avg = (vs->radius[0] + vs->radius[1]) * 0.5f;
1617 vs->radius[0] = vs->radius[1] = avg;
1621 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1622 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1624 return OPERATOR_FINISHED;
1627 void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot)
1629 ot->name = "Skin Radii Equalize";
1630 ot->description = "Make skin radii of selected vertices equal on each axis";
1631 ot->idname = "OBJECT_OT_skin_radii_equalize";
1633 ot->poll = skin_edit_poll;
1634 ot->exec = skin_radii_equalize_exec;
1637 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1640 static void skin_armature_bone_create(Object *skin_ob,
1641 MVert *mvert, MEdge *medge,
1643 BLI_bitmap *edges_visited,
1644 const MeshElemMap *emap,
1645 EditBone *parent_bone,
1650 for (i = 0; i < emap[parent_v].count; i++) {
1651 int endx = emap[parent_v].indices[i];
1652 const MEdge *e = &medge[endx];
1657 /* ignore edge if already visited */
1658 if (BLI_BITMAP_TEST(edges_visited, endx))
1660 BLI_BITMAP_ENABLE(edges_visited, endx);
1662 v = (e->v1 == parent_v ? e->v2 : e->v1);
1664 bone = ED_armature_edit_bone_add(arm, "Bone");
1666 bone->parent = parent_bone;
1667 bone->flag |= BONE_CONNECTED;
1669 copy_v3_v3(bone->head, mvert[parent_v].co);
1670 copy_v3_v3(bone->tail, mvert[v].co);
1671 bone->rad_head = bone->rad_tail = 0.25;
1672 BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
1674 /* add bDeformGroup */
1675 if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) {
1676 ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
1677 ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE);
1680 skin_armature_bone_create(skin_ob,
1690 static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, SceneLayer *sl, Object *skin_ob)
1692 BLI_bitmap *edges_visited;
1693 DerivedMesh *deform_dm;
1695 Mesh *me = skin_ob->data;
1698 MVertSkin *mvert_skin;
1703 deform_dm = mesh_get_derived_deform(scene, skin_ob, CD_MASK_BAREMESH);
1704 mvert = deform_dm->getVertArray(deform_dm);
1706 /* add vertex weights to original mesh */
1707 CustomData_add_layer(&me->vdata,
1713 arm_ob = BKE_object_add(bmain, scene, sl, OB_ARMATURE, NULL);
1714 BKE_object_transform_copy(arm_ob, skin_ob);
1717 arm_ob->dtx |= OB_DRAWXRAY;
1718 arm->drawtype = ARM_LINE;
1719 arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
1721 mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN);
1722 BKE_mesh_vert_edge_map_create(&emap, &emap_mem,
1723 me->medge, me->totvert, me->totedge);
1725 edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
1727 /* note: we use EditBones here, easier to set them up and use
1728 * edit-armature functions to convert back to regular bones */
1729 for (v = 0; v < me->totvert; v++) {
1730 if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
1731 EditBone *bone = NULL;
1733 /* Unless the skin root has just one adjacent edge, create
1734 * a fake root bone (have it going off in the Y direction
1736 if (emap[v].count > 1) {
1737 bone = ED_armature_edit_bone_add(arm, "Bone");
1739 copy_v3_v3(bone->head, me->mvert[v].co);
1740 copy_v3_v3(bone->tail, me->mvert[v].co);
1742 bone->head[1] = 1.0f;
1743 bone->rad_head = bone->rad_tail = 0.25;
1746 if (emap[v].count >= 1) {
1747 skin_armature_bone_create(skin_ob,
1758 MEM_freeN(edges_visited);
1760 MEM_freeN(emap_mem);
1762 ED_armature_from_edit(arm);
1763 ED_armature_edit_free(arm);
1768 static int skin_armature_create_exec(bContext *C, wmOperator *op)
1770 Main *bmain = CTX_data_main(C);
1771 Scene *scene = CTX_data_scene(C);
1772 SceneLayer *sl = CTX_data_scene_layer(C);
1773 Object *ob = CTX_data_active_object(C), *arm_ob;
1774 Mesh *me = ob->data;
1775 ModifierData *skin_md;
1776 ArmatureModifierData *arm_md;
1778 if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
1779 BKE_reportf(op->reports, RPT_WARNING, "Mesh '%s' has no skin vertex data", me->id.name + 2);
1780 return OPERATOR_CANCELLED;
1783 /* create new armature */
1784 arm_ob = modifier_skin_armature_create(bmain, scene, sl, ob);
1786 /* add a modifier to connect the new armature to the mesh */
1787 arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);
1789 skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin);
1790 BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md);
1792 arm_md->object = arm_ob;
1793 arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION;
1794 DEG_relations_tag_update(bmain);
1795 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1798 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1800 return OPERATOR_FINISHED;
1803 static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1805 if (edit_modifier_invoke_properties(C, op))
1806 return skin_armature_create_exec(C, op);
1808 return OPERATOR_CANCELLED;
1811 void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
1813 ot->name = "Skin Armature Create";
1814 ot->description = "Create an armature that parallels the skin layout";
1815 ot->idname = "OBJECT_OT_skin_armature_create";
1817 ot->poll = skin_poll;
1818 ot->invoke = skin_armature_create_invoke;
1819 ot->exec = skin_armature_create_exec;
1822 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1823 edit_modifier_properties(ot);
1825 /************************ delta mush bind operator *********************/
1827 static int correctivesmooth_poll(bContext *C)
1829 return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0);
1832 static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
1834 Scene *scene = CTX_data_scene(C);
1835 Object *ob = ED_object_active_context(C);
1836 CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get(op, ob, eModifierType_CorrectiveSmooth);
1840 return OPERATOR_CANCELLED;
1843 if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
1844 BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
1845 return OPERATOR_CANCELLED;
1848 is_bind = (csmd->bind_coords != NULL);
1850 MEM_SAFE_FREE(csmd->bind_coords);
1851 MEM_SAFE_FREE(csmd->delta_cache);
1855 csmd->bind_coords_num = 0;
1858 /* signal to modifier to recalculate */
1859 csmd->bind_coords_num = (unsigned int)-1;
1862 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1863 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1865 return OPERATOR_FINISHED;
1868 static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1870 if (edit_modifier_invoke_properties(C, op))
1871 return correctivesmooth_bind_exec(C, op);
1873 return OPERATOR_CANCELLED;
1876 void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot)
1879 ot->name = "Corrective Smooth Bind";
1880 ot->description = "Bind base pose in Corrective Smooth modifier";
1881 ot->idname = "OBJECT_OT_correctivesmooth_bind";
1884 ot->poll = correctivesmooth_poll;
1885 ot->invoke = correctivesmooth_bind_invoke;
1886 ot->exec = correctivesmooth_bind_exec;
1889 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1890 edit_modifier_properties(ot);
1893 /************************ mdef bind operator *********************/
1895 static int meshdeform_poll(bContext *C)
1897 return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0);
1900 static int meshdeform_bind_exec(bContext *C, wmOperator *op)
1902 Scene *scene = CTX_data_scene(C);
1903 Object *ob = ED_object_active_context(C);
1904 MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
1907 return OPERATOR_CANCELLED;
1909 if (mmd->bindcagecos) {
1910 MEM_freeN(mmd->bindcagecos);
1911 if (mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1912 if (mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1913 if (mmd->bindinfluences) MEM_freeN(mmd->bindinfluences);
1914 if (mmd->bindoffsets) MEM_freeN(mmd->bindoffsets);
1915 if (mmd->dynverts) MEM_freeN(mmd->dynverts);
1916 if (mmd->bindweights) MEM_freeN(mmd->bindweights); /* deprecated */
1917 if (mmd->bindcos) MEM_freeN(mmd->bindcos); /* deprecated */
1919 mmd->bindcagecos = NULL;
1920 mmd->dyngrid = NULL;
1921 mmd->dyninfluences = NULL;
1922 mmd->bindinfluences = NULL;
1923 mmd->bindoffsets = NULL;
1924 mmd->dynverts = NULL;
1925 mmd->bindweights = NULL; /* deprecated */
1926 mmd->bindcos = NULL; /* deprecated */
1928 mmd->totcagevert = 0;
1929 mmd->totinfluence = 0;
1931 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
1932 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1936 int mode = mmd->modifier.mode;
1938 /* force modifier to run, it will call binding routine */
1939 mmd->bindfunc = mesh_deform_bind;
1940 mmd->modifier.mode |= eModifierMode_Realtime;
1942 if (ob->type == OB_MESH) {
1943 dm = mesh_create_derived_view(scene, ob, 0);
1946 else if (ob->type == OB_LATTICE) {
1947 BKE_lattice_modifiers_calc(scene, ob);
1949 else if (ob->type == OB_MBALL) {
1950 BKE_displist_make_mball(CTX_data_main(C)->eval_ctx, scene, ob);
1952 else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1953 BKE_displist_make_curveTypes(scene, ob, 0);
1956 mmd->bindfunc = NULL;
1957 mmd->modifier.mode = mode;
1960 return OPERATOR_FINISHED;
1963 static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1965 if (edit_modifier_invoke_properties(C, op))
1966 return meshdeform_bind_exec(C, op);
1968 return OPERATOR_CANCELLED;
1971 void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
1974 ot->name = "Mesh Deform Bind";
1975 ot->description = "Bind mesh to cage in mesh deform modifier";
1976 ot->idname = "OBJECT_OT_meshdeform_bind";
1979 ot->poll = meshdeform_poll;
1980 ot->invoke = meshdeform_bind_invoke;
1981 ot->exec = meshdeform_bind_exec;
1984 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1985 edit_modifier_properties(ot);
1988 /****************** explode refresh operator *********************/
1990 static int explode_poll(bContext *C)
1992 return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
1995 static int explode_refresh_exec(bContext *C, wmOperator *op)
1997 Object *ob = ED_object_active_context(C);
1998 ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
2001 return OPERATOR_CANCELLED;
2003 emd->flag |= eExplodeFlag_CalcFaces;
2005 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
2006 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2008 return OPERATOR_FINISHED;
2011 static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2013 if (edit_modifier_invoke_properties(C, op))
2014 return explode_refresh_exec(C, op);
2016 return OPERATOR_CANCELLED;
2020 void OBJECT_OT_explode_refresh(wmOperatorType *ot)
2022 ot->name = "Explode Refresh";
2023 ot->description = "Refresh data in the Explode modifier";
2024 ot->idname = "OBJECT_OT_explode_refresh";
2026 ot->poll = explode_poll;
2027 ot->invoke = explode_refresh_invoke;
2028 ot->exec = explode_refresh_exec;
2031 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2032 edit_modifier_properties(ot);
2036 /****************** ocean bake operator *********************/
2038 static int ocean_bake_poll(bContext *C)
2040 return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
2043 /* copied from init_ocean_modifier, MOD_ocean.c */
2044 static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData *omd)
2046 int do_heightfield, do_chop, do_normals, do_jacobian;
2048 if (!omd || !oc) return;
2050 do_heightfield = true;
2051 do_chop = (omd->chop_amount > 0);
2052 do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
2053 do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
2055 BKE_ocean_init(oc, omd->resolution * omd->resolution, omd->resolution * omd->resolution, omd->spatial_size, omd->spatial_size,
2056 omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
2057 omd->depth, omd->time,
2058 do_heightfield, do_chop, do_normals, do_jacobian,
2062 typedef struct OceanBakeJob {
2065 short *stop, *do_update;
2068 struct OceanCache *och;
2069 struct Ocean *ocean;
2070 struct OceanModifierData *omd;
2073 static void oceanbake_free(void *customdata)
2075 OceanBakeJob *oj = customdata;
2079 /* called by oceanbake, only to check job 'stop' value */
2080 static int oceanbake_breakjob(void *UNUSED(customdata))
2082 //OceanBakeJob *ob = (OceanBakeJob *)customdata;
2083 //return *(ob->stop);
2085 /* this is not nice yet, need to make the jobs list template better
2086 * for identifying/acting upon various different jobs */
2087 /* but for now we'll reuse the render break... */
2088 return (G.is_break);
2091 /* called by oceanbake, wmJob sends notifier */
2092 static void oceanbake_update(void *customdata, float progress, int *cancel)
2094 OceanBakeJob *oj = customdata;
2096 if (oceanbake_breakjob(oj))
2099 *(oj->do_update) = true;
2100 *(oj->progress) = progress;
2103 static void oceanbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
2105 OceanBakeJob *oj = customdata;
2108 oj->do_update = do_update;
2109 oj->progress = progress;
2111 G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
2113 BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
2119 static void oceanbake_endjob(void *customdata)
2121 OceanBakeJob *oj = customdata;
2124 BKE_ocean_free(oj->ocean);
2128 oj->omd->oceancache = oj->och;
2129 oj->omd->cached = true;
2132 static int ocean_bake_exec(bContext *C, wmOperator *op)
2134 Object *ob = ED_object_active_context(C);
2135 OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
2136 Scene *scene = CTX_data_scene(C);
2138 struct Ocean *ocean;
2140 const bool free = RNA_boolean_get(op->ptr, "free");
2146 return OPERATOR_CANCELLED;
2149 omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
2150 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
2151 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2152 return OPERATOR_FINISHED;
2155 och = BKE_ocean_init_cache(omd->cachepath, modifier_path_relbase(ob),
2156 omd->bakestart, omd->bakeend, omd->wave_scale,
2157 omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
2159 och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time");
2161 cfra = scene->r.cfra;
2163 /* precalculate time variable before baking */
2164 for (f = omd->bakestart; f <= omd->bakeend; f++) {
2165 /* from physics_fluid.c:
2167 * XXX: This can't be used due to an anim sys optimization that ignores recalc object animation,
2168 * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
2169 * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
2170 * This doesn't work with drivers:
2171 * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
2174 /* Modifying the global scene isn't nice, but we can do it in
2175 * this part of the process before a threaded job is created */
2177 //scene->r.cfra = f;
2178 //ED_update_for_newframe(CTX_data_main(C), scene, 1);
2180 /* ok, this doesn't work with drivers, but is way faster.
2181 * let's use this for now and hope nobody wants to drive the time value... */
2182 BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
2184 och->time[i] = omd->time;
2188 /* make a copy of ocean to use for baking - threadsafety */
2189 ocean = BKE_ocean_add();
2190 init_ocean_modifier_bake(ocean, omd);
2193 BKE_ocean_bake(ocean, och);
2195 omd->oceancache = och;
2198 scene->r.cfra = cfra;
2200 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
2201 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2206 scene->r.cfra = cfra;
2209 wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation",
2210 WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN);
2211 oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
2216 WM_jobs_customdata_set(wm_job, oj, oceanbake_free);
2217 WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
2218 WM_jobs_callbacks(wm_job, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
2220 WM_jobs_start(CTX_wm_manager(C), wm_job);
2224 return OPERATOR_FINISHED;
2227 static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2229 if (edit_modifier_invoke_properties(C, op))
2230 return ocean_bake_exec(C, op);
2232 return OPERATOR_CANCELLED;
2236 void OBJECT_OT_ocean_bake(wmOperatorType *ot)
2238 ot->name = "Bake Ocean";
2239 ot->description = "Bake an image sequence of ocean data";
2240 ot->idname = "OBJECT_OT_ocean_bake";
2242 ot->poll = ocean_bake_poll;
2243 ot->invoke = ocean_bake_invoke;
2244 ot->exec = ocean_bake_exec;
2247 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2248 edit_modifier_properties(ot);
2250 RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
2253 /************************ LaplacianDeform bind operator *********************/
2255 static int laplaciandeform_poll(bContext *C)
2257 return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0);
2260 static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
2262 Object *ob = ED_object_active_context(C);
2263 LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_LaplacianDeform);
2266 return OPERATOR_CANCELLED;
2267 if (lmd->flag & MOD_LAPLACIANDEFORM_BIND) {
2268 lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
2271 lmd->flag |= MOD_LAPLACIANDEFORM_BIND;
2273 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
2274 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2275 return OPERATOR_FINISHED;
2278 static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2280 if (edit_modifier_invoke_properties(C, op))
2281 return laplaciandeform_bind_exec(C, op);
2283 return OPERATOR_CANCELLED;
2286 void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
2289 ot->name = "Laplacian Deform Bind";
2290 ot->description = "Bind mesh to system in laplacian deform modifier";
2291 ot->idname = "OBJECT_OT_laplaciandeform_bind";
2294 ot->poll = laplaciandeform_poll;
2295 ot->invoke = laplaciandeform_bind_invoke;
2296 ot->exec = laplaciandeform_bind_exec;
2299 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2300 edit_modifier_properties(ot);
2303 /************************ sdef bind operator *********************/
2305 static int surfacedeform_bind_poll(bContext *C)
2307 return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0);
2310 static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
2312 Object *ob = ED_object_active_context(C);
2313 SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_SurfaceDeform);
2316 return OPERATOR_CANCELLED;
2318 if (smd->flags & MOD_SDEF_BIND) {
2319 smd->flags &= ~MOD_SDEF_BIND;
2321 else if (smd->target) {
2322 smd->flags |= MOD_SDEF_BIND;
2325 DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
2326 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2328 return OPERATOR_FINISHED;
2331 static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2333 if (edit_modifier_invoke_properties(C, op))
2334 return surfacedeform_bind_exec(C, op);
2336 return OPERATOR_CANCELLED;
2339 void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot)
2342 ot->name = "Surface Deform Bind";
2343 ot->description = "Bind mesh to target in surface deform modifier";
2344 ot->idname = "OBJECT_OT_surfacedeform_bind";
2347 ot->poll = surfacedeform_bind_poll;
2348 ot->invoke = surfacedeform_bind_invoke;
2349 ot->exec = surfacedeform_bind_exec;
2352 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2353 edit_modifier_properties(ot);