diff options
Diffstat (limited to 'source/blender/editors/transform/transform_conversions.c')
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 203 |
1 files changed, 202 insertions, 1 deletions
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f5b5faa4ad2..ce3d903b8f6 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -50,7 +50,6 @@ #include "DNA_gpencil_types.h" #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" -#include "DNA_object_types.h" #include "MEM_guardedalloc.h" @@ -82,7 +81,9 @@ #include "BKE_nla.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_particle.h" #include "BKE_paint.h" +#include "BKE_pointcache.h" #include "BKE_report.h" #include "BKE_rigidbody.h" #include "BKE_scene.h" @@ -95,6 +96,7 @@ #include "ED_anim_api.h" #include "ED_armature.h" +#include "ED_particle.h" #include "ED_image.h" #include "ED_keyframing.h" #include "ED_keyframes_edit.h" @@ -1801,6 +1803,174 @@ static void createTransLatticeVerts(TransInfo *t) } } +/* ******************* particle edit **************** */ +static void createTransParticleVerts(bContext *C, TransInfo *t) +{ + TransData *td = NULL; + TransDataExtension *tx; + Base *base = CTX_data_active_base(C); + Object *ob = CTX_data_active_object(C); + ParticleEditSettings *pset = PE_settings(t->scene); + PTCacheEdit *edit = PE_get_current(t->scene, ob); + ParticleSystem *psys = NULL; + ParticleSystemModifierData *psmd = NULL; + PTCacheEditPoint *point; + PTCacheEditKey *key; + float mat[4][4]; + int i, k, transformparticle; + int count = 0, hasselected = 0; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; + + if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return; + + psys = edit->psys; + + if (psys) + psmd = psys_get_modifier(ob, psys); + + base->flag |= BA_HAS_RECALC_DATA; + + for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) { + point->flag &= ~PEP_TRANSFORM; + transformparticle = 0; + + if ((point->flag & PEP_HIDE) == 0) { + for (k = 0, key = point->keys; k < point->totkey; k++, key++) { + if ((key->flag & PEK_HIDE) == 0) { + if (key->flag & PEK_SELECT) { + hasselected = 1; + transformparticle = 1; + } + else if (is_prop_edit) + transformparticle = 1; + } + } + } + + if (transformparticle) { + count += point->totkey; + point->flag |= PEP_TRANSFORM; + } + } + + /* note: in prop mode we need at least 1 selected */ + if (hasselected == 0) return; + + t->total = count; + td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)"); + + if (t->mode == TFM_BAKE_TIME) + tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension"); + else + tx = t->ext = NULL; + + unit_m4(mat); + + invert_m4_m4(ob->imat, ob->obmat); + + for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) { + TransData *head, *tail; + head = tail = td; + + if (!(point->flag & PEP_TRANSFORM)) continue; + + if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) + psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat); + + for (k = 0, key = point->keys; k < point->totkey; k++, key++) { + if (key->flag & PEK_USE_WCO) { + copy_v3_v3(key->world_co, key->co); + mul_m4_v3(mat, key->world_co); + td->loc = key->world_co; + } + else + td->loc = key->co; + + copy_v3_v3(td->iloc, td->loc); + copy_v3_v3(td->center, td->loc); + + if (key->flag & PEK_SELECT) + td->flag |= TD_SELECTED; + else if (!is_prop_edit) + td->flag |= TD_SKIP; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + /* don't allow moving roots */ + if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR))) + td->protectflag |= OB_LOCK_LOC; + + td->ob = ob; + td->ext = tx; + if (t->mode == TFM_BAKE_TIME) { + td->val = key->time; + td->ival = *(key->time); + /* abuse size and quat for min/max values */ + td->flag |= TD_NO_EXT; + if (k == 0) tx->size = NULL; + else tx->size = (key - 1)->time; + + if (k == point->totkey - 1) tx->quat = NULL; + else tx->quat = (key + 1)->time; + } + + td++; + if (tx) + tx++; + tail++; + } + if (is_prop_edit && head != tail) + calc_distanceCurveVerts(head, tail - 1); + } +} + +void flushTransParticles(TransInfo *t) +{ + Scene *scene = t->scene; + Object *ob = OBACT; + PTCacheEdit *edit = PE_get_current(scene, ob); + ParticleSystem *psys = edit->psys; + ParticleSystemModifierData *psmd = NULL; + PTCacheEditPoint *point; + PTCacheEditKey *key; + TransData *td; + float mat[4][4], imat[4][4], co[3]; + int i, k; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; + + if (psys) + psmd = psys_get_modifier(ob, psys); + + /* we do transform in world space, so flush world space position + * back to particle local space (only for hair particles) */ + td = t->data; + for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) { + if (!(point->flag & PEP_TRANSFORM)) continue; + + if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { + psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat); + invert_m4_m4(imat, mat); + + for (k = 0, key = point->keys; k < point->totkey; k++, key++) { + copy_v3_v3(co, key->world_co); + mul_m4_v3(imat, co); + + + /* optimization for proportional edit */ + if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) { + copy_v3_v3(key->co, co); + point->flag |= PEP_EDIT_RECALC; + } + } + } + else + point->flag |= PEP_EDIT_RECALC; + } + + PE_update_object(scene, OBACT, 1); +} + /* ********************* mesh ****************** */ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, @@ -6145,6 +6315,13 @@ void special_aftertrans_update(bContext *C, TransInfo *t) else if (t->options & CTX_PAINT_CURVE) { /* pass */ } + else if ((t->scene->basact) && + (ob = t->scene->basact->object) && + (ob->mode & OB_MODE_PARTICLE_EDIT) && + PE_get_current(t->scene, ob)) + { + /* do nothing */ + } else { /* Objects */ int i; @@ -6152,6 +6329,8 @@ void special_aftertrans_update(bContext *C, TransInfo *t) for (i = 0; i < t->total; i++) { TransData *td = t->data + i; + ListBase pidlist; + PTCacheID *pid; ob = td->ob; if (td->flag & TD_NOACTION) @@ -6160,6 +6339,18 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (td->flag & TD_SKIP) continue; + /* flag object caches as outdated */ + BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR); + for (pid = pidlist.first; pid; pid = pid->next) { + if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ + pid->cache->flag |= PTCACHE_OUTDATED; + } + BLI_freelistN(&pidlist); + + /* pointcache refresh */ + if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED)) + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + /* Needed for proper updating of "quick cached" dynamics. */ /* Creates troubles for moving animated objects without */ /* autokey though, probably needed is an anim sys override? */ @@ -7879,6 +8070,16 @@ void createTransData(bContext *C, TransInfo *t) } } + else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) { + createTransParticleVerts(C, t); + t->flag |= T_POINTS; + + if (t->data && t->flag & T_PROP_EDIT) { + sort_trans_data(t); // makes selected become first in array + set_prop_dist(t, 1); + sort_trans_data_dist(t); + } + } else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) { if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) { t->flag |= T_POINTS | T_2D_EDIT; |