doxygen: blender/editors tagged.
[blender-staging.git] / source / blender / editors / physics / particle_edit.c
index 1fd9e91095f805c9868bbf553bfbe24b97b125a7..8a304765a7a10702d7931bf6caca49a2f3c0cc8d 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/physics/particle_edit.c
+ *  \ingroup edphys
+ */
+
+
 #include <stdlib.h>
 #include <math.h>
 #include <string.h>
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
 
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
+#include "BLI_kdtree.h"
+#include "BLI_rand.h"
+#include "BLI_utildefines.h"
+
 #include "BKE_DerivedMesh.h"
 #include "BKE_depsgraph.h"
 
 #include "BKE_particle.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
-#include "BKE_utildefines.h"
-#include "BKE_pointcache.h"
-
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
-#include "BLI_kdtree.h"
-#include "BLI_rand.h"
 
+#include "BKE_pointcache.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "ED_physics.h"
 #include "ED_mesh.h"
 #include "ED_particle.h"
 #include "ED_view3d.h"
@@ -484,13 +490,10 @@ static int key_inside_test(PEData *data, float co[3])
 static int point_is_selected(PTCacheEditPoint *point)
 {
        KEY_K;
-       int sel;
 
        if(point->flag & PEP_HIDE)
                return 0;
 
-       sel= 0;
-
        LOOP_SELECTED_KEYS {
                return 1;
        }
@@ -593,7 +596,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
        ParticleSystemModifierData *psmd = NULL;
        ParticleEditSettings *pset= PE_settings(data->scene);
        POINT_P; KEY_K;
-       float mat[4][4], imat[4][4];
+       float mat[4][4]= MAT4_UNITY, imat[4][4]= MAT4_UNITY;
 
        if(edit->psys)
                psmd= psys_get_modifier(data->ob, edit->psys);
@@ -602,9 +605,6 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
        if(pset->selectmode==SCE_SELECT_PATH)
                selected= 0;
 
-       unit_m4(imat);
-       unit_m4(mat);
-
        LOOP_VISIBLE_POINTS {
                if(pset->selectmode==SCE_SELECT_END) {
                        /* only do end keys */
@@ -776,6 +776,9 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
        if(!mpa) {
                if(!edit->mirror_cache)
                        PE_update_mirror_cache(ob, psys);
+               
+               if(!edit->mirror_cache)
+                       return; /* something went wrong! */
 
                mi= edit->mirror_cache[i];
                if(mi == -1)
@@ -850,6 +853,9 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
        if(!edit->mirror_cache)
                PE_update_mirror_cache(ob, psys);
 
+       if(!edit->mirror_cache)
+               return; /* something went wrong */
+
        /* we delay settings the PARS_EDIT_RECALC for mirrored particles
         * to avoid doing mirror twice */
        LOOP_POINTS {
@@ -939,7 +945,7 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
        }
 }
 /* force set distances between neighbouring keys */
-void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
+static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
 {
        
        ParticleEditSettings *pset=PE_settings(scene);
@@ -1039,10 +1045,8 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
 {
        DerivedMesh *dm=psys_get_modifier(ob,psys)->dm;
        PTCacheEdit *edit= psys->edit;
-       MFace *mface;
-       MVert *mvert;
        float *vec, *nor;
-       int i, totface, totvert;
+       int i, totface /*, totvert*/;
 
        if(!dm)
                return;
@@ -1053,7 +1057,7 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
        BLI_kdtree_free(edit->emitter_field);
 
        totface=dm->getNumFaces(dm);
-       totvert=dm->getNumVerts(dm);
+       /*totvert=dm->getNumVerts(dm);*/ /*UNSUED*/
 
        edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float),"emitter cosnos");
 
@@ -1062,9 +1066,9 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
        vec=edit->emitter_cosnos;
        nor=vec+3;
 
-       mvert=dm->getVertDataArray(dm,CD_MVERT);
        for(i=0; i<totface; i++, vec+=6, nor+=6) {
-               mface=dm->getFaceData(dm,i,CD_MFACE);
+               MFace *mface=dm->getFaceData(dm,i,CD_MFACE);
+               MVert *mvert;
 
                mvert=dm->getVertData(dm,mface->v1,CD_MVERT);
                VECCOPY(vec,mvert->co);
@@ -1605,7 +1609,7 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short extend, s
        ParticleSystem *psys = edit->psys;
        ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
        POINT_P; KEY_K;
-       float co[3], mat[4][4];
+       float co[3], mat[4][4]= MAT4_UNITY;
        short vertco[2];
 
        PEData data;
@@ -1619,8 +1623,6 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short extend, s
        /* only for depths */
        PE_set_view3d_data(C, &data);
 
-       unit_m4(mat);
-
        LOOP_VISIBLE_POINTS {
                if(edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
                        psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + p, mat);
@@ -2067,12 +2069,11 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
        POINT_P;
        PTCacheEditPoint *npoint=0, *new_points=0;
        ParticleSystemModifierData *psmd;
-       int i, totpart, new_totpart= psys->totpart, removed= 0;
+       int i, new_totpart= psys->totpart, removed= 0;
 
        if(mirror) {
                /* mirror tags */
                psmd= psys_get_modifier(ob, psys);
-               totpart= psys->totpart;
 
                LOOP_TAGGED_POINTS {
                        PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
@@ -2088,6 +2089,15 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
                if(new_totpart) {
                        npa= new_pars= MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array");
                        npoint= new_points= MEM_callocN(new_totpart * sizeof(PTCacheEditPoint), "PTCacheEditKey array");
+
+                       if(ELEM(NULL, new_pars, new_points)) {
+                                /* allocation error! */
+                               if(new_pars)
+                                       MEM_freeN(new_pars);
+                               if(new_points)
+                                       MEM_freeN(new_points);
+                               return 0;
+                       }
                }
 
                pa= psys->particles;
@@ -2398,7 +2408,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
 
        BKE_reportf(op->reports, RPT_INFO, "Remove %d double particles.", totremoved);
 
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
 
        return OPERATOR_FINISHED;
@@ -2448,7 +2458,7 @@ static int weight_set_exec(bContext *C, wmOperator *op)
                }
        }
 
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
 
        return OPERATOR_FINISHED;
@@ -2625,7 +2635,7 @@ static int delete_exec(bContext *C, wmOperator *op)
                recalc_lengths(data.edit);
        }
 
-       DAG_id_flush_update(&data.ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&data.ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -2786,7 +2796,7 @@ static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
 
        update_world_cos(ob, edit);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
        return OPERATOR_FINISHED;
 }
@@ -3250,18 +3260,16 @@ static int brush_add(PEData *data, short number)
 
                        if(tree) {
                                ParticleData *ppa;
-                               HairKey *hkey;
-                               ParticleKey key[3];
+                               HairKey *thkey;
+                               ParticleKey key3[3];
                                KDTreeNearest ptn[3];
                                int w, maxw;
-                               float maxd, mind, dd, totw=0.0, weight[3];
+                               float maxd, totw=0.0, weight[3];
 
                                psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,0,0);
                                maxw= BLI_kdtree_find_n_nearest(tree,3,co1,NULL,ptn);
 
                                maxd= ptn[maxw-1].dist;
-                               mind= ptn[0].dist;
-                               dd= maxd - mind;
                                
                                for(w=0; w<maxw; w++) {
                                        weight[w]= (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd));
@@ -3277,36 +3285,36 @@ static int brush_add(PEData *data, short number)
                                ppa= psys->particles+ptn[0].index;
 
                                for(k=0; k<pset->totaddkey; k++) {
-                                       hkey= (HairKey*)pa->hair + k;
-                                       hkey->time= pa->time + k * framestep;
+                                       thkey= (HairKey*)pa->hair + k;
+                                       thkey->time= pa->time + k * framestep;
 
-                                       key[0].time= hkey->time/ 100.0f;
-                                       psys_get_particle_on_path(&sim, ptn[0].index, key, 0);
-                                       mul_v3_fl(key[0].co, weight[0]);
+                                       key3[0].time= thkey->time/ 100.0f;
+                                       psys_get_particle_on_path(&sim, ptn[0].index, key3, 0);
+                                       mul_v3_fl(key3[0].co, weight[0]);
                                        
                                        /* TODO: interpolatint the weight would be nicer */
-                                       hkey->weight= (ppa->hair+MIN2(k, ppa->totkey-1))->weight;
+                                       thkey->weight= (ppa->hair+MIN2(k, ppa->totkey-1))->weight;
                                        
                                        if(maxw>1) {
-                                               key[1].time= key[0].time;
-                                               psys_get_particle_on_path(&sim, ptn[1].index, key + 1, 0);
-                                               mul_v3_fl(key[1].co, weight[1]);
-                                               VECADD(key[0].co, key[0].co, key[1].co);
+                                               key3[1].time= key3[0].time;
+                                               psys_get_particle_on_path(&sim, ptn[1].index, &key3[1], 0);
+                                               mul_v3_fl(key3[1].co, weight[1]);
+                                               VECADD(key3[0].co, key3[0].co, key3[1].co);
 
                                                if(maxw>2) {                                            
-                                                       key[2].time= key[0].time;
-                                                       psys_get_particle_on_path(&sim, ptn[2].index, key + 2, 0);
-                                                       mul_v3_fl(key[2].co, weight[2]);
-                                                       VECADD(key[0].co, key[0].co, key[2].co);
+                                                       key3[2].time= key3[0].time;
+                                                       psys_get_particle_on_path(&sim, ptn[2].index, &key3[2], 0);
+                                                       mul_v3_fl(key3[2].co, weight[2]);
+                                                       VECADD(key3[0].co, key3[0].co, key3[2].co);
                                                }
                                        }
 
                                        if(k==0)
-                                               VECSUB(co1, pa->state.co, key[0].co);
+                                               VECSUB(co1, pa->state.co, key3[0].co);
 
-                                       VECADD(hkey->co, key[0].co, co1);
+                                       VECADD(thkey->co, key3[0].co, co1);
 
-                                       hkey->time= key[0].time;
+                                       thkey->time= key3[0].time;
                                }
                        }
                        else {
@@ -3565,7 +3573,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
 
                        update_world_cos(ob,edit);
                        psys_free_path_cache(NULL, edit);
-                       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
                }
                else
                        PE_update_object(scene, ob, 1);
@@ -3724,8 +3732,6 @@ static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
                for(; pm; pm=pm->next) {
                        for(i=0; i<BPHYS_TOT_DATA; i++)
                                pm->data[i] = MEM_dupallocN(pm->data[i]);
-
-                       pm->index_array = MEM_dupallocN(pm->index_array);
                }
        }
 
@@ -3800,20 +3806,18 @@ static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
                        for(i=0; i<BPHYS_TOT_DATA; i++)
                                pm->data[i] = MEM_dupallocN(pm->data[i]);
 
-                       pm->index_array = MEM_dupallocN(pm->index_array);
-
-                       BKE_ptcache_mem_init_pointers(pm);
+                       BKE_ptcache_mem_pointers_init(pm);
 
                        LOOP_POINTS {
                                LOOP_KEYS {
-                                       if((int)key->ftime == pm->frame) {
+                                       if((int)key->ftime == (int)pm->frame) {
                                                key->co = pm->cur[BPHYS_DATA_LOCATION];
                                                key->vel = pm->cur[BPHYS_DATA_VELOCITY];
                                                key->rot = pm->cur[BPHYS_DATA_ROTATION];
                                                key->time = &key->ftime;
                                        }
                                }
-                               BKE_ptcache_mem_incr_pointers(pm);
+                               BKE_ptcache_mem_pointers_incr(pm);
                        }
                }
        }
@@ -3890,7 +3894,17 @@ void PE_undo_step(Scene *scene, int step)
                }
        }
 
