diff options
Diffstat (limited to 'source/blender/editors/physics/particle_edit.c')
-rw-r--r-- | source/blender/editors/physics/particle_edit.c | 150 |
1 files changed, 146 insertions, 4 deletions
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index f25679986a5..cf02d2773c0 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -37,6 +37,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_key_types.h" #include "DNA_scene_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -56,6 +57,7 @@ #include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" +#include "BKE_key.h" #include "BKE_object.h" #include "BKE_mesh.h" #include "BKE_modifier.h" @@ -1201,6 +1203,9 @@ void update_world_cos(Object *ob, PTCacheEdit *edit) mul_m4_v3(hairmat, key->world_co); } } + + /* apply hair changes to the active shape key */ + PE_shapekey_apply(ob, psys); } static void update_velocities(PTCacheEdit *edit) { @@ -3701,6 +3706,7 @@ typedef struct BrushEdit { int first; int lastmouse[2]; float zfac; + bool done; /* optional cached view settings to avoid setting on every mousemove */ PEData data; @@ -3726,6 +3732,7 @@ static int brush_edit_init(bContext *C, wmOperator *op) bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit"); bedit->first= 1; + bedit->done = false; op->customdata= bedit; bedit->scene= scene; @@ -3881,13 +3888,16 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) } case PE_BRUSH_ADD: { - if (edit->psys && edit->psys->part->from==PART_FROM_FACE) { + bool done = (brush->flag & PE_BRUSH_DATA_ADD_SINGLE) && bedit->done; + if (!done && edit->psys && edit->psys->part->from==PART_FROM_FACE) { data.mval= mval; added= brush_add(&data, brush->count); if (pset->flag & PE_KEEP_LENGTHS) recalc_lengths(edit); + + bedit->done = true; } else added= 0; @@ -4091,10 +4101,11 @@ static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key) BVHTreeFromMesh *shape_bvh = &data->shape_bvh; const float dir[3] = {1.0f, 0.0f, 0.0f}; PointInsideBVH userdata; - userdata.bvhdata = data->shape_bvh; userdata.num_hits = 0; + userdata.bvhdata = data->shape_bvh; + userdata.num_hits = 0; BLI_bvhtree_ray_cast_all(shape_bvh->tree, key->co, dir, 0.0f, point_inside_bvh_cb, &userdata); /* for any point inside a watertight mesh the number of hits is uneven */ @@ -4560,6 +4571,44 @@ int PE_minmax(Scene *scene, float min[3], float max[3]) /************************ particle edit toggle operator ************************/ +bool PE_shapekey_load(Object *ob, ParticleSystem *psys) +{ + const int mode_flag = OB_MODE_PARTICLE_EDIT; + const bool is_mode_set = (ob->mode & mode_flag) != 0; + + if (!is_mode_set) + return false; + + if (psys->edit) { + /* set the active shape key */ + KeyBlock *actkb = BKE_keyblock_from_particles(psys); + + if (actkb) + BKE_keyblock_convert_to_hair_keys(actkb, ob, psys); + } + + return true; +} + +bool PE_shapekey_apply(struct Object *ob, struct ParticleSystem *psys) +{ + const int mode_flag = OB_MODE_PARTICLE_EDIT; + const bool is_mode_set = (ob->mode & mode_flag) != 0; + + if (!is_mode_set) + return false; + + if (psys->edit) { + /* define the active shape key */ + KeyBlock *actkb = BKE_keyblock_from_particles(psys); + + if (actkb) + BKE_keyblock_convert_from_hair_keys(ob, psys, actkb); + } + + return true; +} + /* initialize needed data for bake edit */ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) { @@ -4702,11 +4751,18 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op) PTCacheEdit *edit; ob->mode |= mode_flag; edit= PE_create_current(scene, ob); - + /* mesh may have changed since last entering editmode. * note, this may have run before if the edit data was just created, so could avoid this and speed up a little */ - if (edit && edit->psys) + if (edit && edit->psys) { + /* set the active shape key */ + KeyBlock *actkb = BKE_keyblock_from_particles(edit->psys); + + if (actkb) + BKE_keyblock_convert_to_hair_keys(actkb, ob, edit->psys); + recalc_emitter_field(ob, edit->psys); + } toggle_particle_cursor(C, 1); WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL); @@ -4793,3 +4849,89 @@ void PARTICLE_OT_edited_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; } +/************************ Propagate Shape Key *************************/ + +static int PE_count_keys(PTCacheEdit *edit) +{ + int totkey = 0, p; + for (p = 0; p < edit->totpoint; ++p) { + totkey += edit->points[p].totkey; + } + return totkey; +} + +static void shape_propagate(PTCacheEdit *edit, int totkey, KeyBlock *kb, wmOperator *UNUSED(op)) +{ + PTCacheEditPoint *point; + float *fp; + int i, k; + + if (kb->totelem != totkey) + return; + + fp = kb->data; + point = edit->points; + for (i = 0; i < edit->totpoint; ++i, ++point) { + PTCacheEditKey *key = point->keys; + const bool use_point = !(point->flag & PEP_HIDE); + + for (k = 0; k < point->totkey; ++k, ++key) { + const bool use_key = (key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE); + + if (use_point && use_key) { + copy_v3_v3(fp, key->co); + + point->flag |= PEP_EDIT_RECALC; + } + + fp += 3; + } + } +} + +static int particle_shape_propagate_to_all_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ParticleEditSettings *pset = PE_settings(scene); + Object *ob = ED_object_context(C); + ParticleSystem *psys = psys_get_current(ob); + PTCacheEdit *edit = psys->edit; + Key *key = psys->key; + KeyBlock *kb; + const int totkey = PE_count_keys(edit); + + if (!key) + return OPERATOR_CANCELLED; + + /* we might need world space coordinates, update to be sure */ + update_world_cos(ob, edit); + + for (kb = key->block.first; kb; kb = kb->next) + shape_propagate(edit, totkey, kb, op); + + update_world_cos(ob, edit); + PE_update_object(scene, ob, 1); + + if (!(pset->flag & PE_KEEP_LENGTHS)) + recalc_lengths(edit); + + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); + + return OPERATOR_FINISHED; +} + + +void PARTICLE_OT_shape_propagate_to_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Shape Propagate"; + ot->description = "Apply selected vertex locations to all other shape keys"; + ot->idname = "PARTICLE_OT_shape_propagate_to_all"; + + /* api callbacks */ + ot->exec = particle_shape_propagate_to_all_exec; + ot->poll = PE_hair_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} |