diff options
author | Janne Karhu <jhkarh@gmail.com> | 2009-09-06 00:12:08 +0400 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2009-09-06 00:12:08 +0400 |
commit | 08b8fc34cfc082d73e657d1c2941662c36bc3514 (patch) | |
tree | 221eb2513a3830e8bd51e61ccbb44529afca5f58 /source | |
parent | 05c44056dc48bf718475a1e98c9abbd6cc00a535 (diff) |
Disconnect/connect hair:
- Moves hair from face-space to global space and back.
- Allows for editing of emitter mesh after hair combing.
- Disconnect hair before doing topology changing changes in mesh edit mode, connect after changes.
- Notes:
* The closest location on emitter surface to the hair root is used to connect the hair.
* Emitter deflection, sticky roots and add brush don't apply for disconnect hair in particle mode.
- Todo for future:
* Copy disconnected hair from object to another (when 2.5 has proper copy operators again).
* Possible automatic disconnect/connect with topology changing operations in mesh edit mode.
Other changes/fixes:
- Proper subtypes for some particle mode notifiers.
- Particle mode selections didn't draw correctly because of using lighting for the paths.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_pointcache.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 2 | ||||
-rw-r--r-- | source/blender/editors/physics/editparticle.c | 52 | ||||
-rw-r--r-- | source/blender/editors/space_buttons/buttons_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/space_buttons/buttons_ops.c | 218 | ||||
-rw-r--r-- | source/blender/editors/space_buttons/space_buttons.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 18 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_header.c | 6 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_particle.c | 5 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_sculpt_paint.c | 10 |
12 files changed, 289 insertions, 43 deletions
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 9ba34091064..b7ab07b0f91 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -192,6 +192,7 @@ typedef struct PTCacheUndo { struct ParticleData *particles; struct KDTree *emitter_field; float *emitter_cosnos; + int psys_flag; /* cache stuff */ struct ListBase mem_cache; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 81eb0b79c40..0ba2f357a1f 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -418,7 +418,7 @@ void psys_free_path_cache(ParticleSystem *psys, PTCacheEdit *edit) edit->pathcache= NULL; edit->totcached= 0; } - else { + if(psys) { psys_free_path_cache_buffers(psys->pathcache, &psys->pathcachebufs); psys->pathcache= NULL; psys->totcached= 0; @@ -2676,7 +2676,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra baked = psys->pointcache->flag & PTCACHE_BAKED; /* clear out old and create new empty path cache */ - psys_free_path_cache(psys, NULL); + psys_free_path_cache(psys, psys->edit); cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1); if(psys->soft && psys->softflag & OB_SB_ENABLE) { @@ -2891,7 +2891,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf if(!cache || edit->totpoint != edit->totcached) { /* clear out old and create new empty path cache */ - psys_free_path_cache(NULL, edit); + psys_free_path_cache(edit->psys, edit); cache= edit->pathcache= psys_alloc_path_cache_buffers(&edit->pathcachebufs, totpart, steps+1); } @@ -2946,7 +2946,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); /* non-hair points are allready in global space */ - if(psys) + if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) Mat4MulVecfl(hairmat, result.co); VECCOPY(ca->co, result.co); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index eb570ba287c..1931b89af38 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -158,7 +158,7 @@ void psys_reset(ParticleSystem *psys, int mode) psys->totchild= 0; /* reset path cache */ - psys_free_path_cache(psys, NULL); + psys_free_path_cache(psys, psys->edit); /* reset point cache */ psys->pointcache->flag &= ~PTCACHE_SIMULATION_VALID; diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c index bc48d8f4f55..0f5e677b912 100644 --- a/source/blender/editors/physics/editparticle.c +++ b/source/blender/editors/physics/editparticle.c @@ -555,7 +555,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected Mat4One(mat); LOOP_VISIBLE_POINTS { - if(edit->psys) { + if(edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat); Mat4Invert(imat,mat); } @@ -812,7 +812,7 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) float *vec, *nor, dvec[3], dot, dist_1st; float hairimat[4][4], hairmat[4][4]; - if(edit==NULL || edit->psys==NULL || (pset->flag & PE_DEFLECT_EMITTER)==0) + if(edit==NULL || edit->psys==NULL || (pset->flag & PE_DEFLECT_EMITTER)==0 || (edit->psys->flag & PSYS_GLOBAL_HAIR)) return; psys = edit->psys; @@ -876,6 +876,9 @@ void PE_apply_lengths(Scene *scene, PTCacheEdit *edit) if(edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) return; + if(edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) + return; + LOOP_EDITED_POINTS { LOOP_KEYS { if(k) { @@ -899,10 +902,10 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) float dv1[3]= {0.0f, 0.0f, 0.0f}; float dv2[3]= {0.0f, 0.0f, 0.0f}; - if(edit==0) + if(edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) return; - if((pset->flag & PE_KEEP_LENGTHS)==0) + if(edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) return; LOOP_EDITED_POINTS { @@ -1057,11 +1060,13 @@ static void update_world_cos(Object *ob, PTCacheEdit *edit) return; LOOP_POINTS { - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, hairmat); + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, hairmat); LOOP_KEYS { VECCOPY(key->world_co,key->co); - Mat4MulVecfl(hairmat, key->world_co); + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + Mat4MulVecfl(hairmat, key->world_co); } } } @@ -1480,7 +1485,7 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select) Mat4One(mat); LOOP_VISIBLE_POINTS { - if(edit->psys) + if(edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR)) psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + p, mat); if(pset->selectmode==SCE_SELECT_POINT) { @@ -1777,7 +1782,8 @@ static void rekey_particle(PEData *data, int pa_index) for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) { ekey->co= key->co; ekey->time= &key->time; - ekey->flag |= PEK_USE_WCO; + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + ekey->flag |= PEK_USE_WCO; } pa->flag &= ~PARS_REKEY; @@ -2059,7 +2065,9 @@ static void subdivide_particle(PEData *data, int pa_index) nekey->co= nkey->co; nekey->time= &nkey->time; - nekey->flag |= (PEK_SELECT|PEK_USE_WCO); + nekey->flag |= PEK_SELECT; + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + nekey->flag |= PEK_USE_WCO; nekey++; nkey++; @@ -2129,6 +2137,9 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) float mat[4][4], co[3], threshold= RNA_float_get(op->ptr, "threshold"); int n, totn, removed, flag, totremoved; + if(psys->flag & PSYS_GLOBAL_HAIR) + return OPERATOR_CANCELLED; + edit= psys->edit; psmd= psys_get_modifier(ob, psys); totremoved= 0; @@ -2400,6 +2411,9 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) int *mirrorfaces; int rotation, totpart, newtotpart; + if(psys->flag & PSYS_GLOBAL_HAIR) + return; + psmd= psys_get_modifier(ob, psys); mirrorfaces= mesh_get_x_mirror_faces(ob, NULL); @@ -2750,7 +2764,7 @@ static void brush_puff(PEData *data, int point_index) float mat[4][4], imat[4][4]; float lastco[3], rootco[3], co[3], nor[3], kco[3], dco[3], fac, length; - if(psys) { + if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat); Mat4Invert(imat,mat); } @@ -2849,6 +2863,9 @@ static void brush_add(PEData *data, short number) DerivedMesh *dm=0; Mat4Invert(imat,ob->obmat); + if(psys->flag & PSYS_GLOBAL_HAIR) + return; + BLI_srandom(psys->seed+data->mval[0]+data->mval[1]); /* painting onto the deformed mesh, could be an option? */ @@ -3070,6 +3087,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) float vec[3], mousef[2]; short mval[2], mvalo[2]; int flip, mouse[2], dx, dy, removed= 0, selected= 0; + int lock_root = pset->flag & PE_LOCK_FIRST; if(!PE_start_edit(edit)) return; @@ -3093,6 +3111,10 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) mvalo[0]= bedit->lastmouse[0]; mvalo[1]= bedit->lastmouse[1]; + /* disable locking temporatily for disconnected hair */ + if(edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) + pset->flag &= ~PE_LOCK_FIRST; + if(((pset->brushtype == PE_BRUSH_ADD) ? (sqrt(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first) { @@ -3248,6 +3270,8 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) bedit->lastmouse[1]= mouse[1]; bedit->first= 0; } + + pset->flag |= lock_root; } static void brush_edit_exit(bContext *C, wmOperator *op) @@ -3382,6 +3406,8 @@ static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) for(i=0; i<edit->totpoint; i++, pa++) pa->hair= MEM_dupallocN(pa->hair); + + undo->psys_flag = edit->psys->flag; } else { PTCacheMem *pm; @@ -3449,6 +3475,8 @@ static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) hkey++; } } + + psys->flag = undo->psys_flag; } else { PTCacheMem *pm; @@ -3704,7 +3732,8 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, key->co= hkey->co; key->time= &hkey->time; key->flag= hkey->editflag; - key->flag |= PEK_USE_WCO; + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + key->flag |= PEK_USE_WCO; hkey++; } pa++; @@ -3828,6 +3857,7 @@ static int clear_edited_exec(bContext *C, wmOperator *op) psys->free_edit = NULL; psys->recalc |= PSYS_RECALC_RESET; + psys->flag &= ~PSYS_GLOBAL_HAIR; psys_reset(psys, PSYS_RESET_DEPSGRAPH); DAG_id_flush_update(&ob->id, OB_RECALC_DATA); diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index 8ed17ab1fa8..0a5a5714a06 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -85,6 +85,8 @@ void PARTICLE_OT_new_target(struct wmOperatorType *ot); void PARTICLE_OT_remove_target(struct wmOperatorType *ot); void PARTICLE_OT_target_move_up(struct wmOperatorType *ot); void PARTICLE_OT_target_move_down(struct wmOperatorType *ot); +void PARTICLE_OT_connect_hair(struct wmOperatorType *ot); +void PARTICLE_OT_disconnect_hair(struct wmOperatorType *ot); void SCENE_OT_render_layer_add(struct wmOperatorType *ot); void SCENE_OT_render_layer_remove(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 8cdc6b0cd2b..60480a9f165 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -35,6 +35,8 @@ #include "DNA_group_types.h" #include "DNA_object_types.h" #include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_node_types.h" #include "DNA_texture_types.h" #include "DNA_scene_types.h" @@ -42,8 +44,11 @@ #include "DNA_space_types.h" #include "DNA_world_types.h" +#include "BKE_bvhutils.h" +#include "BKE_cdderivedmesh.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" #include "BKE_group.h" #include "BKE_font.h" #include "BKE_library.h" @@ -51,11 +56,13 @@ #include "BKE_material.h" #include "BKE_node.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_world.h" +#include "BLI_arithb.h" #include "BLI_editVert.h" #include "BLI_listbase.h" @@ -838,6 +845,217 @@ void PARTICLE_OT_target_move_down(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/************************ connect/disconnect hair operators *********************/ + +static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) +{ + ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); + ParticleData *pa = psys->particles; + PTCacheEdit *edit = psys->edit; + PTCacheEditPoint *point = edit ? edit->points : NULL; + 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; + + for(i=0; i<psys->totpart; i++,pa++) { + if(point) { + ekey = point->keys; + point++; + } + + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + + for(k=0,key=pa->hair; k<pa->totkey; k++,key++) { + Mat4MulVecfl(hairmat,key->co); + + if(ekey) { + ekey->flag &= ~PEK_USE_WCO; + ekey++; + } + } + } + + psys_free_path_cache(psys, psys->edit); + + psys->flag |= PSYS_GLOBAL_HAIR; + + PE_update_object(scene, ob, 0); +} + +static int disconnect_hair_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys= NULL; + int 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(scene, ob, psys); + } + } + else { + psys = ptr.data; + disconnect_hair(scene, ob, psys); + } + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, 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->exec= disconnect_hair_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh"); +} + +static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) +{ + ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); + ParticleData *pa = psys->particles; + PTCacheEdit *edit = psys->edit; + PTCacheEditPoint *point = edit ? edit->points : NULL; + PTCacheEditKey *ekey; + HairKey *key; + BVHTreeFromMesh bvhtree; + BVHTreeNearest nearest; + MFace *mface; + DerivedMesh *dm = CDDM_copy(psmd->dm); + int numverts = dm->getNumVerts (dm); + int i, k; + float hairmat[4][4], imat[4][4]; + float v[4][3], vec[3]; + + if(!psys || !psys->part || psys->part->type != PART_HAIR) + return; + + memset( &bvhtree, 0, sizeof(bvhtree) ); + + /* convert to global coordinates */ + for (i=0; i<numverts; i++) + Mat4MulVecfl (ob->obmat, CDDM_get_vert(dm, i)->co); + + bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6); + + for(i=0; i<psys->totpart; i++,pa++) { + key = pa->hair; + + nearest.index = -1; + nearest.dist = FLT_MAX; + + BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree); + + if(nearest.index == -1) { + printf("No nearest point found for hair root!"); + continue; + } + + mface = CDDM_get_face(dm,nearest.index); + + VecCopyf(v[0], CDDM_get_vert(dm,mface->v1)->co); + VecCopyf(v[1], CDDM_get_vert(dm,mface->v2)->co); + VecCopyf(v[2], CDDM_get_vert(dm,mface->v3)->co); + if(mface->v4) { + VecCopyf(v[3], CDDM_get_vert(dm,mface->v4)->co); + MeanValueWeights(v, 4, nearest.co, pa->fuv); + } + else + MeanValueWeights(v, 3, nearest.co, pa->fuv); + + pa->num = nearest.index; + pa->num_dmcache = psys_particle_dm_face_lookup(ob,psmd->dm,pa->num,pa->fuv,NULL); + + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + Mat4Invert(imat,hairmat); + + VECSUB(vec, nearest.co, key->co); + + if(point) { + ekey = point->keys; + point++; + } + + for(k=0,key=pa->hair; k<pa->totkey; k++,key++) { + VECADD(key->co, key->co, vec); + Mat4MulVecfl(imat,key->co); + + if(ekey) { + ekey->flag |= PEK_USE_WCO; + ekey++; + } + } + } + + free_bvhtree_from_mesh(&bvhtree); + dm->release(dm); + + psys_free_path_cache(psys, psys->edit); + + psys->flag &= ~PSYS_GLOBAL_HAIR; + + PE_update_object(scene, ob, 0); +} + +static int connect_hair_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys= NULL; + int all = RNA_boolean_get(op->ptr, "all"); + + if(!ob) + return OPERATOR_CANCELLED; + + if(all) { + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + connect_hair(scene, ob, psys); + } + } + else { + psys = ptr.data; + connect_hair(scene, ob, psys); + } + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, 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->exec= connect_hair_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh"); +} + /********************** render layer operators *********************/ static int render_layer_add_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 5d1dbe47345..385f55b71c1 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -204,6 +204,8 @@ void buttons_operatortypes(void) WM_operatortype_append(PARTICLE_OT_remove_target); WM_operatortype_append(PARTICLE_OT_target_move_up); WM_operatortype_append(PARTICLE_OT_target_move_down); + WM_operatortype_append(PARTICLE_OT_connect_hair); + WM_operatortype_append(PARTICLE_OT_disconnect_hair); WM_operatortype_append(SCENE_OT_render_layer_add); WM_operatortype_append(SCENE_OT_render_layer_remove); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 25ff1244254..57e7d897e24 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3749,7 +3749,6 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj nosel_col[1]=(float)nosel[1]/255.0f; nosel_col[2]=(float)nosel[2]/255.0f; - /* draw paths */ if(timed) { glEnable(GL_BLEND); @@ -3758,24 +3757,16 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj } glEnableClientState(GL_VERTEX_ARRAY); - - /* solid shaded with lighting */ - glEnableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); - /* only draw child paths with lighting */ - if(dt > OB_WIRE) - glEnable(GL_LIGHTING); - - /* draw paths without lighting */ cache=edit->pathcache; for(i=0; i<totpoint; i++){ path = cache[i]; glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); - glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel); if(timed) { for(k=0, pcol=pathcol, pkey=path; k<steps; k++, pkey++, pcol+=4){ @@ -3796,9 +3787,6 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj /* draw edit vertices */ if(pset->selectmode!=SCE_SELECT_PATH){ - glDisableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glDisable(GL_LIGHTING); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); if(pset->selectmode==SCE_SELECT_POINT){ @@ -3810,7 +3798,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj if(!(point->flag & PEP_HIDE)) totkeys += point->totkey; - if(!edit->psys) + if(!(edit->points->keys->flag & PEK_USE_WCO)) pd=pdata=MEM_callocN(totkeys*3*sizeof(float), "particle edit point data"); cd=cdata=MEM_callocN(totkeys*(timed?4:3)*sizeof(float), "particle edit color data"); @@ -3843,7 +3831,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj if(point->flag & PEP_HIDE) continue; - if(edit->psys) + if(point->keys->flag & PEK_USE_WCO) glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co); else glVertexPointer(3, GL_FLOAT, 3*sizeof(float), pd); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 2283d36e018..b6159cf4314 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -1760,17 +1760,17 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event) case B_SEL_PATH: ts->particle.selectmode= SCE_SELECT_PATH; - WM_event_add_notifier(C, NC_OBJECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); ED_undo_push(C, "Selectmode Set: Path"); break; case B_SEL_POINT: ts->particle.selectmode = SCE_SELECT_POINT; - WM_event_add_notifier(C, NC_OBJECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); ED_undo_push(C, "Selectmode Set: Point"); break; case B_SEL_END: ts->particle.selectmode = SCE_SELECT_END; - WM_event_add_notifier(C, NC_OBJECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); ED_undo_push(C, "Selectmode Set: End point"); break; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 0fce9592d1d..3f32b707043 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1690,11 +1690,11 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) if(!(point->flag & PEP_TRANSFORM)) continue; - if(psys) + if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat); for(k=0, key=point->keys; k<point->totkey; k++, key++) { - if(psys) { + if(key->flag & PEK_USE_WCO) { VECCOPY(key->world_co, key->co); Mat4MulVecfl(mat, key->world_co); td->loc = key->world_co; @@ -1714,7 +1714,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) Mat3One(td->smtx); /* don't allow moving roots */ - if(k==0 && pset->flag & PE_LOCK_FIRST) + if(k==0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR))) td->protectflag |= OB_LOCK_LOC; td->ob = ob; @@ -1764,7 +1764,7 @@ void flushTransParticles(TransInfo *t) for(i=0, point=edit->points; i<edit->totpoint; i++, point++, td++) { if(!(point->flag & PEP_TRANSFORM)) continue; - if(psys) { + if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat); Mat4Invert(imat,mat); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 4a23605c717..71b953effdf 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -1884,6 +1884,11 @@ static void rna_def_particle_system(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "softflag", OB_SB_ENABLE); RNA_def_property_ui_text(prop, "Use Soft Body", "Enable use of soft body for hair physics simulation."); + prop= RNA_def_property(srna, "global_hair", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_GLOBAL_HAIR); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Global Hair", "Hair keys are in global coordinate space"); + /* reactor */ prop= RNA_def_property(srna, "reactor_target_object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "target_ob"); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 5575b170398..ab4b27cea7b 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -107,7 +107,7 @@ static void rna_ParticleEdit_redo(bContext *C, PointerRNA *ptr) if(!edit) return; - psys_free_path_cache(NULL, edit); + psys_free_path_cache(edit->psys, edit); } static void rna_ParticleEdit_update(bContext *C, PointerRNA *ptr) @@ -410,7 +410,7 @@ static void rna_def_particle_edit(BlenderRNA *brna) prop= RNA_def_property(srna, "fade_time", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_FADE_TIME); RNA_def_property_ui_text(prop, "Fade Time", "Fade paths and keys further away from current frame."); - RNA_def_property_update(prop, NC_OBJECT, "rna_ParticleEdit_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_ParticleEdit_update"); prop= RNA_def_property(srna, "auto_velocity", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_AUTO_VELOCITY); @@ -443,18 +443,18 @@ static void rna_def_particle_edit(BlenderRNA *brna) prop= RNA_def_property(srna, "draw_step", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 2, 10); RNA_def_property_ui_text(prop, "Steps", "How many steps to draw the path with."); - RNA_def_property_update(prop, NC_OBJECT, "rna_ParticleEdit_redo"); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_ParticleEdit_redo"); prop= RNA_def_property(srna, "fade_frames", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 2, 100); RNA_def_property_ui_text(prop, "Frames", "How many frames to fade."); - RNA_def_property_update(prop, NC_OBJECT, "rna_ParticleEdit_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_ParticleEdit_update"); prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "edittype"); RNA_def_property_enum_items(prop, edit_type_items); RNA_def_property_ui_text(prop, "Type", ""); - RNA_def_property_update(prop, NC_OBJECT, "rna_ParticleEdit_redo"); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_ParticleEdit_redo"); prop= RNA_def_property(srna, "editable", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_ParticleEdit_editable_get", NULL); |