Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/physics/particle_object.c')
-rw-r--r--source/blender/editors/physics/particle_object.c1916
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");
}