diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/editors/physics/particle_object.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/editors/physics/particle_object.c')
-rw-r--r-- | source/blender/editors/physics/particle_object.c | 1916 |
1 files changed, 975 insertions, 941 deletions
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 2287659ef03..92eed9be2f5 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -21,7 +21,6 @@ * \ingroup edphys */ - #include <stdlib.h> #include <string.h> @@ -70,956 +69,971 @@ #include "physics_intern.h" -static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}; +static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}; /********************** particle system slot operators *********************/ static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - Object *ob = ED_object_context(C); - Scene *scene = CTX_data_scene(C); + Main *bmain = CTX_data_main(C); + Object *ob = ED_object_context(C); + Scene *scene = CTX_data_scene(C); - if (!scene || !ob) - return OPERATOR_CANCELLED; + if (!scene || !ob) + return OPERATOR_CANCELLED; - object_add_particle_system(bmain, scene, ob, NULL); + object_add_particle_system(bmain, scene, ob, NULL); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void OBJECT_OT_particle_system_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Particle System Slot"; - ot->idname = "OBJECT_OT_particle_system_add"; - ot->description = "Add a particle system"; + /* identifiers */ + ot->name = "Add Particle System Slot"; + ot->idname = "OBJECT_OT_particle_system_add"; + ot->description = "Add a particle system"; - /* api callbacks */ - ot->poll = ED_operator_object_active_editable; - ot->exec = particle_system_add_exec; + /* api callbacks */ + ot->poll = ED_operator_object_active_editable; + ot->exec = particle_system_add_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - Object *ob = ED_object_context(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - int mode_orig; - - if (!scene || !ob) - return OPERATOR_CANCELLED; - - mode_orig = ob->mode; - object_remove_particle_system(bmain, scene, ob); - - /* possible this isn't the active object - * object_remove_particle_system() clears the mode on the last psys - */ - if (mode_orig & OB_MODE_PARTICLE_EDIT) { - if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) { - if (view_layer->basact && view_layer->basact->object == ob) { - WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); - } - } - } - - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob); - - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + Object *ob = ED_object_context(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + int mode_orig; + + if (!scene || !ob) + return OPERATOR_CANCELLED; + + mode_orig = ob->mode; + object_remove_particle_system(bmain, scene, ob); + + /* possible this isn't the active object + * object_remove_particle_system() clears the mode on the last psys + */ + if (mode_orig & OB_MODE_PARTICLE_EDIT) { + if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) { + if (view_layer->basact && view_layer->basact->object == ob) { + WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); + } + } + } + + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, ob); + + return OPERATOR_FINISHED; } void OBJECT_OT_particle_system_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Particle System Slot"; - ot->idname = "OBJECT_OT_particle_system_remove"; - ot->description = "Remove the selected particle system"; + /* identifiers */ + ot->name = "Remove Particle System Slot"; + ot->idname = "OBJECT_OT_particle_system_remove"; + ot->description = "Remove the selected particle system"; - /* api callbacks */ - ot->poll = ED_operator_object_active_editable; - ot->exec = particle_system_remove_exec; + /* api callbacks */ + ot->poll = ED_operator_object_active_editable; + ot->exec = particle_system_remove_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /********************** new particle settings operator *********************/ static bool psys_poll(bContext *C) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - return (ptr.data != NULL); + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + return (ptr.data != NULL); } static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - ParticleSystem *psys; - ParticleSettings *part = NULL; - Object *ob; - PointerRNA ptr; + Main *bmain = CTX_data_main(C); + ParticleSystem *psys; + ParticleSettings *part = NULL; + Object *ob; + PointerRNA ptr; - ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - psys = ptr.data; + psys = ptr.data; - /* add or copy particle setting */ - if (psys->part) - part = BKE_particlesettings_copy(bmain, psys->part); - else - part = BKE_particlesettings_add(bmain, "ParticleSettings"); + /* add or copy particle setting */ + if (psys->part) + part = BKE_particlesettings_copy(bmain, psys->part); + else + part = BKE_particlesettings_add(bmain, "ParticleSettings"); - ob = ptr.id.data; + ob = ptr.id.data; - if (psys->part) - id_us_min(&psys->part->id); + if (psys->part) + id_us_min(&psys->part->id); - psys->part = part; + psys->part = part; - psys_check_boid_data(psys); + psys_check_boid_data(psys); - DEG_relations_tag_update(bmain); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void PARTICLE_OT_new(wmOperatorType *ot) { - /* identifiers */ - ot->name = "New Particle Settings"; - ot->idname = "PARTICLE_OT_new"; - ot->description = "Add new particle settings"; + /* identifiers */ + ot->name = "New Particle Settings"; + ot->idname = "PARTICLE_OT_new"; + ot->description = "Add new particle settings"; - /* api callbacks */ - ot->exec = new_particle_settings_exec; - ot->poll = psys_poll; + /* api callbacks */ + ot->exec = new_particle_settings_exec; + ot->poll = psys_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /********************** keyed particle target operators *********************/ static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; - Object *ob = ptr.id.data; + Main *bmain = CTX_data_main(C); + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; + Object *ob = ptr.id.data; - ParticleTarget *pt; + ParticleTarget *pt; - if (!psys) - return OPERATOR_CANCELLED; + if (!psys) + return OPERATOR_CANCELLED; - pt = psys->targets.first; - for (; pt; pt = pt->next) - pt->flag &= ~PTARGET_CURRENT; + pt = psys->targets.first; + for (; pt; pt = pt->next) + pt->flag &= ~PTARGET_CURRENT; - pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target"); + pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target"); - pt->flag |= PTARGET_CURRENT; - pt->psys = 1; + pt->flag |= PTARGET_CURRENT; + pt->psys = 1; - BLI_addtail(&psys->targets, pt); + BLI_addtail(&psys->targets, pt); - DEG_relations_tag_update(bmain); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void PARTICLE_OT_new_target(wmOperatorType *ot) { - /* identifiers */ - ot->name = "New Particle Target"; - ot->idname = "PARTICLE_OT_new_target"; - ot->description = "Add a new particle target"; + /* identifiers */ + ot->name = "New Particle Target"; + ot->idname = "PARTICLE_OT_new_target"; + ot->description = "Add a new particle target"; - /* api callbacks */ - ot->exec = new_particle_target_exec; + /* api callbacks */ + ot->exec = new_particle_target_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; - Object *ob = ptr.id.data; - - ParticleTarget *pt; + Main *bmain = CTX_data_main(C); + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; + Object *ob = ptr.id.data; - if (!psys) - return OPERATOR_CANCELLED; + ParticleTarget *pt; - pt = psys->targets.first; - for (; pt; pt = pt->next) { - if (pt->flag & PTARGET_CURRENT) { - BLI_remlink(&psys->targets, pt); - MEM_freeN(pt); - break; - } + if (!psys) + return OPERATOR_CANCELLED; - } - pt = psys->targets.last; + pt = psys->targets.first; + for (; pt; pt = pt->next) { + if (pt->flag & PTARGET_CURRENT) { + BLI_remlink(&psys->targets, pt); + MEM_freeN(pt); + break; + } + } + pt = psys->targets.last; - if (pt) - pt->flag |= PTARGET_CURRENT; + if (pt) + pt->flag |= PTARGET_CURRENT; - DEG_relations_tag_update(bmain); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void PARTICLE_OT_target_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Particle Target"; - ot->idname = "PARTICLE_OT_target_remove"; - ot->description = "Remove the selected particle target"; + /* identifiers */ + ot->name = "Remove Particle Target"; + ot->idname = "PARTICLE_OT_target_remove"; + ot->description = "Remove the selected particle target"; - /* api callbacks */ - ot->exec = remove_particle_target_exec; + /* api callbacks */ + ot->exec = remove_particle_target_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /************************ move up particle target operator *********************/ static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; - Object *ob = ptr.id.data; - ParticleTarget *pt; - - if (!psys) - return OPERATOR_CANCELLED; - - pt = psys->targets.first; - for (; pt; pt = pt->next) { - if (pt->flag & PTARGET_CURRENT && pt->prev) { - BLI_remlink(&psys->targets, pt); - BLI_insertlinkbefore(&psys->targets, pt->prev, pt); - - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - break; - } - } - - return OPERATOR_FINISHED; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; + Object *ob = ptr.id.data; + ParticleTarget *pt; + + if (!psys) + return OPERATOR_CANCELLED; + + pt = psys->targets.first; + for (; pt; pt = pt->next) { + if (pt->flag & PTARGET_CURRENT && pt->prev) { + BLI_remlink(&psys->targets, pt); + BLI_insertlinkbefore(&psys->targets, pt->prev, pt); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + break; + } + } + + return OPERATOR_FINISHED; } void PARTICLE_OT_target_move_up(wmOperatorType *ot) { - ot->name = "Move Up Target"; - ot->idname = "PARTICLE_OT_target_move_up"; - ot->description = "Move particle target up in the list"; + ot->name = "Move Up Target"; + ot->idname = "PARTICLE_OT_target_move_up"; + ot->description = "Move particle target up in the list"; - ot->exec = target_move_up_exec; + ot->exec = target_move_up_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /************************ move down particle target operator *********************/ static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; - Object *ob = ptr.id.data; - ParticleTarget *pt; - - if (!psys) - return OPERATOR_CANCELLED; - pt = psys->targets.first; - for (; pt; pt = pt->next) { - if (pt->flag & PTARGET_CURRENT && pt->next) { - BLI_remlink(&psys->targets, pt); - BLI_insertlinkafter(&psys->targets, pt->next, pt); - - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - break; - } - } - - return OPERATOR_FINISHED; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; + Object *ob = ptr.id.data; + ParticleTarget *pt; + + if (!psys) + return OPERATOR_CANCELLED; + pt = psys->targets.first; + for (; pt; pt = pt->next) { + if (pt->flag & PTARGET_CURRENT && pt->next) { + BLI_remlink(&psys->targets, pt); + BLI_insertlinkafter(&psys->targets, pt->next, pt); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + break; + } + } + + return OPERATOR_FINISHED; } void PARTICLE_OT_target_move_down(wmOperatorType *ot) { - ot->name = "Move Down Target"; - ot->idname = "PARTICLE_OT_target_move_down"; - ot->description = "Move particle target down in the list"; + ot->name = "Move Down Target"; + ot->idname = "PARTICLE_OT_target_move_down"; + ot->description = "Move particle target down in the list"; - ot->exec = target_move_down_exec; + ot->exec = target_move_down_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /************************ refresh dupli objects *********************/ static int dupliob_refresh_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; - if (!psys) - return OPERATOR_CANCELLED; + if (!psys) + return OPERATOR_CANCELLED; - psys_check_group_weights(psys->part); - DEG_id_tag_update(&psys->part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); + psys_check_group_weights(psys->part); + DEG_id_tag_update(&psys->part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void PARTICLE_OT_dupliob_refresh(wmOperatorType *ot) { - ot->name = "Refresh Dupli Objects"; - ot->idname = "PARTICLE_OT_dupliob_refresh"; - ot->description = "Refresh list of dupli objects and their weights"; + ot->name = "Refresh Dupli Objects"; + ot->idname = "PARTICLE_OT_dupliob_refresh"; + ot->description = "Refresh list of dupli objects and their weights"; - ot->exec = dupliob_refresh_exec; + ot->exec = dupliob_refresh_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /************************ move up particle dupliweight operator *********************/ static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; - ParticleSettings *part; - ParticleDupliWeight *dw; - - if (!psys) - return OPERATOR_CANCELLED; - - part = psys->part; - for (dw = part->instance_weights.first; dw; dw = dw->next) { - if (dw->flag & PART_DUPLIW_CURRENT && dw->prev) { - BLI_remlink(&part->instance_weights, dw); - BLI_insertlinkbefore(&part->instance_weights, dw->prev, dw); - - DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); - break; - } - } - - return OPERATOR_FINISHED; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; + ParticleSettings *part; + ParticleDupliWeight *dw; + + if (!psys) + return OPERATOR_CANCELLED; + + part = psys->part; + for (dw = part->instance_weights.first; dw; dw = dw->next) { + if (dw->flag & PART_DUPLIW_CURRENT && dw->prev) { + BLI_remlink(&part->instance_weights, dw); + BLI_insertlinkbefore(&part->instance_weights, dw->prev, dw); + + DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); + break; + } + } + + return OPERATOR_FINISHED; } void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot) { - ot->name = "Move Up Dupli Object"; - ot->idname = "PARTICLE_OT_dupliob_move_up"; - ot->description = "Move dupli object up in the list"; + ot->name = "Move Up Dupli Object"; + ot->idname = "PARTICLE_OT_dupliob_move_up"; + ot->description = "Move dupli object up in the list"; - ot->exec = dupliob_move_up_exec; + ot->exec = dupliob_move_up_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /********************** particle dupliweight operators *********************/ static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; - ParticleSettings *part; - ParticleDupliWeight *dw; - - if (!psys) - return OPERATOR_CANCELLED; - part = psys->part; - for (dw = part->instance_weights.first; dw; dw = dw->next) { - if (dw->flag & PART_DUPLIW_CURRENT) { - dw->flag &= ~PART_DUPLIW_CURRENT; - dw = MEM_dupallocN(dw); - dw->flag |= PART_DUPLIW_CURRENT; - BLI_addhead(&part->instance_weights, dw); - - DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); - break; - } - } - - return OPERATOR_FINISHED; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; + ParticleSettings *part; + ParticleDupliWeight *dw; + + if (!psys) + return OPERATOR_CANCELLED; + part = psys->part; + for (dw = part->instance_weights.first; dw; dw = dw->next) { + if (dw->flag & PART_DUPLIW_CURRENT) { + dw->flag &= ~PART_DUPLIW_CURRENT; + dw = MEM_dupallocN(dw); + dw->flag |= PART_DUPLIW_CURRENT; + BLI_addhead(&part->instance_weights, dw); + + DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); + break; + } + } + + return OPERATOR_FINISHED; } void PARTICLE_OT_dupliob_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Particle Dupliob"; - ot->idname = "PARTICLE_OT_dupliob_copy"; - ot->description = "Duplicate the current dupliobject"; + /* identifiers */ + ot->name = "Copy Particle Dupliob"; + ot->idname = "PARTICLE_OT_dupliob_copy"; + ot->description = "Duplicate the current dupliobject"; - /* api callbacks */ - ot->exec = copy_particle_dupliob_exec; + /* api callbacks */ + ot->exec = copy_particle_dupliob_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int remove_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; - ParticleSettings *part; - ParticleDupliWeight *dw; - - if (!psys) - return OPERATOR_CANCELLED; - - part = psys->part; - for (dw = part->instance_weights.first; dw; dw = dw->next) { - if (dw->flag & PART_DUPLIW_CURRENT) { - BLI_remlink(&part->instance_weights, dw); - MEM_freeN(dw); - break; - } - - } - dw = part->instance_weights.last; - - if (dw) - dw->flag |= PART_DUPLIW_CURRENT; - - DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); - - return OPERATOR_FINISHED; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; + ParticleSettings *part; + ParticleDupliWeight *dw; + + if (!psys) + return OPERATOR_CANCELLED; + + part = psys->part; + for (dw = part->instance_weights.first; dw; dw = dw->next) { + if (dw->flag & PART_DUPLIW_CURRENT) { + BLI_remlink(&part->instance_weights, dw); + MEM_freeN(dw); + break; + } + } + dw = part->instance_weights.last; + + if (dw) + dw->flag |= PART_DUPLIW_CURRENT; + + DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); + + return OPERATOR_FINISHED; } void PARTICLE_OT_dupliob_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Particle Dupliobject"; - ot->idname = "PARTICLE_OT_dupliob_remove"; - ot->description = "Remove the selected dupliobject"; + /* identifiers */ + ot->name = "Remove Particle Dupliobject"; + ot->idname = "PARTICLE_OT_dupliob_remove"; + ot->description = "Remove the selected dupliobject"; - /* api callbacks */ - ot->exec = remove_particle_dupliob_exec; + /* api callbacks */ + ot->exec = remove_particle_dupliob_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /************************ move down particle dupliweight operator *********************/ static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op)) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); - ParticleSystem *psys = ptr.data; - ParticleSettings *part; - ParticleDupliWeight *dw; - - if (!psys) - return OPERATOR_CANCELLED; - - part = psys->part; - for (dw = part->instance_weights.first; dw; dw = dw->next) { - if (dw->flag & PART_DUPLIW_CURRENT && dw->next) { - BLI_remlink(&part->instance_weights, dw); - BLI_insertlinkafter(&part->instance_weights, dw->next, dw); - - DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); - break; - } - } - - return OPERATOR_FINISHED; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys = ptr.data; + ParticleSettings *part; + ParticleDupliWeight *dw; + + if (!psys) + return OPERATOR_CANCELLED; + + part = psys->part; + for (dw = part->instance_weights.first; dw; dw = dw->next) { + if (dw->flag & PART_DUPLIW_CURRENT && dw->next) { + BLI_remlink(&part->instance_weights, dw); + BLI_insertlinkafter(&part->instance_weights, dw->next, dw); + + DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL); + break; + } + } + + return OPERATOR_FINISHED; } void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot) { - ot->name = "Move Down Dupli Object"; - ot->idname = "PARTICLE_OT_dupliob_move_down"; - ot->description = "Move dupli object down in the list"; + ot->name = "Move Down Dupli Object"; + ot->idname = "PARTICLE_OT_dupliob_move_down"; + ot->description = "Move dupli object down in the list"; - ot->exec = dupliob_move_down_exec; + ot->exec = dupliob_move_down_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /************************ connect/disconnect hair operators *********************/ -static void disconnect_hair( - Depsgraph *depsgraph, Scene *scene, - Object *ob, ParticleSystem *psys) +static void disconnect_hair(Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys) { - Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); - ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys); - ParticleSystemModifierData *psmd_eval = - psys_get_modifier(object_eval, psys_eval); - ParticleEditSettings *pset = PE_settings(scene); - ParticleData *pa; - PTCacheEdit *edit; - PTCacheEditPoint *point; - PTCacheEditKey *ekey = NULL; - HairKey *key; - int i, k; - float hairmat[4][4]; - - if (!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR) - return; - - if (!psys->part || psys->part->type != PART_HAIR) - return; - - edit = psys->edit; - point = edit ? edit->points : NULL; - - for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) { - if (point) { - ekey = point->keys; - point++; - } - - psys_mat_hair_to_global( - ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat); - - for (k = 0, key = pa->hair; k < pa->totkey; k++, key++) { - mul_m4_v3(hairmat, key->co); - - if (ekey) { - ekey->flag &= ~PEK_USE_WCO; - ekey++; - } - } - } - - psys_free_path_cache(psys, psys->edit); - - psys->flag |= PSYS_GLOBAL_HAIR; - - if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF)) { - pset->brushtype = PE_BRUSH_COMB; - } - - PE_update_object(depsgraph, scene, ob, 0); + Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); + ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys); + ParticleSystemModifierData *psmd_eval = psys_get_modifier(object_eval, psys_eval); + ParticleEditSettings *pset = PE_settings(scene); + ParticleData *pa; + PTCacheEdit *edit; + PTCacheEditPoint *point; + PTCacheEditKey *ekey = NULL; + HairKey *key; + int i, k; + float hairmat[4][4]; + + if (!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR) + return; + + if (!psys->part || psys->part->type != PART_HAIR) + return; + + edit = psys->edit; + point = edit ? edit->points : NULL; + + for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) { + if (point) { + ekey = point->keys; + point++; + } + + psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat); + + for (k = 0, key = pa->hair; k < pa->totkey; k++, key++) { + mul_m4_v3(hairmat, key->co); + + if (ekey) { + ekey->flag &= ~PEK_USE_WCO; + ekey++; + } + } + } + + psys_free_path_cache(psys, psys->edit); + + psys->flag |= PSYS_GLOBAL_HAIR; + + if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF)) { + pset->brushtype = PE_BRUSH_COMB; + } + + PE_update_object(depsgraph, scene, ob, 0); } static int disconnect_hair_exec(bContext *C, wmOperator *op) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - Object *ob = ED_object_context(C); - ParticleSystem *psys = NULL; - const bool all = RNA_boolean_get(op->ptr, "all"); - - if (!ob) - return OPERATOR_CANCELLED; - - if (all) { - for (psys = ob->particlesystem.first; psys; psys = psys->next) { - disconnect_hair(depsgraph, scene, ob, psys); - } - } - else { - psys = psys_get_current(ob); - disconnect_hair(depsgraph, scene, ob, psys); - } - - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - - return OPERATOR_FINISHED; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + Object *ob = ED_object_context(C); + ParticleSystem *psys = NULL; + const bool all = RNA_boolean_get(op->ptr, "all"); + + if (!ob) + return OPERATOR_CANCELLED; + + if (all) { + for (psys = ob->particlesystem.first; psys; psys = psys->next) { + disconnect_hair(depsgraph, scene, ob, psys); + } + } + else { + psys = psys_get_current(ob); + disconnect_hair(depsgraph, scene, ob, psys); + } + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + + return OPERATOR_FINISHED; } void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) { - ot->name = "Disconnect Hair"; - ot->description = "Disconnect hair from the emitter mesh"; - ot->idname = "PARTICLE_OT_disconnect_hair"; + ot->name = "Disconnect Hair"; + ot->description = "Disconnect hair from the emitter mesh"; + ot->idname = "PARTICLE_OT_disconnect_hair"; - ot->exec = disconnect_hair_exec; + ot->exec = disconnect_hair_exec; - /* flags */ - /* No REGISTER, redo does not work due to missing update, see T47750. */ - ot->flag = OPTYPE_UNDO; + /* flags */ + /* No REGISTER, redo does not work due to missing update, see T47750. */ + ot->flag = OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh"); + RNA_def_boolean( + ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh"); } /* from/to_world_space : whether from/to particles are in world or hair space * from/to_mat : additional transform for from/to particles (e.g. for using object space copying) */ -static bool remap_hair_emitter( - Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys, - Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit, - float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global) +static bool remap_hair_emitter(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + ParticleSystem *psys, + Object *target_ob, + ParticleSystem *target_psys, + PTCacheEdit *target_edit, + float from_mat[4][4], + float to_mat[4][4], + bool from_global, + bool to_global) { - Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); - ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys); - ParticleSystemModifierData *target_psmd = - psys_get_modifier(object_eval, psys_eval); - ParticleData *pa, *tpa; - PTCacheEditPoint *edit_point; - PTCacheEditKey *ekey; - BVHTreeFromMesh bvhtree = {NULL}; - MFace *mface = NULL, *mf; - MEdge *medge = NULL, *me; - MVert *mvert; - Mesh *mesh, *target_mesh; - int numverts; - int i, k; - float from_ob_imat[4][4], to_ob_imat[4][4]; - float from_imat[4][4], to_imat[4][4]; - - if (!target_psmd->mesh_final) - return false; - if (!psys->part || psys->part->type != PART_HAIR) - return false; - if (!target_psys->part || target_psys->part->type != PART_HAIR) - return false; - - edit_point = target_edit ? target_edit->points : NULL; - - invert_m4_m4(from_ob_imat, ob->obmat); - invert_m4_m4(to_ob_imat, target_ob->obmat); - invert_m4_m4(from_imat, from_mat); - invert_m4_m4(to_imat, to_mat); - - if (target_psmd->mesh_final->runtime.deformed_only) { - /* we don't want to mess up target_psmd->dm when converting to global coordinates below */ - mesh = target_psmd->mesh_final; - } - else { - mesh = target_psmd->mesh_original; - } - target_mesh = target_psmd->mesh_final; - if (mesh == NULL) { - return false; - } - /* don't modify the original vertices */ - BKE_id_copy_ex(NULL, &mesh->id, (ID **)&mesh, LIB_ID_COPY_LOCALIZE); - - /* BMESH_ONLY, deform dm may not have tessface */ - BKE_mesh_tessface_ensure(mesh); - - numverts = mesh->totvert; - mvert = mesh->mvert; - - /* convert to global coordinates */ - for (i = 0; i < numverts; i++) - mul_m4_v3(to_mat, mvert[i].co); - - if (mesh->totface != 0) { - mface = mesh->mface; - BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2); - } - else if (mesh->totedge != 0) { - medge = mesh->medge; - BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2); - } - else { - BKE_id_free(NULL, mesh); - return false; - } - - for (i = 0, tpa = target_psys->particles, pa = psys->particles; - i < target_psys->totpart; - i++, tpa++, pa++) - { - float from_co[3]; - BVHTreeNearest nearest; - - if (from_global) - mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co); - else - mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co); - mul_m4_v3(from_mat, from_co); - - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - - BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); - - if (nearest.index == -1) { - if (G.debug & G_DEBUG) - printf("No nearest point found for hair root!"); - continue; - } - - if (mface) { - float v[4][3]; - - mf = &mface[nearest.index]; - - copy_v3_v3(v[0], mvert[mf->v1].co); - copy_v3_v3(v[1], mvert[mf->v2].co); - copy_v3_v3(v[2], mvert[mf->v3].co); - if (mf->v4) { - copy_v3_v3(v[3], mvert[mf->v4].co); - interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co); - } - else - interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co); - tpa->foffset = 0.0f; - - tpa->num = nearest.index; - tpa->num_dmcache = psys_particle_dm_face_lookup(target_mesh, mesh, tpa->num, tpa->fuv, NULL); - } - else { - me = &medge[nearest.index]; - - tpa->fuv[1] = line_point_factor_v3(nearest.co, - mvert[me->v1].co, - mvert[me->v2].co); - tpa->fuv[0] = 1.0f - tpa->fuv[1]; - tpa->fuv[2] = tpa->fuv[3] = 0.0f; - tpa->foffset = 0.0f; - - tpa->num = nearest.index; - tpa->num_dmcache = -1; - } - - /* translate hair keys */ - { - HairKey *key, *tkey; - float hairmat[4][4], imat[4][4]; - float offset[3]; - - if (to_global) - copy_m4_m4(imat, target_ob->obmat); - else { - /* note: using target_dm here, which is in target_ob object space and has full modifiers */ - psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat); - invert_m4_m4(imat, hairmat); - } - mul_m4_m4m4(imat, imat, to_imat); - - /* offset in world space */ - sub_v3_v3v3(offset, nearest.co, from_co); - - if (edit_point) { - for (k = 0, key = pa->hair, tkey = tpa->hair, ekey = edit_point->keys; k < tpa->totkey; k++, key++, tkey++, ekey++) { - float co_orig[3]; - - if (from_global) - mul_v3_m4v3(co_orig, from_ob_imat, key->co); - else - mul_v3_m4v3(co_orig, from_ob_imat, key->world_co); - mul_m4_v3(from_mat, co_orig); - - add_v3_v3v3(tkey->co, co_orig, offset); - - mul_m4_v3(imat, tkey->co); - - ekey->flag |= PEK_USE_WCO; - } - - edit_point++; - } - else { - for (k = 0, key = pa->hair, tkey = tpa->hair; k < tpa->totkey; k++, key++, tkey++) { - float co_orig[3]; - - if (from_global) - mul_v3_m4v3(co_orig, from_ob_imat, key->co); - else - mul_v3_m4v3(co_orig, from_ob_imat, key->world_co); - mul_m4_v3(from_mat, co_orig); - - add_v3_v3v3(tkey->co, co_orig, offset); - - mul_m4_v3(imat, tkey->co); - } - } - } - } - - free_bvhtree_from_mesh(&bvhtree); - BKE_id_free(NULL, mesh); - - psys_free_path_cache(target_psys, target_edit); - - PE_update_object(depsgraph, scene, target_ob, 0); - - return true; + Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); + ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys); + ParticleSystemModifierData *target_psmd = psys_get_modifier(object_eval, psys_eval); + ParticleData *pa, *tpa; + PTCacheEditPoint *edit_point; + PTCacheEditKey *ekey; + BVHTreeFromMesh bvhtree = {NULL}; + MFace *mface = NULL, *mf; + MEdge *medge = NULL, *me; + MVert *mvert; + Mesh *mesh, *target_mesh; + int numverts; + int i, k; + float from_ob_imat[4][4], to_ob_imat[4][4]; + float from_imat[4][4], to_imat[4][4]; + + if (!target_psmd->mesh_final) + return false; + if (!psys->part || psys->part->type != PART_HAIR) + return false; + if (!target_psys->part || target_psys->part->type != PART_HAIR) + return false; + + edit_point = target_edit ? target_edit->points : NULL; + + invert_m4_m4(from_ob_imat, ob->obmat); + invert_m4_m4(to_ob_imat, target_ob->obmat); + invert_m4_m4(from_imat, from_mat); + invert_m4_m4(to_imat, to_mat); + + if (target_psmd->mesh_final->runtime.deformed_only) { + /* we don't want to mess up target_psmd->dm when converting to global coordinates below */ + mesh = target_psmd->mesh_final; + } + else { + mesh = target_psmd->mesh_original; + } + target_mesh = target_psmd->mesh_final; + if (mesh == NULL) { + return false; + } + /* don't modify the original vertices */ + BKE_id_copy_ex(NULL, &mesh->id, (ID **)&mesh, LIB_ID_COPY_LOCALIZE); + + /* BMESH_ONLY, deform dm may not have tessface */ + BKE_mesh_tessface_ensure(mesh); + + numverts = mesh->totvert; + mvert = mesh->mvert; + + /* convert to global coordinates */ + for (i = 0; i < numverts; i++) + mul_m4_v3(to_mat, mvert[i].co); + + if (mesh->totface != 0) { + mface = mesh->mface; + BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2); + } + else if (mesh->totedge != 0) { + medge = mesh->medge; + BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2); + } + else { + BKE_id_free(NULL, mesh); + return false; + } + + for (i = 0, tpa = target_psys->particles, pa = psys->particles; i < target_psys->totpart; + i++, tpa++, pa++) { + float from_co[3]; + BVHTreeNearest nearest; + + if (from_global) + mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co); + else + mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co); + mul_m4_v3(from_mat, from_co); + + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + + BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); + + if (nearest.index == -1) { + if (G.debug & G_DEBUG) + printf("No nearest point found for hair root!"); + continue; + } + + if (mface) { + float v[4][3]; + + mf = &mface[nearest.index]; + + copy_v3_v3(v[0], mvert[mf->v1].co); + copy_v3_v3(v[1], mvert[mf->v2].co); + copy_v3_v3(v[2], mvert[mf->v3].co); + if (mf->v4) { + copy_v3_v3(v[3], mvert[mf->v4].co); + interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co); + } + else + interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co); + tpa->foffset = 0.0f; + + tpa->num = nearest.index; + tpa->num_dmcache = psys_particle_dm_face_lookup(target_mesh, mesh, tpa->num, tpa->fuv, NULL); + } + else { + me = &medge[nearest.index]; + + tpa->fuv[1] = line_point_factor_v3(nearest.co, mvert[me->v1].co, mvert[me->v2].co); + tpa->fuv[0] = 1.0f - tpa->fuv[1]; + tpa->fuv[2] = tpa->fuv[3] = 0.0f; + tpa->foffset = 0.0f; + + tpa->num = nearest.index; + tpa->num_dmcache = -1; + } + + /* translate hair keys */ + { + HairKey *key, *tkey; + float hairmat[4][4], imat[4][4]; + float offset[3]; + + if (to_global) + copy_m4_m4(imat, target_ob->obmat); + else { + /* note: using target_dm here, which is in target_ob object space and has full modifiers */ + psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat); + invert_m4_m4(imat, hairmat); + } + mul_m4_m4m4(imat, imat, to_imat); + + /* offset in world space */ + sub_v3_v3v3(offset, nearest.co, from_co); + + if (edit_point) { + for (k = 0, key = pa->hair, tkey = tpa->hair, ekey = edit_point->keys; k < tpa->totkey; + k++, key++, tkey++, ekey++) { + float co_orig[3]; + + if (from_global) + mul_v3_m4v3(co_orig, from_ob_imat, key->co); + else + mul_v3_m4v3(co_orig, from_ob_imat, key->world_co); + mul_m4_v3(from_mat, co_orig); + + add_v3_v3v3(tkey->co, co_orig, offset); + + mul_m4_v3(imat, tkey->co); + + ekey->flag |= PEK_USE_WCO; + } + + edit_point++; + } + else { + for (k = 0, key = pa->hair, tkey = tpa->hair; k < tpa->totkey; k++, key++, tkey++) { + float co_orig[3]; + + if (from_global) + mul_v3_m4v3(co_orig, from_ob_imat, key->co); + else + mul_v3_m4v3(co_orig, from_ob_imat, key->world_co); + mul_m4_v3(from_mat, co_orig); + + add_v3_v3v3(tkey->co, co_orig, offset); + + mul_m4_v3(imat, tkey->co); + } + } + } + } + + free_bvhtree_from_mesh(&bvhtree); + BKE_id_free(NULL, mesh); + + psys_free_path_cache(target_psys, target_edit); + + PE_update_object(depsgraph, scene, target_ob, 0); + + return true; } -static bool connect_hair( - Depsgraph *depsgraph, Scene *scene, - Object *ob, ParticleSystem *psys) +static bool connect_hair(Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys) { - bool ok; - - if (!psys) - return false; - - ok = remap_hair_emitter( - depsgraph, scene, ob, psys, ob, psys, psys->edit, - ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false); - psys->flag &= ~PSYS_GLOBAL_HAIR; - - return ok; + bool ok; + + if (!psys) + return false; + + ok = remap_hair_emitter(depsgraph, + scene, + ob, + psys, + ob, + psys, + psys->edit, + ob->obmat, + ob->obmat, + psys->flag & PSYS_GLOBAL_HAIR, + false); + psys->flag &= ~PSYS_GLOBAL_HAIR; + + return ok; } static int connect_hair_exec(bContext *C, wmOperator *op) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - Object *ob = ED_object_context(C); - ParticleSystem *psys = NULL; - const bool all = RNA_boolean_get(op->ptr, "all"); - bool any_connected = false; - - if (!ob) - return OPERATOR_CANCELLED; - - if (all) { - for (psys = ob->particlesystem.first; psys; psys = psys->next) { - any_connected |= connect_hair(depsgraph, scene, ob, psys); - } - } - else { - psys = psys_get_current(ob); - any_connected |= connect_hair(depsgraph, scene, ob, psys); - } - - if (!any_connected) { - BKE_report(op->reports, RPT_WARNING, - "No hair connected (can't connect hair if particle system modifier is disabled)"); - return OPERATOR_CANCELLED; - } - - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); - - return OPERATOR_FINISHED; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + Object *ob = ED_object_context(C); + ParticleSystem *psys = NULL; + const bool all = RNA_boolean_get(op->ptr, "all"); + bool any_connected = false; + + if (!ob) + return OPERATOR_CANCELLED; + + if (all) { + for (psys = ob->particlesystem.first; psys; psys = psys->next) { + any_connected |= connect_hair(depsgraph, scene, ob, psys); + } + } + else { + psys = psys_get_current(ob); + any_connected |= connect_hair(depsgraph, scene, ob, psys); + } + + if (!any_connected) { + BKE_report(op->reports, + RPT_WARNING, + "No hair connected (can't connect hair if particle system modifier is disabled)"); + return OPERATOR_CANCELLED; + } + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob); + + return OPERATOR_FINISHED; } void PARTICLE_OT_connect_hair(wmOperatorType *ot) { - ot->name = "Connect Hair"; - ot->description = "Connect hair to the emitter mesh"; - ot->idname = "PARTICLE_OT_connect_hair"; + ot->name = "Connect Hair"; + ot->description = "Connect hair to the emitter mesh"; + ot->idname = "PARTICLE_OT_connect_hair"; - ot->exec = connect_hair_exec; + ot->exec = connect_hair_exec; - /* flags */ - /* No REGISTER, redo does not work due to missing update, see T47750. */ - ot->flag = OPTYPE_UNDO; + /* flags */ + /* No REGISTER, redo does not work due to missing update, see T47750. */ + ot->flag = OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh"); + RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh"); } /************************ particle system copy operator *********************/ typedef enum eCopyParticlesSpace { - PAR_COPY_SPACE_OBJECT = 0, - PAR_COPY_SPACE_WORLD = 1, + PAR_COPY_SPACE_OBJECT = 0, + PAR_COPY_SPACE_WORLD = 1, } eCopyParticlesSpace; -static void copy_particle_edit( - Depsgraph *depsgraph, Scene *scene, - Object *ob, ParticleSystem *psys, ParticleSystem *psys_from) +static void copy_particle_edit(Depsgraph *depsgraph, + Scene *scene, + Object *ob, + ParticleSystem *psys, + ParticleSystem *psys_from) { - PTCacheEdit *edit_from = psys_from->edit, *edit; - ParticleData *pa; - KEY_K; - POINT_P; - - if (!edit_from) - return; - - edit = MEM_dupallocN(edit_from); - edit->psys = psys; - psys->edit = edit; - - edit->pathcache = NULL; - BLI_listbase_clear(&edit->pathcachebufs); - - edit->emitter_field = NULL; - edit->emitter_cosnos = NULL; - - edit->points = MEM_dupallocN(edit_from->points); - pa = psys->particles; - LOOP_POINTS { - HairKey *hkey = pa->hair; - - point->keys = MEM_dupallocN(point->keys); - LOOP_KEYS { - key->co = hkey->co; - key->time = &hkey->time; - key->flag = hkey->editflag; - if (!(psys->flag & PSYS_GLOBAL_HAIR)) { - key->flag |= PEK_USE_WCO; - hkey->editflag |= PEK_USE_WCO; - } - - hkey++; - } - - pa++; - } - update_world_cos(depsgraph, ob, edit); - - UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col); - UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col); - - recalc_lengths(edit); - recalc_emitter_field(depsgraph, ob, psys); - PE_update_object(depsgraph, scene, ob, true); + PTCacheEdit *edit_from = psys_from->edit, *edit; + ParticleData *pa; + KEY_K; + POINT_P; + + if (!edit_from) + return; + + edit = MEM_dupallocN(edit_from); + edit->psys = psys; + psys->edit = edit; + + edit->pathcache = NULL; + BLI_listbase_clear(&edit->pathcachebufs); + + edit->emitter_field = NULL; + edit->emitter_cosnos = NULL; + + edit->points = MEM_dupallocN(edit_from->points); + pa = psys->particles; + LOOP_POINTS + { + HairKey *hkey = pa->hair; + + point->keys = MEM_dupallocN(point->keys); + LOOP_KEYS + { + key->co = hkey->co; + key->time = &hkey->time; + key->flag = hkey->editflag; + if (!(psys->flag & PSYS_GLOBAL_HAIR)) { + key->flag |= PEK_USE_WCO; + hkey->editflag |= PEK_USE_WCO; + } + + hkey++; + } + + pa++; + } + update_world_cos(depsgraph, ob, edit); + + UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col); + UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col); + + recalc_lengths(edit); + recalc_emitter_field(depsgraph, ob, psys); + PE_update_object(depsgraph, scene, ob, true); } static void remove_particle_systems_from_object(Object *ob_to) { - ModifierData *md, *md_next; - - if (ob_to->type != OB_MESH) - return; - if (!ob_to->data || ID_IS_LINKED(ob_to->data)) - return; - - for (md = ob_to->modifiers.first; md; md = md_next) { - md_next = md->next; - - /* remove all particle system modifiers as well, - * these need to sync to the particle system list - */ - if (ELEM(md->type, eModifierType_ParticleSystem, eModifierType_DynamicPaint, eModifierType_Smoke)) { - BLI_remlink(&ob_to->modifiers, md); - modifier_free(md); - } - } - - BKE_object_free_particlesystems(ob_to); + ModifierData *md, *md_next; + + if (ob_to->type != OB_MESH) + return; + if (!ob_to->data || ID_IS_LINKED(ob_to->data)) + return; + + for (md = ob_to->modifiers.first; md; md = md_next) { + md_next = md->next; + + /* remove all particle system modifiers as well, + * these need to sync to the particle system list + */ + if (ELEM(md->type, + eModifierType_ParticleSystem, + eModifierType_DynamicPaint, + eModifierType_Smoke)) { + BLI_remlink(&ob_to->modifiers, md); + modifier_free(md); + } + } + + BKE_object_free_particlesystems(ob_to); } /* single_psys_from is optional, if NULL all psys of ob_from are copied */ @@ -1031,245 +1045,265 @@ static bool copy_particle_systems_to_object(const bContext *C, int space, bool duplicate_settings) { - Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ModifierData *md; - ParticleSystem *psys_start = NULL, *psys, *psys_from; - ParticleSystem **tmp_psys; - Mesh *final_mesh; - CustomData_MeshMasks cdmask = {0}; - int i, totpsys; - - if (ob_to->type != OB_MESH) - return false; - if (!ob_to->data || ID_IS_LINKED(ob_to->data)) - return false; - - /* For remapping we need a valid DM. - * Because the modifiers are appended at the end it's safe to use - * the final DM of the object without particles. - * However, when evaluating the DM all the particle modifiers must be valid, - * i.e. have the psys assigned already. - * To break this hen/egg problem we create all psys separately first (to collect required customdata masks), - * then create the DM, then add them to the object and make the psys modifiers ... - */ - #define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first) - #define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next) - totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem); - - tmp_psys = MEM_mallocN(sizeof(ParticleSystem *) * totpsys, "temporary particle system array"); - - for (psys_from = PSYS_FROM_FIRST, i = 0; - psys_from; - psys_from = PSYS_FROM_NEXT(psys_from), ++i) - { - psys = BKE_object_copy_particlesystem(psys_from, 0); - tmp_psys[i] = psys; - - if (psys_start == NULL) - psys_start = psys; - - psys_emitter_customdata_mask(psys, &cdmask); - } - /* to iterate source and target psys in sync, - * we need to know where the newly added psys start - */ - psys_start = totpsys > 0 ? tmp_psys[0] : NULL; - - /* Get the evaluated mesh (psys and their modifiers have not been appended yet) */ - final_mesh = mesh_get_eval_final(depsgraph, scene, ob_to, &cdmask); - - /* now append psys to the object and make modifiers */ - for (i = 0, psys_from = PSYS_FROM_FIRST; - i < totpsys; - ++i, psys_from = PSYS_FROM_NEXT(psys_from)) - { - ParticleSystemModifierData *psmd; - - psys = tmp_psys[i]; - - /* append to the object */ - BLI_addtail(&ob_to->particlesystem, psys); - - /* add a particle system modifier for each system */ - md = modifier_new(eModifierType_ParticleSystem); - psmd = (ParticleSystemModifierData *)md; - /* push on top of the stack, no use trying to reproduce old stack order */ - BLI_addtail(&ob_to->modifiers, md); - - BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i); - modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd); - - psmd->psys = psys; - BKE_id_copy_ex(NULL, &final_mesh->id, (ID **)&psmd->mesh_final, LIB_ID_COPY_LOCALIZE); - - BKE_mesh_calc_normals(psmd->mesh_final); - BKE_mesh_tessface_ensure(psmd->mesh_final); - - if (psys_from->edit) { - copy_particle_edit(depsgraph, scene, ob_to, psys, psys_from); - } - - if (duplicate_settings) { - id_us_min(&psys->part->id); - psys->part = BKE_particlesettings_copy(bmain, psys->part); - } - } - MEM_freeN(tmp_psys); - - /* note: do this after creating DM copies for all the particle system modifiers, - * the remapping otherwise makes final_dm invalid! - */ - for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0; - psys; - psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i) - { - float(*from_mat)[4], (*to_mat)[4]; - - switch (space) { - case PAR_COPY_SPACE_OBJECT: - from_mat = I; - to_mat = I; - break; - case PAR_COPY_SPACE_WORLD: - from_mat = ob_from->obmat; - to_mat = ob_to->obmat; - break; - default: - /* should not happen */ - from_mat = to_mat = NULL; - BLI_assert(false); - break; - } - if (ob_from != ob_to) { - remap_hair_emitter( - depsgraph, scene, ob_from, psys_from, ob_to, psys, psys->edit, - from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR); - } - - /* tag for recalc */ -// psys->recalc |= ID_RECALC_PSYS_RESET; - } - - #undef PSYS_FROM_FIRST - #undef PSYS_FROM_NEXT - - DEG_id_tag_update(&ob_to->id, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to); - return true; + Main *bmain = CTX_data_main(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ModifierData *md; + ParticleSystem *psys_start = NULL, *psys, *psys_from; + ParticleSystem **tmp_psys; + Mesh *final_mesh; + CustomData_MeshMasks cdmask = {0}; + int i, totpsys; + + if (ob_to->type != OB_MESH) + return false; + if (!ob_to->data || ID_IS_LINKED(ob_to->data)) + return false; + +/* For remapping we need a valid DM. + * Because the modifiers are appended at the end it's safe to use + * the final DM of the object without particles. + * However, when evaluating the DM all the particle modifiers must be valid, + * i.e. have the psys assigned already. + * To break this hen/egg problem we create all psys separately first (to collect required customdata masks), + * then create the DM, then add them to the object and make the psys modifiers ... + */ +#define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first) +#define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next) + totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem); + + tmp_psys = MEM_mallocN(sizeof(ParticleSystem *) * totpsys, "temporary particle system array"); + + for (psys_from = PSYS_FROM_FIRST, i = 0; psys_from; psys_from = PSYS_FROM_NEXT(psys_from), ++i) { + psys = BKE_object_copy_particlesystem(psys_from, 0); + tmp_psys[i] = psys; + + if (psys_start == NULL) + psys_start = psys; + + psys_emitter_customdata_mask(psys, &cdmask); + } + /* to iterate source and target psys in sync, + * we need to know where the newly added psys start + */ + psys_start = totpsys > 0 ? tmp_psys[0] : NULL; + + /* Get the evaluated mesh (psys and their modifiers have not been appended yet) */ + final_mesh = mesh_get_eval_final(depsgraph, scene, ob_to, &cdmask); + + /* now append psys to the object and make modifiers */ + for (i = 0, psys_from = PSYS_FROM_FIRST; i < totpsys; + ++i, psys_from = PSYS_FROM_NEXT(psys_from)) { + ParticleSystemModifierData *psmd; + + psys = tmp_psys[i]; + + /* append to the object */ + BLI_addtail(&ob_to->particlesystem, psys); + + /* add a particle system modifier for each system */ + md = modifier_new(eModifierType_ParticleSystem); + psmd = (ParticleSystemModifierData *)md; + /* push on top of the stack, no use trying to reproduce old stack order */ + BLI_addtail(&ob_to->modifiers, md); + + BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i); + modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd); + + psmd->psys = psys; + BKE_id_copy_ex(NULL, &final_mesh->id, (ID **)&psmd->mesh_final, LIB_ID_COPY_LOCALIZE); + + BKE_mesh_calc_normals(psmd->mesh_final); + BKE_mesh_tessface_ensure(psmd->mesh_final); + + if (psys_from->edit) { + copy_particle_edit(depsgraph, scene, ob_to, psys, psys_from); + } + + if (duplicate_settings) { + id_us_min(&psys->part->id); + psys->part = BKE_particlesettings_copy(bmain, psys->part); + } + } + MEM_freeN(tmp_psys); + + /* note: do this after creating DM copies for all the particle system modifiers, + * the remapping otherwise makes final_dm invalid! + */ + for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0; psys; + psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i) { + float(*from_mat)[4], (*to_mat)[4]; + + switch (space) { + case PAR_COPY_SPACE_OBJECT: + from_mat = I; + to_mat = I; + break; + case PAR_COPY_SPACE_WORLD: + from_mat = ob_from->obmat; + to_mat = ob_to->obmat; + break; + default: + /* should not happen */ + from_mat = to_mat = NULL; + BLI_assert(false); + break; + } + if (ob_from != ob_to) { + remap_hair_emitter(depsgraph, + scene, + ob_from, + psys_from, + ob_to, + psys, + psys->edit, + from_mat, + to_mat, + psys_from->flag & PSYS_GLOBAL_HAIR, + psys->flag & PSYS_GLOBAL_HAIR); + } + + /* tag for recalc */ + // psys->recalc |= ID_RECALC_PSYS_RESET; + } + +#undef PSYS_FROM_FIRST +#undef PSYS_FROM_NEXT + + DEG_id_tag_update(&ob_to->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to); + return true; } static bool copy_particle_systems_poll(bContext *C) { - Object *ob; - if (!ED_operator_object_active_editable(C)) - return false; + Object *ob; + if (!ED_operator_object_active_editable(C)) + return false; - ob = ED_object_active_context(C); - if (BLI_listbase_is_empty(&ob->particlesystem)) - return false; + ob = ED_object_active_context(C); + if (BLI_listbase_is_empty(&ob->particlesystem)) + return false; - return true; + return true; } static int copy_particle_systems_exec(bContext *C, wmOperator *op) { - const int space = RNA_enum_get(op->ptr, "space"); - const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles"); - const bool use_active = RNA_boolean_get(op->ptr, "use_active"); - Scene *scene = CTX_data_scene(C); - Object *ob_from = ED_object_active_context(C); - ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL; - - int changed_tot = 0; - int fail = 0; - - CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects) - { - if (ob_from != ob_to) { - bool changed = false; - if (remove_target_particles) { - remove_particle_systems_from_object(ob_to); - changed = true; - } - if (copy_particle_systems_to_object(C, scene, ob_from, psys_from, ob_to, space, false)) - changed = true; - else - fail++; - - if (changed) - changed_tot++; - } - } - CTX_DATA_END; - - if ((changed_tot == 0 && fail == 0) || fail) { - BKE_reportf(op->reports, RPT_ERROR, - "Copy particle systems to selected: %d done, %d failed", - changed_tot, fail); - } - - return OPERATOR_FINISHED; + const int space = RNA_enum_get(op->ptr, "space"); + const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles"); + const bool use_active = RNA_boolean_get(op->ptr, "use_active"); + Scene *scene = CTX_data_scene(C); + Object *ob_from = ED_object_active_context(C); + ParticleSystem *psys_from = + use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : + NULL; + + int changed_tot = 0; + int fail = 0; + + CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects) { + if (ob_from != ob_to) { + bool changed = false; + if (remove_target_particles) { + remove_particle_systems_from_object(ob_to); + changed = true; + } + if (copy_particle_systems_to_object(C, scene, ob_from, psys_from, ob_to, space, false)) + changed = true; + else + fail++; + + if (changed) + changed_tot++; + } + } + CTX_DATA_END; + + if ((changed_tot == 0 && fail == 0) || fail) { + BKE_reportf(op->reports, + RPT_ERROR, + "Copy particle systems to selected: %d done, %d failed", + changed_tot, + fail); + } + + return OPERATOR_FINISHED; } void PARTICLE_OT_copy_particle_systems(wmOperatorType *ot) { - static const EnumPropertyItem space_items[] = { - {PAR_COPY_SPACE_OBJECT, "OBJECT", 0, "Object", "Copy inside each object's local space"}, - {PAR_COPY_SPACE_WORLD, "WORLD", 0, "World", "Copy in world space"}, - {0, NULL, 0, NULL, NULL}, - }; - - ot->name = "Copy Particle Systems"; - ot->description = "Copy particle systems from the active object to selected objects"; - ot->idname = "PARTICLE_OT_copy_particle_systems"; - - ot->poll = copy_particle_systems_poll; - ot->exec = copy_particle_systems_exec; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_enum(ot->srna, "space", space_items, PAR_COPY_SPACE_OBJECT, "Space", "Space transform for copying from one object to another"); - RNA_def_boolean(ot->srna, "remove_target_particles", true, "Remove Target Particles", "Remove particle systems on the target objects"); - RNA_def_boolean(ot->srna, "use_active", false, "Use Active", "Use the active particle system from the context"); + static const EnumPropertyItem space_items[] = { + {PAR_COPY_SPACE_OBJECT, "OBJECT", 0, "Object", "Copy inside each object's local space"}, + {PAR_COPY_SPACE_WORLD, "WORLD", 0, "World", "Copy in world space"}, + {0, NULL, 0, NULL, NULL}, + }; + + ot->name = "Copy Particle Systems"; + ot->description = "Copy particle systems from the active object to selected objects"; + ot->idname = "PARTICLE_OT_copy_particle_systems"; + + ot->poll = copy_particle_systems_poll; + ot->exec = copy_particle_systems_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, + "space", + space_items, + PAR_COPY_SPACE_OBJECT, + "Space", + "Space transform for copying from one object to another"); + RNA_def_boolean(ot->srna, + "remove_target_particles", + true, + "Remove Target Particles", + "Remove particle systems on the target objects"); + RNA_def_boolean(ot->srna, + "use_active", + false, + "Use Active", + "Use the active particle system from the context"); } static bool duplicate_particle_systems_poll(bContext *C) { - if (!ED_operator_object_active_editable(C)) { - return false; - } - Object *ob = ED_object_active_context(C); - if (BLI_listbase_is_empty(&ob->particlesystem)) { - return false; - } - return true; + if (!ED_operator_object_active_editable(C)) { + return false; + } + Object *ob = ED_object_active_context(C); + if (BLI_listbase_is_empty(&ob->particlesystem)) { + return false; + } + return true; } static int duplicate_particle_systems_exec(bContext *C, wmOperator *op) { - const bool duplicate_settings = RNA_boolean_get(op->ptr, "use_duplicate_settings"); - Scene *scene = CTX_data_scene(C); - Object *ob = ED_object_active_context(C); - ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data; - copy_particle_systems_to_object(C, scene, ob, psys, ob, - PAR_COPY_SPACE_OBJECT, duplicate_settings); - return OPERATOR_FINISHED; + const bool duplicate_settings = RNA_boolean_get(op->ptr, "use_duplicate_settings"); + Scene *scene = CTX_data_scene(C); + Object *ob = ED_object_active_context(C); + ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data; + copy_particle_systems_to_object( + C, scene, ob, psys, ob, PAR_COPY_SPACE_OBJECT, duplicate_settings); + return OPERATOR_FINISHED; } void PARTICLE_OT_duplicate_particle_system(wmOperatorType *ot) { - ot->name = "Duplicate Particle System"; - ot->description = "Duplicate particle system within the active object"; - ot->idname = "PARTICLE_OT_duplicate_particle_system"; + ot->name = "Duplicate Particle System"; + ot->description = "Duplicate particle system within the active object"; + ot->idname = "PARTICLE_OT_duplicate_particle_system"; - ot->poll = duplicate_particle_systems_poll; - ot->exec = duplicate_particle_systems_exec; + ot->poll = duplicate_particle_systems_poll; + ot->exec = duplicate_particle_systems_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "use_duplicate_settings", false, "Duplicate Settings", - "Duplicate settings as well, so the new particle system uses its own settings"); + RNA_def_boolean(ot->srna, + "use_duplicate_settings", + false, + "Duplicate Settings", + "Duplicate settings as well, so the new particle system uses its own settings"); } |