diff options
author | Bastien Montagne <bastien@blender.org> | 2020-07-09 12:44:11 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2020-07-09 12:46:28 +0300 |
commit | 8ddf7556a512b2b2ce89b75c9660e01a7aba8675 (patch) | |
tree | af98ecda886e9a12f65a30eba87357ea011eed8a /source/blender | |
parent | ea5fe7abc183c1e53d327f97280f589499fe60bb (diff) |
Fix T78718: Crash when deleting particle system modifier with the X Shortcut.
Duplication and deletion code of modifiers was totally wrong for
particle system, that special weird thing needs its own custom
management.
Note that for now I chose not to duplicate the particle settings ID when
duplicating the modifier...
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 28 | ||||
-rw-r--r-- | source/blender/editors/include/ED_object.h | 5 | ||||
-rw-r--r-- | source/blender/editors/object/object_edit.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 48 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_tools.c | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object.c | 5 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object_force.c | 2 |
8 files changed, 67 insertions, 30 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index a22cb9ef126..7de588450d6 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -365,6 +365,10 @@ struct ModifierData *object_add_particle_system(struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name); +struct ModifierData *object_copy_particle_system(struct Main *bmain, + struct Scene *scene, + struct Object *ob, + const struct ParticleSystem *psys_orig); void object_remove_particle_system(struct Main *bmain, struct Scene *scene, struct Object *ob); struct ParticleSettings *BKE_particlesettings_add(struct Main *bmain, const char *name); struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 942f3e0ca2b..cb1b523a7a9 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3611,7 +3611,8 @@ void psys_mat_hair_to_global( /************************************************/ /* ParticleSettings handling */ /************************************************/ -ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, const char *name) +static ModifierData *object_add_or_copy_particle_system( + Main *bmain, Scene *scene, Object *ob, const char *name, const ParticleSystem *psys_orig) { ParticleSystem *psys; ModifierData *md; @@ -3622,7 +3623,7 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, } if (name == NULL) { - name = DATA_("ParticleSettings"); + name = (psys_orig != NULL) ? psys_orig->name : DATA_("ParticleSettings"); } psys = ob->particlesystem.first; @@ -3635,8 +3636,13 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, BLI_addtail(&ob->particlesystem, psys); psys_unique_name(ob, psys, name); - psys->part = BKE_particlesettings_add(bmain, psys->name); - + if (psys_orig != NULL) { + psys->part = psys_orig->part; + id_us_plus(&psys->part->id); + } + else { + psys->part = BKE_particlesettings_add(bmain, psys->name); + } md = BKE_modifier_new(eModifierType_ParticleSystem); BLI_strncpy(md->name, psys->name, sizeof(md->name)); BKE_modifier_unique_name(&ob->modifiers, md); @@ -3656,6 +3662,20 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, return md; } + +ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, const char *name) +{ + return object_add_or_copy_particle_system(bmain, scene, ob, name, NULL); +} + +ModifierData *object_copy_particle_system(Main *bmain, + Scene *scene, + Object *ob, + const ParticleSystem *psys_orig) +{ + return object_add_or_copy_particle_system(bmain, scene, ob, NULL, psys_orig); +} + void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob) { ParticleSystem *psys = psys_get_current(ob); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 5ec4de5d597..d8f55a0f60a 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -362,9 +362,10 @@ struct ModifierData *ED_object_modifier_add(struct ReportList *reports, int type); bool ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain, + struct Scene *scene, struct Object *ob, struct ModifierData *md); -void ED_object_modifier_clear(struct Main *bmain, struct Object *ob); +void ED_object_modifier_clear(struct Main *bmain, struct Scene *scene, struct Object *ob); bool ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md); @@ -392,6 +393,8 @@ bool ED_object_modifier_apply(struct Main *bmain, int mode, bool keep_modifier); int ED_object_modifier_copy(struct ReportList *reports, + struct Main *bmain, + struct Scene *scene, struct Object *ob, struct ModifierData *md); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index a9eb454eb04..04113f70e52 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -895,7 +895,7 @@ void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object) else { if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) || ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) { - ED_object_modifier_remove(NULL, bmain, object, md); + ED_object_modifier_remove(NULL, bmain, scene, object, md); } } } diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 6c929ad781e..6f254ea9400 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -330,10 +330,8 @@ static bool object_modifier_safe_to_delete(Main *bmain, !ED_object_iter_other(bmain, ob, false, object_has_modifier_cb, &type)); } -static bool object_modifier_remove(Main *bmain, - Object *ob, - ModifierData *md, - bool *r_sort_depsgraph) +static bool object_modifier_remove( + Main *bmain, Scene *scene, Object *ob, ModifierData *md, bool *r_sort_depsgraph) { /* It seems on rapid delete it is possible to * get called twice on same modifier, so make @@ -344,11 +342,8 @@ static bool object_modifier_remove(Main *bmain, /* special cases */ if (md->type == eModifierType_ParticleSystem) { - ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; - - BLI_remlink(&ob->particlesystem, psmd->psys); - psys_free(ob, psmd->psys); - psmd->psys = NULL; + object_remove_particle_system(bmain, scene, ob); + return true; } else if (md->type == eModifierType_Softbody) { if (ob->soft) { @@ -391,12 +386,13 @@ static bool object_modifier_remove(Main *bmain, return 1; } -bool ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, ModifierData *md) +bool ED_object_modifier_remove( + ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md) { bool sort_depsgraph = false; bool ok; - ok = object_modifier_remove(bmain, ob, md, &sort_depsgraph); + ok = object_modifier_remove(bmain, scene, ob, md, &sort_depsgraph); if (!ok) { BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name); @@ -409,7 +405,7 @@ bool ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, Mod return 1; } -void ED_object_modifier_clear(Main *bmain, Object *ob) +void ED_object_modifier_clear(Main *bmain, Scene *scene, Object *ob) { ModifierData *md = ob->modifiers.first; bool sort_depsgraph = false; @@ -423,7 +419,7 @@ void ED_object_modifier_clear(Main *bmain, Object *ob) next_md = md->next; - object_modifier_remove(bmain, ob, md, &sort_depsgraph); + object_modifier_remove(bmain, scene, ob, md, &sort_depsgraph); md = next_md; } @@ -881,14 +877,23 @@ bool ED_object_modifier_apply(Main *bmain, return true; } -int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md) +int ED_object_modifier_copy( + ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md) { ModifierData *nmd; - nmd = BKE_modifier_new(md->type); - BKE_modifier_copydata(md, nmd); - BLI_insertlinkafter(&ob->modifiers, md, nmd); - BKE_modifier_unique_name(&ob->modifiers, nmd); + if (md->type == eModifierType_ParticleSystem) { + nmd = object_copy_particle_system(bmain, scene, ob, ((ParticleSystemModifierData *)md)->psys); + BLI_remlink(&ob->modifiers, nmd); + BLI_insertlinkafter(&ob->modifiers, md, nmd); + return true; + } + else { + nmd = BKE_modifier_new(md->type); + BKE_modifier_copydata(md, nmd); + BLI_insertlinkafter(&ob->modifiers, md, nmd); + BKE_modifier_unique_name(&ob->modifiers, nmd); + } return 1; } @@ -1120,6 +1125,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type) static int modifier_remove_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); @@ -1133,7 +1139,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) char name[MAX_NAME]; strcpy(name, md->name); - if (!ED_object_modifier_remove(op->reports, bmain, ob, md)) { + if (!ED_object_modifier_remove(op->reports, bmain, scene, ob, md)) { return OPERATOR_CANCELLED; } @@ -1547,10 +1553,12 @@ void OBJECT_OT_modifier_convert(wmOperatorType *ot) static int modifier_copy_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); - if (!md || !ED_object_modifier_copy(op->reports, ob, md)) { + if (!md || !ED_object_modifier_copy(op->reports, bmain, scene, ob, md)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index a77b5424eb6..419e25d5dca 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -1127,6 +1127,7 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem { bContext *C = (bContext *)Carg; Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); ModifierData *md = (ModifierData *)te->directdata; Object *ob = (Object *)outliner_search_back(te, ID_OB); @@ -1141,7 +1142,7 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); } else if (event == OL_MODIFIER_OP_DELETE) { - ED_object_modifier_remove(NULL, bmain, ob, md); + ED_object_modifier_remove(NULL, bmain, scene, ob, md); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER | NA_REMOVED, ob); te->store_elem->flag &= ~TSE_SELECTED; } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 089410ffd25..00d3a6e84b7 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1579,7 +1579,8 @@ static void rna_Object_modifier_remove(Object *object, PointerRNA *md_ptr) { ModifierData *md = md_ptr->data; - if (ED_object_modifier_remove(reports, CTX_data_main(C), object, md) == false) { + if (ED_object_modifier_remove(reports, CTX_data_main(C), CTX_data_scene(C), object, md) == + false) { /* error is already set */ return; } @@ -1591,7 +1592,7 @@ static void rna_Object_modifier_remove(Object *object, static void rna_Object_modifier_clear(Object *object, bContext *C) { - ED_object_modifier_clear(CTX_data_main(C), object); + ED_object_modifier_clear(CTX_data_main(C), CTX_data_scene(C), object); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, object); } diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 0b932f3236f..2524f590051 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -851,7 +851,7 @@ static void rna_CollisionSettings_dependency_update(Main *bmain, Scene *scene, P ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Collision); } else if (!ob->pd->deflect && md) { - ED_object_modifier_remove(NULL, bmain, ob, md); + ED_object_modifier_remove(NULL, bmain, scene, ob, md); } WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); |