-       DAG_id_flush_update(&OBACT->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
+}
+
+int PE_undo_valid(Scene *scene)
+{
+       PTCacheEdit *edit= PE_get_current(scene, OBACT);
+       
+       if(edit) {
+               return (edit->undo.last != edit->undo.first);
+       }
+       return 0;
 }
 
 static void PTCacheUndo_number(Scene *scene, PTCacheEdit *edit, int nr)
@@ -4016,8 +4030,11 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache,
        if(cache && cache->flag & PTCACHE_DISK_CACHE)
                return;
 
+       if(psys == NULL && cache->mem_cache.first == NULL)
+               return;
+
        if(!edit) {
-               totpoint = psys ? psys->totpart : ((PTCacheMem*)cache->mem_cache.first)->totpoint;
+               totpoint = psys ? psys->totpart : (int)((PTCacheMem*)cache->mem_cache.first)->totpoint;
 
                edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit");
                edit->points=MEM_callocN(totpoint*sizeof(PTCacheEditPoint),"PTCacheEditPoints");
@@ -4066,25 +4083,9 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache,
                                totframe++;
 
                        for(pm=cache->mem_cache.first; pm; pm=pm->next) {
-                               BKE_ptcache_mem_init_pointers(pm);
-
                                LOOP_POINTS {
-                                       if(psys) {
-                                               if(pm->index_array) {
-                                                       if(pm->index_array[p])
-                                                               BKE_ptcache_mem_seek_pointers(p, pm);
-                                                       else
-                                                               continue;
-                                               }
-                                               else {
-                                                       pa = psys->particles + p;
-                                                       if((pm->next && pm->next->frame < pa->time)
-                                                               || (pm->prev && pm->prev->frame >= pa->dietime)) {
-                                                                       BKE_ptcache_mem_incr_pointers(pm);
-                                                                       continue;
-                                                               }
-                                               }
-                                       }
+                                       if(BKE_ptcache_mem_pointers_seek(p, pm) == 0)
+                                               continue;
 
                                        if(!point->totkey) {
                                                key = point->keys = MEM_callocN(totframe*sizeof(PTCacheEditKey),"ParticleEditKeys");
@@ -4098,7 +4099,7 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache,
                                        key->rot = pm->cur[BPHYS_DATA_ROTATION];
                                        key->ftime = (float)pm->frame;
                                        key->time = &key->ftime;
-                                       BKE_ptcache_mem_incr_pointers(pm);
+                                       BKE_ptcache_mem_pointers_incr(pm);
 
                                        point->totkey++;
                                }
@@ -4154,7 +4155,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *UNUSED(op))
                WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
        }
 
-       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
        return OPERATOR_FINISHED;
 }
@@ -4194,7 +4195,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
 
                        psys_reset(psys, PSYS_RESET_DEPSGRAPH);
                        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
-                       DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
                }
        }
        else { /* some operation might have protected hair from editing so let's clear the flag */
@@ -4202,7 +4203,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
                psys->flag &= ~PSYS_GLOBAL_HAIR;
                psys->flag &= ~PSYS_EDITED;
                WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
-               DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
 
        return OPERATOR_FINISHED;