diff --git a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj index 7b7d1ac0608..b9232fe620a 100644 --- a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj +++ b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj @@ -73,7 +73,7 @@ + + @@ -254,6 +257,9 @@ + + diff --git a/projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj b/projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj index ffa4c00f098..4f1e616dd36 100644 --- a/projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj +++ b/projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj @@ -21,7 +21,7 @@ 0: + f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"] + if props[6]['template billboard'] == 2: + f.mode |= Blender.Mesh.FaceModes["BILLBOARD"] + f.mode |= Blender.Mesh.FaceModes["LIGHT"] + #f.mat = props[0] f.image = props[1] f.uv = props[2] diff --git a/release/scripts/import_mdd.py b/release/scripts/import_mdd.py index 8e7b9985d3d..1ee196ab67f 100644 --- a/release/scripts/import_mdd.py +++ b/release/scripts/import_mdd.py @@ -1,11 +1,11 @@ #!BPY - #""" - #Name: 'Load MDD to Mesh RVKs' - #Blender: 242 - #Group: 'Import' - #Tooltip: 'baked vertex animation to active mesh object.' - #""" +""" + Name: 'Load MDD to Mesh RVKs' + Blender: 242 + Group: 'Import' + Tooltip: 'baked vertex animation to active mesh object.' +""" __author__ = "Bill L.Nieuwendorp" __bpydoc__ = """\ This script Imports Lightwaves MotionDesigner format. diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index c3e978a5a9a..a82faa56e40 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -34,6 +34,8 @@ #ifndef BKE_ANIM_H #define BKE_ANIM_H +#define MAX_DUPLI_RECUR 8 + struct Path; struct Object; struct PartEff; @@ -46,6 +48,7 @@ typedef struct DupliObject { unsigned int origlay; int index, no_draw, type; float mat[4][4], omat[4][4]; + float orco[3], uv[2]; } DupliObject; void free_path(struct Path *path); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index e71145e8d79..8aaa9e42289 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -180,7 +180,7 @@ typedef struct Global { #define G_DRAW_FACEAREA (1 << 23) #define G_DRAW_EDGEANG (1 << 24) -#define G_RECORDKEYS (1 << 25) +/* #define G_RECORDKEYS (1 << 25) also removed */ /*#ifdef WITH_VERSE*/ #define G_VERSE_CONNECTED (1 << 26) #define G_DRAW_VERSE_DEBUG (1 << 27) @@ -189,7 +189,7 @@ typedef struct Global { #define G_SCULPTMODE (1 << 29) #define G_PARTICLEEDIT (1 << 30) -#define G_AUTOMATKEYS (1 << 30) +/* #define G_AUTOMATKEYS (1 << 30) also removed */ #define G_HIDDENHANDLES (1 << 31) /* used for curves only */ /* macro for testing face select mode diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index a1ac97406e1..d92e8bad1f9 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -244,6 +244,8 @@ float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time); void psys_get_particle_on_path(struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel); int psys_get_particle_state(struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always); +void psys_get_dupli_texture(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco); +void psys_get_dupli_path_transform(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys, int totthread); int psys_threads_init_distribution(ParticleThread *threads, struct DerivedMesh *dm, int from); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index c0776583a04..0b87f0c1d98 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -32,7 +32,7 @@ FILE(GLOB SRC intern/*.c) SET(INC . ../../../intern/guardedalloc ../include ../blenlib ../makesdna ../python ../render/extern/include ../../../intern/decimation/extern - ../imbuf ../avi ../../../intern/elbeem/extern + ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern ../../../intern/iksolver/extern ../blenloader ../quicktime ../../../intern/bmfont ../nodes diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index aada60be21b..9ee4e62b9cb 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2135,9 +2135,13 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], } /* add an orco layer if needed */ - if(dataMask & CD_MASK_ORCO) + if(dataMask & CD_MASK_ORCO) { add_orco_dm(ob, finaldm, orcodm); + if(deform_r && *deform_r) + add_orco_dm(ob, *deform_r, NULL); + } + *final_r = finaldm; if(orcodm) diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index b3bc6c72996..488d8801e41 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -69,6 +69,7 @@ CPPFLAGS += $(NAN_SDLCFLAGS) CPPFLAGS += -I$(NAN_IKSOLVER)/include CPPFLAGS += -I$(NAN_DECIMATION)/include CPPFLAGS += -I$(NAN_ELBEEM)/include +CPPFLAGS += -I$(NAN_OPENNL)/include # path to zlib CPPFLAGS += -I$(NAN_ZLIB)/include diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 4dab625d2c9..61668ddb0eb 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -441,6 +441,8 @@ static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert float length, actlength, repeat, scale; repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat); + if(strip->scale == 0.0f) strip->scale= 1.0f; + scale = abs(strip->scale); /* scale must be positive (for now) */ actlength = strip->actend-strip->actstart; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 40c776248cf..933cf1f2e3b 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -75,8 +75,6 @@ #include #endif -#define MAX_DUPLI_RECUR 4 - static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level); void free_path(Path *path) @@ -378,10 +376,12 @@ struct vertexDupliData { float pmat[4][4]; float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */ Object *ob, *par; + float (*orco)[3]; }; static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { + DupliObject *dob; struct vertexDupliData *vdd= userData; float vec[3], *q2, mat[3][3], tmat[4][4], obmat[4][4]; @@ -407,7 +407,9 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n Mat4CpyMat4(tmat, obmat); Mat4MulMat43(obmat, tmat, mat); } - new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS); + dob= new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, OB_DUPLIVERTS); + if(vdd->orco) + VECCOPY(dob->orco, vdd->orco[index]); if(vdd->ob->transflag & OB_DUPLI) { float tmpmat[4][4]; @@ -429,16 +431,25 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ Scene *sce = NULL; Group *group = NULL; GroupObject * go = NULL; + CustomDataMask dataMask = CD_MASK_BAREMESH; Mat4CpyMat4(pmat, par->obmat); /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; + + if(G.rendering) + dataMask |= CD_MASK_ORCO; if(par==G.obedit) - dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); + dm= editmesh_get_derived_cage(dataMask); else - dm = mesh_get_derived_deform(par, CD_MASK_BAREMESH); + dm= mesh_get_derived_deform(par, dataMask); + + if(G.rendering) + vdd.orco= dm->getVertDataArray(dm, CD_ORCO); + else + vdd.orco= NULL; totvert = dm->getNumVerts(dm); @@ -517,25 +528,31 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma { Object *ob, *ob_iter; Base *base = NULL; + DupliObject *dob; DerivedMesh *dm; + Mesh *me; + MTFace *mtface; MFace *mface; MVert *mvert; - float pmat[4][4], imat[3][3]; + float pmat[4][4], imat[3][3], (*orco)[3], w; int lay, oblay, totface, a; Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; - + CustomDataMask dataMask = CD_MASK_BAREMESH; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; - Mat4CpyMat4(pmat, par->obmat); + if(G.rendering) + dataMask |= CD_MASK_ORCO; + Mat4CpyMat4(pmat, par->obmat); + if(par==G.obedit) { int totvert; - dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); + dm= editmesh_get_derived_cage(dataMask); totface= dm->getNumFaces(dm); mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp"); @@ -545,13 +562,22 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma dm->copyVertArray(dm, mvert); } else { - dm = mesh_get_derived_deform(par, CD_MASK_BAREMESH); + dm = mesh_get_derived_deform(par, dataMask); totface= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); mvert= dm->getVertArray(dm); } - + + if(G.rendering) { + me= (Mesh*)par->data; + orco= dm->getVertDataArray(dm, CD_ORCO); + mtface= me->mtface; + } + else { + orco= NULL; + mtface= NULL; + } /* having to loop on scene OR group objects is NOT FUN */ if (GS(id->name) == ID_SCE) { @@ -595,10 +621,14 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ for(a=0; aorco, dob->orco, orco[mv1], w); + VECADDFAC(dob->orco, dob->orco, orco[mv2], w); + VECADDFAC(dob->orco, dob->orco, orco[mv3], w); + if(mv4) + VECADDFAC(dob->orco, dob->orco, orco[mv4], w); + } + + if(mtface) { + dob->uv[0] += w*mtface[a].uv[0][0]; + dob->uv[1] += w*mtface[a].uv[0][1]; + dob->uv[0] += w*mtface[a].uv[1][0]; + dob->uv[1] += w*mtface[a].uv[1][1]; + dob->uv[0] += w*mtface[a].uv[2][0]; + dob->uv[1] += w*mtface[a].uv[2][1]; + + if(mv4) { + dob->uv[0] += w*mtface[a].uv[3][0]; + dob->uv[1] += w*mtface[a].uv[3][1]; + } + } + } if(ob->transflag & OB_DUPLI) { float tmpmat[4][4]; @@ -660,38 +715,14 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma dm->release(dm); } -static void particle_dupli_path_rotation(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) -{ - float loc[3], nor[3], vec[3], side[3], len; - - VecSubf(vec, (cache+cache->steps-1)->co, cache->co); - len= Normalize(vec); - - if(pa) - psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); - else - psys_particle_on_emitter(ob, psmd, - (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, - cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0); - - Crossf(side, nor, vec); - Normalize(side); - Crossf(nor, vec, side); - - Mat4One(mat); - VECCOPY(mat[0], vec); - VECCOPY(mat[1], side); - VECCOPY(mat[2], nor); - - *scale= len; -} - static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level) { GroupObject *go; Object *ob=0, **oblist=0; + DupliObject *dob; ParticleSettings *part; ParticleData *pa; + ChildParticle *cpa=0; ParticleKey state; ParticleCacheKey *cache; ParticleSystemModifierData *psmd; @@ -773,10 +804,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ } else { /* TODO: figure these two out */ + cpa= &psys->child[a - totpart]; pa_num = a; - pa_time = psys->particles[psys->child[a - totpart].parent].time; + pa_time = psys->particles[cpa->parent].time; - size=psys_get_child_size(psys, &psys->child[a - totpart], ctime, 0); + size=psys_get_child_size(psys, cpa, ctime, 0); } if(part->draw_as==PART_DRAW_GR) { @@ -795,12 +827,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ if(hair) { if(a < totpart) { cache = psys->pathcache[a]; - particle_dupli_path_rotation(par, part, psmd, pa, 0, cache, pamat, &scale); + psys_get_dupli_path_transform(par, part, psmd, pa, 0, cache, pamat, &scale); } else { - ChildParticle *cpa= psys->child+(a-totpart); cache = psys->childcache[a-totpart]; - particle_dupli_path_rotation(par, part, psmd, 0, cpa, cache, pamat, &scale); + psys_get_dupli_path_transform(par, part, psmd, 0, cpa, cache, pamat, &scale); } VECCOPY(pamat[3], cache->co); @@ -833,7 +864,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ else Mat4CpyMat4(mat, tmat); - new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS); + dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS); + if(G.rendering) + psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); } } else { @@ -857,7 +890,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ else Mat4CpyMat4(mat, tmat); - new_dupli_object(lb, ob, mat, par->lay, counter, OB_DUPLIPARTS); + dob= new_dupli_object(lb, ob, mat, par->lay, counter, OB_DUPLIPARTS); + if(G.rendering) + psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); } } } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index f7864761b1d..c23cc90aeb8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1490,7 +1490,7 @@ void makeBevelList(Object *ob) resolu= nu->resolu; if((nu->type & 7)==CU_POLY) { - + len= nu->pntsu; bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); BLI_addtail(&(cu->bev), bl); @@ -1974,7 +1974,7 @@ float calc_curve_subdiv_radius(Curve *cu, Nurb *nu, int cursubdiv) } if ( ((nu->type & 7)==CU_NURBS) && (nu->flagu & CU_CYCLIC)) { - if (bp == bplast) bp = bpfirst; + if (bp >= bplast) bp = bpfirst; else bp++; } diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 0874890a2c6..3a8847a5be1 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1287,7 +1287,7 @@ void multires_edge_level_update(Object *ob, Mesh *me) if(!G.obedit) { MultiresLevel *cr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); MultiresLevel *edge_lvl= BLI_findlink(&me->mr->levels,me->mr->edgelvl-1); - const int threshold= edge_lvl->totedge * powf(2, me->mr->current - me->mr->edgelvl); + const int threshold= edge_lvl->totedge * pow(2, me->mr->current - me->mr->edgelvl); unsigned i; for(i=0; itotedge; ++i) { diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 54b8a5c47e6..0ac60e6da4e 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3563,3 +3563,78 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey //} } +void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco) +{ + MFace *mface; + MTFace *mtface; + float loc[3]; + int num; + + if(cpa) { + if(part->childtype == PART_CHILD_FACES) { + mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE); + if(mtface) { + mface= psmd->dm->getFaceData(psmd->dm, cpa->num, CD_MFACE); + mtface += cpa->num; + psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv); + } + else + uv[0]= uv[1]= 0.0f; + } + else + uv[0]= uv[1]= 0.0f; + + psys_particle_on_emitter(ob, psmd, + (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, + cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,0,0,0,orco,0); + } + else { + if(part->from == PART_FROM_FACE) { + mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE); + num= pa->num_dmcache; + + if(num == DMCACHE_NOTFOUND) + if(pa->num < psmd->dm->getNumFaces(psmd->dm)) + num= pa->num; + + if(mtface && num != DMCACHE_NOTFOUND) { + mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE); + mtface += num; + psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv); + } + else + uv[0]= uv[1]= 0.0f; + } + else + uv[0]= uv[1]= 0.0f; + + psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,orco,0); + } +} + +void psys_get_dupli_path_transform(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) +{ + float loc[3], nor[3], vec[3], side[3], len; + + VecSubf(vec, (cache+cache->steps-1)->co, cache->co); + len= Normalize(vec); + + if(pa) + psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); + else + psys_particle_on_emitter(ob, psmd, + (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, + cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0); + + Crossf(side, nor, vec); + Normalize(side); + Crossf(nor, vec, side); + + Mat4One(mat); + VECCOPY(mat[0], vec); + VECCOPY(mat[1], side); + VECCOPY(mat[2], nor); + + *scale= len; +} + diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 436d4d2210d..f69e7bcd05f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1138,7 +1138,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm double step, pos; step= (totpart <= 1)? 0.5: 1.0/(totpart-1); - pos= 0.0f; + pos= 1e-16f; /* tiny offset to avoid zero weight face */ i= 0; for(p=0; pmarkers); + BLI_freelistN(&sce->transform_spaces); BLI_freelistN(&sce->r.layers); if(sce->toolsettings){ @@ -703,4 +704,6 @@ void sculpt_reset_curve(SculptData *sd) cm->curve[4].y= 0.20611; cm->curve[5].x= 1; cm->curve[5].y= 0; + + curvemapping_changed(sd->cumap, 0); } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index b08b3e819d9..7c427d3c434 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1510,14 +1510,20 @@ void scan_for_ext_spring_forces(Object *ob,float timenow) } f = Normalize(vel); f = -0.0001f*f*f*sb->aeroedge; - /* todo add a nice angle dependant function */ - /* look up one at bergman scheafer */ + /* (todo) add a nice angle dependant function done for now BUT */ + /* still there could be some nice drag/lift function, but who needs it */ VECSUB(sp, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos); Projf(pr,vel,sp); VECSUB(vel,vel,pr); Normalize(vel); - Vec3PlusStVec(bs->ext_force,f,vel); + if (ob->softflag & OB_SB_AERO_ANGLE){ + Normalize(sp); + Vec3PlusStVec(bs->ext_force,f*(1.0f-ABS(Inpf(vel,sp))),vel); + } + else{ + Vec3PlusStVec(bs->ext_force,f,vel); // to keep compatible with 2.45 release files + } } /* --- springs seeing wind */ } @@ -2252,15 +2258,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int float defforce[3]; do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow); } -/* - if (do_selfcollision ){ - float ce[3]; - VecMidf(ce,sb->scratch->aabbmax,sb->scratch->aabbmin); - for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { - bp->octantflag = set_octant_flags(ce,bp->pos,bp->colball); - } - } -*/ + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { /* clear forces accumulator */ bp->force[0]= bp->force[1]= bp->force[2]= 0.0; @@ -3622,7 +3620,7 @@ SoftBody *sbNew(void) sb->inspring= 0.5f; sb->infrict= 0.5f; - /*todo backward file compat should copy infrict to inpush while reading old files*/ + /*todo backward file compat should copy inspring to inpush while reading old files*/ sb->inpush = 0.5f; sb->interval= 10; diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 1197e710806..cf02fc67ec4 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -3415,6 +3415,8 @@ void tubemap(float x, float y, float z, float *u, float *v) len= sqrt(x*x+y*y); if(len>0) { *u = (1.0 - (atan2(x/len,y/len) / M_PI)) / 2.0; + } else { + *v = *u = 0.0f; /* to avoid un-initialized variables */ } } @@ -3432,6 +3434,8 @@ void spheremap(float x, float y, float z, float *u, float *v) z/=len; *v = 1.0- saacos(z)/M_PI; + } else { + *v = *u = 0.0f; /* to avoid un-initialized variables */ } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 54d405132a9..dbc2a658ea9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3482,6 +3482,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) } link_list(fd, &(sce->markers)); + link_list(fd, &(sce->transform_spaces)); link_list(fd, &(sce->r.layers)); sce->nodetree= newdataadr(fd, sce->nodetree); @@ -7295,6 +7296,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main) strip->scale = length / (repeat * actlength); if (strip->scale == 0.0f) strip->scale= 1.0f; } + if(ob->soft){ + ob->soft->inpush = ob->soft->inspring; + ob->soft->shearstiff = 1.0f; + } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 3326d38c56f..9d766b1e22e 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1410,6 +1410,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) MetaStack *ms; Strip *strip; TimeMarker *marker; + TransformOrientation *ts; SceneRenderLayer *srl; int a; @@ -1514,6 +1515,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase) for(marker= sce->markers.first; marker; marker= marker->next) writestruct(wd, DATA, "TimeMarker", 1, marker); + /* writing dynamic list of TransformOrientations to the blend file */ + for(ts = sce->transform_spaces.first; ts; ts = ts->next) + writestruct(wd, DATA, "TransformOrientation", 1, ts); + for(srl= sce->r.layers.first; srl; srl= srl->next) writestruct(wd, DATA, "SceneRenderLayer", 1, srl); diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index eb4adb4bbcf..938d6d3d672 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -118,6 +118,7 @@ void sample_action_keys(void); void column_select_action_keys(int mode); void selectall_action_keys(short mval[], short mode, short selectmode); void markers_selectkeys_between(void); +void nextprev_action_keyframe(short dir); /* Action Data Copying */ void free_actcopybuf(void); @@ -130,6 +131,9 @@ void down_sel_action(void); void top_sel_action(void); void bottom_sel_action(void); +void expand_all_action(void); +void openclose_level_action(short mode); + /* IPO/Handle Types */ void sethandles_action_keys(int code); void action_set_ipo_flags(short mode, short event); diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h index 78f5ff90a4e..43f0629f935 100644 --- a/source/blender/include/BIF_space.h +++ b/source/blender/include/BIF_space.h @@ -55,6 +55,7 @@ struct SpaceOops; #define VIEW3D_HANDLER_OBJECT 3 #define VIEW3D_HANDLER_PREVIEW 4 #define VIEW3D_HANDLER_MULTIRES 5 +#define VIEW3D_HANDLER_TRANSFORM 6 /* ipo handler codes */ #define IPO_HANDLER_PROPERTIES 20 diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index 6d4095f0d40..c8e2a4832ab 100644 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -81,6 +81,8 @@ int calculateTransformCenter(int centerMode, float *vec); struct TransInfo; struct ScrArea; +struct Base; +struct Scene; struct TransInfo * BIF_GetTransInfo(void); void BIF_setSingleAxisConstraint(float vec[3], char *text); @@ -88,6 +90,20 @@ void BIF_setDualAxisConstraint(float vec1[3], float vec2[3], char *text); void BIF_setLocalAxisConstraint(char axis, char *text); void BIF_setLocalLockConstraint(char axis, char *text); +int BIF_snappingSupported(void); + +struct TransformOrientation; + +void BIF_clearTransformOrientation(void); +void BIF_removeTransformOrientation(struct TransformOrientation *ts); +void BIF_manageTransformOrientation(int confirm, int set); +int BIF_menuselectTransformOrientation(void); +void BIF_selectTransformOrientation(struct TransformOrientation *ts); +void BIF_selectTransformOrientationFromIndex(int index); + +char * BIF_menustringTransformOrientation(); /* the returned value was allocated and needs to be freed after use */ +int BIF_countTransformOrientation(); + /* Drawing callbacks */ void BIF_drawConstraint(void); void BIF_drawPropCircle(void); diff --git a/source/blender/include/BSE_node.h b/source/blender/include/BSE_node.h index b1854e31d50..9e6acc7af04 100644 --- a/source/blender/include/BSE_node.h +++ b/source/blender/include/BSE_node.h @@ -103,6 +103,9 @@ void node_rename_but(char *s); void init_node_butfuncs(void); +void node_curvemap_sample(float *col); + + /* exported to CMP and SHD nodes */ //void node_ID_title_cb(void *node_v, void *unused_v); //void node_but_title_cb(void *node_v, void *but_v); diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 8f9de747c2a..36ae384467d 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -237,6 +237,7 @@ #define B_SEL_PATH 166 #define B_SEL_POINT 167 #define B_SEL_END 168 +#define B_MAN_MODE 169 /* IPO: 200 */ #define B_IPOHOME 201 diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 37abfc771ea..b8d194802ac 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -170,6 +170,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_ARMATUREPANEL3 1013 #define B_OBJECTPANELSCALE 1014 #define B_OBJECTPANELDIMS 1015 +#define B_TRANSFORMSPACEADD 1016 +#define B_TRANSFORMSPACECLEAR 1017 /* *********************** */ #define B_LAMPBUTS 1200 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 58cbd5c8755..e9e82612721 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -122,7 +122,7 @@ typedef struct TransDataExtension { float iquat[4]; /* Initial rotation quaternion */ float *size; /* Size of the data to transform (Faculative) */ float isize[3]; /* Initial size */ - float obmat[3][3]; /* Object matrix */ + float obmat[4][4]; /* Object matrix */ } TransDataExtension; typedef struct TransData2D { @@ -382,6 +382,7 @@ void special_aftertrans_update(TransInfo *t); void transform_autoik_update(TransInfo *t, short mode); /* auto-keying stuff used by special_aftertrans_update */ +short autokeyframe_cfra_can_key(struct Object *ob); void autokeyframe_ob_cb_func(struct Object *ob, int tmode); void autokeyframe_pose_cb_func(struct Object *ob, int tmode, short targetless_ik); @@ -462,6 +463,15 @@ short hasNumInput(NumInput *n); void applyNumInput(NumInput *n, float *vec); char handleNumInput(NumInput *n, unsigned short event); +/*********************** TransSpace ******************************/ + +int manageObjectSpace(int confirm, int set); +int manageMeshSpace(int confirm, int set); + +int addMatrixSpace(float mat[3][3], char name[]); +int addObjectSpace(struct Object *ob); +void applyTransformOrientation(void); + #endif diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index a4224976f5f..3caa74c9a72 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -69,13 +69,16 @@ typedef struct CurveMapping { CurveMap cm[4]; /* max 4 builtin curves per mapping struct now */ float black[3], white[3]; /* black/white point (black[0] abused for current frame) */ - float bwmul[3], padf; /* black/white point multiply value, for speed */ + float bwmul[3]; /* black/white point multiply value, for speed */ + + float sample[3]; /* sample values, if flag set it draws line and intersection */ } CurveMapping; /* cumapping->flag */ #define CUMA_DO_CLIP 1 #define CUMA_PREMULLED 2 #define CUMA_DRAW_CFRA 4 +#define CUMA_DRAW_SAMPLE 8 #endif diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index dd6b2692de6..1deda6a29d5 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -85,7 +85,7 @@ typedef struct Material { short flarec, starc, linec, ringc; float hasize, flaresize, subsize, flareboost; float strand_sta, strand_end, strand_ease, strand_surfnor; - float strand_min, strand_pad; + float strand_min, strand_widthfade; char strand_uvname[32]; float sbias; /* shadow bias */ diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index b0408f2f4d9..6ef0e5a9462 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -190,6 +190,7 @@ typedef struct SoftBody { #define OB_SB_EDGECOLL 2048 #define OB_SB_COLLFINAL 4096 #define OB_SB_PROTECT_CACHE 8192 +#define OB_SB_AERO_ANGLE 16384 /* sb->solverflags */ #define SBSO_MONITOR 1 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index c82a1f9e510..282093f39be 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -333,6 +333,12 @@ typedef struct ParticleEditSettings { int draw_timed; } ParticleEditSettings; +typedef struct TransformOrientation { + struct TransformOrientation *next, *prev; + char name[36]; + float mat[3][3]; +} TransformOrientation; + typedef struct ToolSettings { /* Subdivide Settings */ short cornertype; @@ -366,7 +372,7 @@ typedef struct ToolSettings { /* Auto-IK */ short autoik_chainlen; - /* Image Paint (8 byte aligned please!) */ + /* Image Paint (8 byttse aligned please!) */ struct ImagePaintSettings imapaint; /* Particle Editing */ @@ -494,6 +500,7 @@ typedef struct Scene { ScriptLink scriptlink; ListBase markers; + ListBase transform_spaces; short jumpframe, pad1; short snap_flag, snap_target; diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 182ac6025fd..bc2b0521d4f 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -347,11 +347,12 @@ typedef struct TexMapping { #define PROJ_Z 3 /* texflag */ -#define MTEX_RGBTOINT 1 -#define MTEX_STENCIL 2 -#define MTEX_NEGATIVE 4 -#define MTEX_ALPHAMIX 8 -#define MTEX_VIEWSPACE 16 +#define MTEX_RGBTOINT 1 +#define MTEX_STENCIL 2 +#define MTEX_NEGATIVE 4 +#define MTEX_ALPHAMIX 8 +#define MTEX_VIEWSPACE 16 +#define MTEX_DUPLI_MAPTO 32 /* blendtype */ #define MTEX_BLEND 0 @@ -364,6 +365,10 @@ typedef struct TexMapping { #define MTEX_LIGHT 7 #define MTEX_SCREEN 8 #define MTEX_OVERLAY 9 +#define MTEX_BLEND_HUE 10 +#define MTEX_BLEND_SAT 11 +#define MTEX_BLEND_VAL 12 +#define MTEX_BLEND_COLOR 13 /* **************** EnvMap ********************* */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 138040b13ca..9f118bd38cc 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -197,7 +197,10 @@ typedef struct UserDef { short glreslimit; char versemaster[160]; char verseuser[160]; - float glalphaclip, pad; + float glalphaclip; + + short autokey_mode; /* autokeying mode */ + short autokey_flag; /* flags for autokeying */ struct ColorBand coba_weight; /* from texture.h */ } UserDef; @@ -229,16 +232,14 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_ADD_VIEWALIGNED (1 << 19) #define USER_ADD_VIEWALIGNED (1 << 19) - /* viewzom */ #define USER_ZOOM_CONT 0 #define USER_ZOOM_SCALE 1 #define USER_ZOOM_DOLLY 2 /* uiflag */ - -#define USER_KEYINSERTACT (1 << 0) -#define USER_KEYINSERTOBJ (1 << 1) +// old flag for #define USER_KEYINSERTACT (1 << 0) +// old flag for #define USER_KEYINSERTOBJ (1 << 1) #define USER_WHEELZOOMDIR (1 << 2) #define USER_FILTERFILEEXTS (1 << 3) #define USER_DRAWVIEWINFO (1 << 4) @@ -252,17 +253,33 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_LOCKAROUND (1 << 12) #define USER_GLOBALUNDO (1 << 13) #define USER_ORBIT_SELECTION (1 << 14) -#define USER_KEYINSERTAVAI (1 << 15) +// old flag for #define USER_KEYINSERTAVAI (1 << 15) #define USER_HIDE_DOT (1 << 16) #define USER_SHOW_ROTVIEWICON (1 << 17) #define USER_SHOW_VIEWPORTNAME (1 << 18) -#define USER_KEYINSERTNEED (1 << 19) +// old flag for #define USER_KEYINSERTNEED (1 << 19) #define USER_ZOOM_TO_MOUSEPOS (1 << 20) -#define USER_SHOW_FPS (1 << 21) +#define USER_SHOW_FPS (1 << 21) #define USER_UNDOSAVE (1 << 22) // flag to signal a write_undo() call after a save (save on exit needed then) -/* transopts */ +/* Auto-Keying mode */ + /* AUTOKEY_ON is a bitflag */ +#define AUTOKEY_ON 1 + /* AUTOKEY_ON + 2**n... (i.e. AUTOKEY_MODE_NORMAL = AUTOKEY_ON + 2) to preserve setting, even when autokey turned off */ +#define AUTOKEY_MODE_NORMAL 3 +#define AUTOKEY_MODE_EDITKEYS 5 +/* Auto-Keying flag */ +#define AUTOKEY_FLAG_INSERTAVAIL (1<<0) +#define AUTOKEY_FLAG_INSERTNEEDED (1<<1) +#define AUTOKEY_FLAG_AUTOMATKEY (1<<2) + +/* Auto-Keying macros */ +#define IS_AUTOKEY_ON (U.autokey_mode & AUTOKEY_ON) +#define IS_AUTOKEY_MODE(mode) (U.autokey_mode == AUTOKEY_MODE_##mode) +#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag == AUTOKEY_FLAG_##flag) + +/* transopts */ #define USER_TR_TOOLTIPS (1 << 0) #define USER_TR_BUTTONS (1 << 1) #define USER_TR_MENUS (1 << 2) @@ -273,7 +290,6 @@ extern UserDef U; /* from usiblender.c !!!! */ #define CONVERT_TO_UTF8 (1 << 7) /* dupflag */ - #define USER_DUP_MESH (1 << 0) #define USER_DUP_CURVE (1 << 1) #define USER_DUP_SURF (1 << 2) @@ -287,13 +303,11 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_DUP_ACT (1 << 10) /* gameflags */ - #define USER_VERTEX_ARRAYS 1 #define USER_DISABLE_SOUND 2 #define USER_DISABLE_MIPMAP 4 /* vrml flag */ - #define USER_VRML_LAYERS 1 #define USER_VRML_AUTOSCALE 2 #define USER_VRML_TWOSIDED 4 diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index ee75d7b8f0f..78605464268 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -200,6 +200,7 @@ typedef struct View3D { #define V3D_MANIP_LOCAL 1 #define V3D_MANIP_NORMAL 2 #define V3D_MANIP_VIEW 3 +#define V3D_MANIP_CUSTOM 4 /* anything of value 4 or higher is custom */ /* View3d->twflag */ /* USE = user setting, DRAW = based on selection */ diff --git a/source/blender/python/api2_2x/doc/Mathutils.py b/source/blender/python/api2_2x/doc/Mathutils.py index 7546bb5b6d5..8b0c41b9a69 100644 --- a/source/blender/python/api2_2x/doc/Mathutils.py +++ b/source/blender/python/api2_2x/doc/Mathutils.py @@ -28,15 +28,15 @@ Example:: print angle """ -def Rand (high = 1, low = 0): +def Rand (low=0.0, high = 1.0): """ Return a random number within a range. - High and low represent the range from which the random - number must return its result. - @type high: float - @param high: The upper range. + low and high represent are optional parameters which represent the range + from which the random number must return its result. @type low: float @param low: The lower range. + @type high: float + @param high: The upper range. """ def Intersect(vec1, vec2, vec3, ray, orig, clip=1): diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c index b6411522179..d2d1b581ae8 100644 --- a/source/blender/radiosity/intern/source/radfactors.c +++ b/source/blender/radiosity/intern/source/radfactors.c @@ -744,11 +744,9 @@ void subdivideshootElements(int it) } } if(rn) { - min[0]= min[1]= min[2]= 1.0e10; - max[0]= max[1]= max[2]= -1.0e10; + INIT_MINMAX(min, max); /* errmin and max are the filtered colors */ - errmin[0]= errmin[1]= errmin[2]= 1.0e10; - errmax[0]= errmax[1]= errmax[2]= -1.0e10; + INIT_MINMAX(errmin, errmax); minmaxradelemfilt(rp->first, min, max, errmin, errmax); /* if small difference between colors: no subdiv */ diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 5b81052f5d2..8971126e643 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -133,6 +133,7 @@ typedef struct ShadeInput float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[4], rad[3]; float refcol[4], displace[3]; float strand, tang[3], stress, winspeed[4]; + float duplilo[3], dupliuv[3]; ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */ ShadeInputCol col[8]; /* 8 = MAX_MCOL */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 7fbbd0f5abc..9034ff79243 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -266,6 +266,8 @@ typedef struct ObjectInstanceRen { float mat[4][4], imat[3][3]; short flag; + float dupliorco[3], dupliuv[2]; + float *vectors; int totvector; } ObjectInstanceRen; @@ -343,7 +345,7 @@ typedef struct StrandBuffer { unsigned int lay; int overrideuv; int flag, maxdepth; - float adaptcos, minwidth; + float adaptcos, minwidth, widthfade; float winmat[4][4]; int winx, winy; diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h index c919a54008e..a3a3b4e5e4a 100644 --- a/source/blender/render/intern/include/renderdatabase.h +++ b/source/blender/render/intern/include/renderdatabase.h @@ -94,7 +94,7 @@ struct HaloRen *RE_inithalo_particle(struct Render *re, struct ObjectRen *obr, s struct StrandBuffer *RE_addStrandBuffer(struct ObjectRen *obr, int totvert); struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int psysindex); -void RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4]); +struct ObjectInstanceRen *RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4]); void RE_makeRenderInstances(struct Render *re); void RE_instanceTransformNormal(struct ObjectInstanceRen *obi, float *nor, float *tnor); diff --git a/source/blender/render/intern/include/strand.h b/source/blender/render/intern/include/strand.h index f2f1c2763c0..f1c0b6d1e3a 100644 --- a/source/blender/render/intern/include/strand.h +++ b/source/blender/render/intern/include/strand.h @@ -86,7 +86,7 @@ typedef struct StrandSegment { } StrandSegment; void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint); -void render_strand_segment(struct Render *re, float winmat[][4], struct StrandPart *spart, struct ZSpan *zspan, StrandSegment *sseg); +void render_strand_segment(struct Render *re, float winmat[][4], struct StrandPart *spart, struct ZSpan *zspan, int totzspan, StrandSegment *sseg); void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *), int do_pano, int do_buckets); struct RenderBuckets *init_buckets(struct Render *re); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 56e7265b69e..1e391508228 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1496,11 +1496,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time; float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); - float adapt_angle=0.0, adapt_pix=0.0, random; - float simplify[2]; + float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2]; int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0; int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; - int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}; + int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num; char **uv_name=0; /* 1. check that everything is ok & updated */ @@ -1644,6 +1643,13 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem strandbuf->overrideuv= override_uv; strandbuf->minwidth= ma->strand_min; + if(ma->strand_widthfade == 0.0f) + strandbuf->widthfade= 0.0f; + else if(ma->strand_widthfade >= 1.0f) + strandbuf->widthfade= 2.0f - ma->strand_widthfade; + else + strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f); + if(part->flag & PART_HAIR_BSPLINE) strandbuf->flag |= R_STRAND_BSPLINE; if(ma->mode & MA_STR_B_UNITS) @@ -1700,13 +1706,25 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem if(uvco && ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)){ layer=psmd->dm->faceData.layers + CustomData_get_layer_index(&psmd->dm->faceData,CD_MFACE); - for(i=0; idm->getFaceData(psmd->dm,pa->num,CD_MFACE); - mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i); - mtface+=pa->num; - - psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*i); + num= pa->num_dmcache; + + if(num == DMCACHE_NOTFOUND) + if(pa->num < psmd->dm->getNumFaces(psmd->dm)) + num= pa->num; + + for(i=0; idm->getFaceData(psmd->dm,num,CD_MFACE); + mtface=(MTFace*)CustomData_get_layer_n(&psmd->dm->faceData,CD_MTFACE,i); + mtface+=num; + + psys_interpolate_uvs(mtface,mface->v4,pa->fuv,uvco+2*i); + } + else { + uvco[2*i]= 0.0f; + uvco[2*i + 1]= 0.0f; + } } } @@ -2130,8 +2148,16 @@ static void displace_render_face(Render *re, VlakRen *vlr, float *scale) { ShadeInput shi; + /* Warning, This is not that nice, and possibly a bit slow, + however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ + memset(&shi, 0, sizeof(ShadeInput)); + /* end warning! - Campbell */ + /* set up shadeinput struct for multitex() */ - shi.osatex= 0; /* signal not to use dx[] and dy[] texture AA vectors */ + + /* memset above means we dont need this */ + /*shi.osatex= 0;*/ /* signal not to use dx[] and dy[] texture AA vectors */ + shi.vlr= vlr; /* current render face */ shi.mat= vlr->mat; /* current input material */ @@ -4072,10 +4098,44 @@ static int allow_render_dupli_instance(Render *re, DupliObject *dob, Object *obd !(re->r.mode & R_RADIO)); } +static void dupli_render_particle_set(Render *re, Object *ob, int level, int enable) +{ + /* ugly function, but we need to set particle systems to their render + * settings before calling object_duplilist, to get render level duplis */ + Group *group; + GroupObject *go; + ParticleSystem *psys; + + if(level >= MAX_DUPLI_RECUR) + return; + + if(ob->transflag & OB_DUPLIPARTS) { + DerivedMesh *dm; + + for(psys=ob->particlesystem.first; psys; psys=psys->next) + if(enable) + psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy); + else + psys_render_restore(ob, psys); + + if(enable) { + dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); + dm->release(dm); + } + } + + if(ob->dup_group==NULL) return; + group= ob->dup_group; + + for(go= group->gobject.first; go; go= go->next) + dupli_render_particle_set(re, go->ob, level+1, enable); +} + static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int only_verts) { Base *base; Object *ob; + ObjectInstanceRen *obi; Scene *sce; float mat[4][4], obmat[4][4]; @@ -4106,7 +4166,10 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int DupliObject *dob; ListBase *lb; + dupli_render_particle_set(re, ob, 0, 1); lb= object_duplilist(sce, ob); + dupli_render_particle_set(re, ob, 0, 0); + for(dob= lb->first; dob; dob= dob->next) { Object *obd= dob->ob; @@ -4136,11 +4199,18 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int Mat4Invert(imat, obmat); MTC_Mat4MulSerie(mat, re->viewmat, dob->mat, imat, re->viewinv, 0, 0, 0, 0); - RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat); + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat); + VECCOPY(obi->dupliorco, dob->orco); + obi->dupliuv[0]= dob->uv[0]; + obi->dupliuv[1]= dob->uv[1]; psysindex= 1; - for(psys=obd->particlesystem.first; psys; psys=psys->next) + for(psys=obd->particlesystem.first; psys; psys=psys->next) { RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat); + VECCOPY(obi->dupliorco, dob->orco); + obi->dupliuv[0]= dob->uv[0]; + obi->dupliuv[1]= dob->uv[1]; + } obd->flag |= OB_DONE; obd->transflag |= OB_RENDER_DUPLI; diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index b950f54417e..7dc205e2794 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -93,10 +93,10 @@ static void ibuf_get_color(float *col, struct ImBuf *ibuf, int x, int y) else { char *rect = (char *)( ibuf->rect+ ofs); - col[0] = ((float)rect[0])/255.0f; - col[1] = ((float)rect[1])/255.0f; - col[2] = ((float)rect[2])/255.0f; - col[3] = ((float)rect[3])/255.0f; + col[0] = ((float)rect[0])*(1.0f/255.0f); + col[1] = ((float)rect[1])*(1.0f/255.0f); + col[2] = ((float)rect[2])*(1.0f/255.0f); + col[3] = ((float)rect[3])*(1.0f/255.0f); } } diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index cffed99c738..a1088d1a920 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -25,6 +25,7 @@ */ #include +#include #include "BLI_arithb.h" /* External modules: */ @@ -130,6 +131,12 @@ static void render_lighting_halo(HaloRen *har, float *colf) if(lar->mode & LA_TEXTURE) { ShadeInput shi; + + /* Warning, This is not that nice, and possibly a bit slow, + however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ + memset(&shi, 0, sizeof(ShadeInput)); + /* end warning! - Campbell */ + VECCOPY(shi.co, rco); shi.osatex= 0; do_lamp_tex(lar, lv, &shi, lacol); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 69e90a7537c..5038518e71a 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -409,6 +409,11 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo float ref[3], maxsize=RE_ray_tree_max_size(R.raytree); float dist_mir = origshi->mat->dist_mir; + /* Warning, This is not that nice, and possibly a bit slow for every ray, + however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ + memset(&shi, 0, sizeof(ShadeInput)); + /* end warning! - Campbell */ + VECCOPY(isec.start, start); if (dist_mir > 0.0) { isec.end[0]= start[0]+dist_mir*vec[0]; @@ -430,13 +435,13 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo shi.osatex= origshi->osatex; shi.depth= 1; /* only used to indicate tracing */ shi.thread= origshi->thread; - shi.sample= 0; + //shi.sample= 0; // memset above, so dont need this shi.xs= origshi->xs; shi.ys= origshi->ys; shi.lay= origshi->lay; shi.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */ shi.combinedflag= 0xFFFFFF; /* ray trace does all options */ - shi.do_preview= 0; + //shi.do_preview= 0; // memset above, so dont need this shi.light_override= origshi->light_override; shi.mat_override= origshi->mat_override; @@ -1231,16 +1236,22 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) float d= 1.0f; /* we got a face */ + /* Warning, This is not that nice, and possibly a bit slow for every ray, + however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ + memset(&shi, 0, sizeof(ShadeInput)); + /* end warning! - Campbell */ + shi.depth= 1; /* only used to indicate tracing */ shi.mask= 1; - shi.osatex= 0; + + /*shi.osatex= 0; shi.thread= shi.sample= 0; shi.lay= 0; shi.passflag= 0; shi.combinedflag= 0; shi.do_preview= 0; shi.light_override= NULL; - shi.mat_override= NULL; + shi.mat_override= NULL;*/ shade_ray(is, &shi, &shr); if (traflag & RAY_TRA) @@ -1300,6 +1311,12 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) if(RE_ray_tree_intersect(R.raytree, &isec)) { float fac; + + /* Warning, This is not that nice, and possibly a bit slow for every ray, + however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ + memset(&shi, 0, sizeof(ShadeInput)); + /* end warning! - Campbell */ + shade_ray(&isec, &shi, &shr_t); fac= isec.labda*isec.labda; fac= 1.0f; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 3eda349eef9..e2f331afafd 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -296,7 +296,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) long *rd= pa->rectdaps; int x, y, *rz= pa->rectz; - shade_input_initialize(&shi, pa, rl, 0); + shade_input_initialize(&shi, pa, rl, 0); /* this zero's ShadeInput for us */ for(y=pa->disprect.ymin; ydisprect.ymax; y++) { for(x=pa->disprect.xmin; xdisprect.xmax; x++, rz++, pass+=4) { diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 059a72507c5..b9dfd0ab266 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -688,11 +688,6 @@ ObjectRen *RE_addRenderObject(Render *re, Object *ob, Object *par, int index, in obr->index= index; obr->psysindex= psysindex; - if(!re->objecthash) - re->objecthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - if(!BLI_ghash_lookup(re->objecthash, ob)) - BLI_ghash_insert(re->objecthash, ob, obr); - return obr; } @@ -823,11 +818,6 @@ void free_renderdata_tables(Render *re) re->instancetable.first= re->instancetable.last= NULL; } - if(re->objecthash) { - BLI_ghash_free(re->objecthash, NULL, NULL); - re->objecthash= NULL; - } - if(re->sortedhalos) { MEM_freeN(re->sortedhalos); re->sortedhalos= NULL; @@ -1261,7 +1251,7 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], /* ------------------------------------------------------------------------- */ -void RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4]) +ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[][4]) { ObjectInstanceRen *obi; float mat3[3][3]; @@ -1281,11 +1271,38 @@ void RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, i } BLI_addtail(&re->instancetable, obi); + + return obi; +} + +void find_dupli_objectren(Render *re, ObjectInstanceRen *obi, ObjectInstanceRen *lastobi) +{ + ObjectRen *obr; + + /* see if last object did the same lookup, so we can just reuse result */ + if(lastobi && obi->ob == lastobi->ob && obi->par == lastobi->par && obi->psysindex == lastobi->psysindex) { + obi->obr= lastobi->obr; + return; + } + + /* dupli objects are created after object instances, so we look through + * object list to find it */ + obr= re->objecttable.first; + while(obr && (obr->ob != obi->ob || obr->par != obi->par || obr->psysindex != obi->psysindex)) + obr= obr->next; + + if(!obr) { + obr= re->objecttable.first; + while(obr && (obr->ob != obi->ob || obr->psysindex != obi->psysindex) && obr->par == NULL) + obr= obr->next; + } + + obi->obr= obr; } void RE_makeRenderInstances(Render *re) { - ObjectInstanceRen *obi, *oldobi; + ObjectInstanceRen *obi, *oldobi, *lastobi= NULL; ListBase newlist; int tot; @@ -1300,12 +1317,8 @@ void RE_makeRenderInstances(Render *re) *obi= *oldobi; if(!obi->obr) { - /* dupli objects are created after object instances, so they were - * stored in a object -> objectren hash, we do lookup of the actual - * pointer here */ - if(re->objecthash && (obi->obr=BLI_ghash_lookup(re->objecthash, obi->ob))) - while(obi->obr && obi->obr->psysindex != obi->psysindex) - obi->obr= obi->obr->next; + find_dupli_objectren(re, obi, lastobi); + lastobi= obi; } if(obi->obr) { @@ -1317,10 +1330,6 @@ void RE_makeRenderInstances(Render *re) re->totinstance--; } - if(re->objecthash) { - BLI_ghash_free(re->objecthash, NULL, NULL); - re->objecthash= NULL; - } BLI_freelistN(&re->instancetable); re->instancetable= newlist; } diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index f937218cdb6..d862729317b 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -919,6 +919,8 @@ void shade_input_set_shade_texco(ShadeInput *shi) shi->dylo[2]= dl*o3[2]-shi->dy_u*o1[2]-shi->dy_v*o2[2]; } } + + VECCOPY(shi->duplilo, obi->dupliorco); } if(texco & TEXCO_GLOB) { @@ -1033,6 +1035,10 @@ void shade_input_set_shade_texco(ShadeInput *shi) } } + shi->dupliuv[0]= -1.0f + 2.0f*obi->dupliuv[0]; + shi->dupliuv[1]= -1.0f + 2.0f*obi->dupliuv[1]; + shi->dupliuv[2]= 0.0f; + if(shi->totuv == 0) { ShadeInputUV *suv= &shi->uv[0]; @@ -1181,7 +1187,9 @@ void shade_input_set_shade_texco(ShadeInput *shi) } } } - } + } /* else { + Note! For raytracing winco is not set, important because thus means all shader input's need to have their variables set to zero else in-initialized values are used + */ } /* ****************** ShadeSample ************************************** */ diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index adaf2ae3259..3ad9bb66559 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -436,7 +436,7 @@ typedef struct StrandPart { GHash *hash; StrandPoint point1, point2; ShadeSample ssamp1, ssamp2, ssamp; - float t[3]; + float t[3], s[3]; } StrandPart; typedef struct StrandSortSegment { @@ -520,6 +520,23 @@ static void add_strand_obindex(RenderLayer *rl, int offset, ObjectRen *obr) } } +static void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha) +{ + if(alpha < 1.0f) { + shr->combined[0] *= alpha; + shr->combined[1] *= alpha; + shr->combined[2] *= alpha; + shr->combined[3] *= alpha; + + shr->col[0] *= alpha; + shr->col[1] *= alpha; + shr->col[2] *= alpha; + shr->col[3] *= alpha; + + shr->alpha *= alpha; + } +} + static void do_strand_point_project(float winmat[][4], ZSpan *zspan, float *co, float *hoco, float *zco) { projectvert(co, winmat, hoco); @@ -537,7 +554,6 @@ static void strand_project_point(float winmat[][4], float winx, float winy, Stra spoint->y= spoint->hoco[1]*div*winy*0.5f; } -#include "BLI_rand.h" static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint); static void strand_shade_get(StrandPart *spart, int lookup, ShadeSample *ssamp, StrandPoint *spoint, StrandVert *svert, StrandSegment *sseg) @@ -576,22 +592,6 @@ static void strand_shade_segment(StrandPart *spart) strand_shade_get(spart, !last, &spart->ssamp2, &sseg->point2, sseg->v[2], sseg); sseg->shaded= 1; } - -#if 0 - float c[3]; - - c[0]= BLI_frand(); - c[1]= BLI_frand(); - c[2]= BLI_frand(); - - spart->ssamp1.shr[0].combined[0] *= c[0]; - spart->ssamp1.shr[0].combined[1] *= c[1]; - spart->ssamp1.shr[0].combined[2] *= c[2]; - - spart->ssamp2.shr[0].combined[0] *= c[0]; - spart->ssamp2.shr[0].combined[1] *= c[1]; - spart->ssamp2.shr[0].combined[2] *= c[2]; -#endif } static void do_strand_blend(void *handle, int x, int y, float u, float v, float z) @@ -599,7 +599,7 @@ static void do_strand_blend(void *handle, int x, int y, float u, float v, float StrandPart *spart= (StrandPart*)handle; StrandBuffer *buffer= spart->segment->buffer; ShadeResult *shr; - float /**pass,*/ t; + float /**pass,*/ t, s; int offset, zverg; /* check again solid z-buffer */ @@ -625,6 +625,14 @@ static void do_strand_blend(void *handle, int x, int y, float u, float v, float interpolate_shade_result(spart->ssamp1.shr, spart->ssamp2.shr, t, spart->ssamp.shr, spart->addpassflag); + /* alpha along width */ + if(buffer->widthfade != 0.0f) { + s = fabs(u*spart->s[0] + v*spart->s[1] + (1.0f-u-v)*spart->s[2]); + s = 1.0f - pow(s, buffer->widthfade); + + strand_apply_shaderesult_alpha(spart->ssamp.shr, s); + } + /* add in shaderesult array for part */ spart->ssamp.shi[0].mask= (1<sample); addtosamp_shr(shr, &spart->ssamp, spart->addpassflag); @@ -696,19 +704,7 @@ static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *ss shade_input_do_shade(shi, shr); /* apply simplification */ - if(spoint->alpha < 1.0f) { - shr->combined[0] *= spoint->alpha; - shr->combined[1] *= spoint->alpha; - shr->combined[2] *= spoint->alpha; - shr->combined[3] *= spoint->alpha; - - shr->col[0] *= spoint->alpha; - shr->col[1] *= spoint->alpha; - shr->col[2] *= spoint->alpha; - shr->col[3] *= spoint->alpha; - - shr->alpha *= spoint->alpha; - } + strand_apply_shaderesult_alpha(shr, spoint->alpha); /* include lamphalos for strand, since halo layer was added already */ if(re->flag & R_LAMPHALO) @@ -747,16 +743,22 @@ static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, f spart->sample= sample; spart->t[0]= t-dt; + spart->s[0]= -1.0f; spart->t[1]= t-dt; + spart->s[1]= 1.0f; spart->t[2]= t; + spart->s[2]= 1.0f; zspan_scanconvert_strand(zspan, spart, jco1, jco2, jco3, do_strand_blend); spart->t[0]= t-dt; + spart->s[0]= -1.0f; spart->t[1]= t; + spart->s[1]= 1.0f; spart->t[2]= t; + spart->s[2]= -1.0f; zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_blend); } -static void strand_render(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandPoint *p1, StrandPoint *p2) +static void strand_render(Render *re, StrandSegment *sseg, float winmat[][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandPoint *p1, StrandPoint *p2) { if(spart) { float t= p2->t; @@ -772,17 +774,27 @@ static void strand_render(Render *re, float winmat[][4], StrandPart *spart, ZSpa } else { float hoco1[4], hoco2[3]; + int a, obi, index; + + obi= sseg->obi - re->objectinstance; + index= sseg->strand->index; - projectvert(p1->co, winmat, hoco1); - projectvert(p2->co, winmat, hoco2); - - /* render both strand and single pixel wire to counter aliasing */ - zbufclip4(zspan, 0, 0, p1->hoco2, p1->hoco1, p2->hoco1, p2->hoco2, p1->clip2, p1->clip1, p2->clip1, p2->clip2); - zbufsinglewire(zspan, 0, 0, hoco1, hoco2); + projectvert(p1->co, winmat, hoco1); + projectvert(p2->co, winmat, hoco2); + + for(a=0; ahoco2, p1->hoco1, p2->hoco1, p2->hoco2, p1->clip2, p1->clip1, p2->clip1, p2->clip2); +#endif + /* only render a line for now, which makes the shadow map more + similiar across frames, and so reduces flicker */ + zbufsinglewire(&zspan[a], obi, index, hoco1, hoco2); + } } } - -static int strand_segment_recursive(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth) + +static int strand_segment_recursive(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandSegment *sseg, StrandPoint *p1, StrandPoint *p2, int depth) { StrandPoint p; StrandBuffer *buffer= sseg->buffer; @@ -815,21 +827,23 @@ static int strand_segment_recursive(Render *re, float winmat[][4], StrandPart *s do_strand_point_project(winmat, zspan, p.co2, p.hoco2, p.zco2); } else { +#if 0 projectvert(p.co1, winmat, p.hoco1); projectvert(p.co2, winmat, p.hoco2); p.clip1= testclip(p.hoco1); p.clip2= testclip(p.hoco2); +#endif } - if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, p1, &p, depth+1)) - strand_render(re, winmat, spart, zspan, p1, &p); - if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, &p, p2, depth+1)) - strand_render(re, winmat, spart, zspan, &p, p2); + if(!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, p1, &p, depth+1)) + strand_render(re, sseg, winmat, spart, zspan, totzspan, p1, &p); + if(!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, &p, p2, depth+1)) + strand_render(re, sseg, winmat, spart, zspan, totzspan, &p, p2); return 1; } -void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, StrandSegment *sseg) +void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandSegment *sseg) { StrandBuffer *buffer= sseg->buffer; StrandPoint *p1= &sseg->point1; @@ -850,6 +864,7 @@ void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSp do_strand_point_project(winmat, zspan, p2->co2, p2->hoco2, p2->zco2); } else { +#if 0 projectvert(p1->co1, winmat, p1->hoco1); projectvert(p1->co2, winmat, p1->hoco2); projectvert(p2->co1, winmat, p2->hoco1); @@ -858,10 +873,11 @@ void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSp p1->clip2= testclip(p1->hoco2); p2->clip1= testclip(p2->hoco1); p2->clip2= testclip(p2->hoco2); +#endif } - if(!strand_segment_recursive(re, winmat, spart, zspan, sseg, p1, p2, 0)) - strand_render(re, winmat, spart, zspan, p1, p2); + if(!strand_segment_recursive(re, winmat, spart, zspan, totzspan, sseg, p1, p2, 0)) + strand_render(re, sseg, winmat, spart, zspan, totzspan, p1, p2); } static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, StrandPart *spart, float *pass) @@ -1126,7 +1142,7 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r spart.segment= &sseg; - render_strand_segment(re, winmat, &spart, &zspan, &sseg); + render_strand_segment(re, winmat, &spart, &zspan, 1, &sseg); } } diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 0c0fd6edbd2..a4182637f02 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -53,6 +53,7 @@ #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_library.h" #include "BKE_image.h" @@ -1255,7 +1256,7 @@ void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg in[1]= (fact*tex[1] + facm*out[1]); in[2]= (fact*tex[2] + facm*out[2]); break; - + case MTEX_MUL: fact*= facg; facm= 1.0-facg; @@ -1343,9 +1344,28 @@ void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg col= fact*tex[2]; if(col > out[2]) in[2]= col; else in[2]= out[2]; break; + + case MTEX_BLEND_HUE: + fact*= facg; + VECCOPY(in, out); + ramp_blend(MA_RAMP_HUE, in, in+1, in+2, fact, tex); + break; + case MTEX_BLEND_SAT: + fact*= facg; + VECCOPY(in, out); + ramp_blend(MA_RAMP_SAT, in, in+1, in+2, fact, tex); + break; + case MTEX_BLEND_VAL: + fact*= facg; + VECCOPY(in, out); + ramp_blend(MA_RAMP_VAL, in, in+1, in+2, fact, tex); + break; + case MTEX_BLEND_COLOR: + fact*= facg; + VECCOPY(in, out); + ramp_blend(MA_RAMP_COLOR, in, in+1, in+2, fact, tex); + break; } - - } float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip) @@ -1427,7 +1447,14 @@ void do_material_tex(ShadeInput *shi) /* which coords */ if(mtex->texco==TEXCO_ORCO) { - co= shi->lo; dx= shi->dxlo; dy= shi->dylo; + if(mtex->texflag & MTEX_DUPLI_MAPTO) { + co= shi->duplilo; dx= dxt; dy= dyt; + dxt[0]= dxt[1]= dxt[2]= 0.0f; + dyt[0]= dyt[1]= dyt[2]= 0.0f; + } + else { + co= shi->lo; dx= shi->dxlo; dy= shi->dylo; + } } else if(mtex->texco==TEXCO_STICKY) { co= shi->sticky; dx= shi->dxsticky; dy= shi->dysticky; @@ -1466,21 +1493,28 @@ void do_material_tex(ShadeInput *shi) co= shi->gl; dx= shi->dxco; dy= shi->dyco; } else if(mtex->texco==TEXCO_UV) { - ShadeInputUV *suv= &shi->uv[shi->actuv]; - int i; + if(mtex->texflag & MTEX_DUPLI_MAPTO) { + co= shi->dupliuv; dx= dxt; dy= dyt; + dxt[0]= dxt[1]= dxt[2]= 0.0f; + dyt[0]= dyt[1]= dyt[2]= 0.0f; + } + else { + ShadeInputUV *suv= &shi->uv[shi->actuv]; + int i; - if(mtex->uvname[0] != 0) { - for(i = 0; i < shi->totuv; i++) { - if(strcmp(shi->uv[i].name, mtex->uvname)==0) { - suv= &shi->uv[i]; - break; + if(mtex->uvname[0] != 0) { + for(i = 0; i < shi->totuv; i++) { + if(strcmp(shi->uv[i].name, mtex->uvname)==0) { + suv= &shi->uv[i]; + break; + } } } - } - co= suv->uv; - dx= suv->dxuv; - dy= suv->dyuv; + co= suv->uv; + dx= suv->dxuv; + dy= suv->dyuv; + } } else if(mtex->texco==TEXCO_WINDOW) { co= shi->winco; dx= shi->dxwin; dy= shi->dywin; diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 57d2bbb3489..98a19c8c0e0 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -546,13 +546,13 @@ static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec apn= ap; while(apn) { /* loop unrolled */ - if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } + if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; } if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; } - if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } + if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; } if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; } - if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } + if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; } if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; } - if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } + if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; } if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; } if(apn->next==0) apn->next= addpsA(zspan); apn= apn->next; @@ -2354,7 +2354,7 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int c4= zbuf_shadow_project(cache, sseg.v[3]-strand->vert, obwinmat, sseg.v[3]->co, ho4); if(!(c1 & c2 & c3 & c4)) - render_strand_segment(NULL, winmat, NULL, &zspan, &sseg); + render_strand_segment(re, winmat, NULL, &zspan, 1, &sseg); } } diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 57c9eab5d70..cfa4937749d 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -3935,9 +3935,10 @@ static void build_bonestring (char *string, EditBone *bone) int skip=0; int index, numbones, i; char (*qsort_ptr)[32] = NULL; + char *s = string; /* That space is there for a reason - for no parent */ - sprintf (string, "Parent%%t| %%x%d", -1); + s += sprintf (string, "Parent%%t| %%x%d", -1); numbones = BLI_countlist(&G.edbo); @@ -3978,7 +3979,7 @@ static void build_bonestring (char *string, EditBone *bone) ( int (*)(const void *, const void *) ) strcmp); for (i=0; i < numbones; ++i) { - sprintf (string, "%s%s", string, qsort_ptr[i]); + strcat(s, qsort_ptr[i]); } if (qsort_ptr) diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index f1b75d075f3..581ff63a987 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -1380,7 +1380,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s int togButWidth = 50; int textButWidth = ((width/2)-togButWidth); - height = 106; + height = 136; uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); @@ -1417,8 +1417,11 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-72, (textButWidth-5), 18, &(data->zmax), 0.0001, 1000, 0.1,0.5,"Highest z value to allow"); uiBlockEndAlign(block); + /* special option(s) */ + uiDefButBitS(block, TOG, LIMIT_TRANSFORM, B_CONSTRAINT_TEST, "For Transform", *xco+(width/4), *yco-100, (width/2), 18, &data->flag2, 0, 24, 0, 0, "Transforms are affected by this constraint as well"); + /* constraint space settings */ - draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner(ob), -1); + draw_constraint_spaceselect(block, con, *xco, *yco-130, is_armature_owner(ob), -1); } break; case CONSTRAINT_TYPE_RIGIDBODYJOINT: @@ -3449,14 +3452,14 @@ static void object_softbodies__enable_psys(void *ob_v, void *psys_v) #ifdef _work_on_sb_solver static char sbsolvers[] = "Solver %t|RKP almost SOFT not usable but for some german teachers %x1|STU ip semi implicit euler%x3|SI1 (half step)adaptive semi implict euler %x2|SI2 (use dv)adaptive semi implict euler %x4|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; #else -static char sbsolvers[] = "STU PID semi implicit euler%x3|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; +static char sbsolvers[] = "SIF semi implicit euler with fixed step size (worth a try with real stiff egdes)%x3|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; #endif static void object_softbodies_II(Object *ob) { SoftBody *sb=ob->soft; uiBlock *block; static int val; - short *softflag=&ob->softflag, psys_cur=0; + short *softflag=&ob->softflag, psys_cur=0,adaptive_mode; int ob_has_hair=psys_ob_has_hair(ob); if(!_can_softbodies_at_all(ob)) return; /*bah that is ugly! creating missing data members in UI code*/ @@ -3541,15 +3544,38 @@ static void object_softbodies_II(Object *ob) uiBlockEndAlign(block); /*SOLVER SETTINGS*/ uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_DIFF, sbsolvers,10,100,50,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver"); - uiDefButF(block, NUM, B_DIFF, "Error Lim:", 60,100,130,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed"); - uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"O", 190,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Old Error Calculation"); - uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 210,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); - uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 300,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); - uiBlockEndAlign(block); - uiDefButS(block, NUM, B_DIFF, "MinS:", 10,80,100,20, &sb->minloops, 0.00, 30000.0, 10, 0, "Minimal # solver steps/frame "); - uiDefButS(block, NUM, B_DIFF, "MaxS:", 110,80,100,20, &sb->maxloops, 0.00, 30000.0, 10, 0, "Maximal # solver steps/frame "); - uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); + uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,100,50,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver"); + /*some have adapive step size - some not*/ + switch (sb->solver_ID) { + case 0: + case 1: + {adaptive_mode = 1; break;} + case 3: + {adaptive_mode = 0; break;} + default: printf("SB_solver?\n"); // should never happen + + } + if(adaptive_mode){ + uiDefButF(block, NUM, B_DIFF, "Error Lim:", 60,100,120,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed"); + uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"O", 180,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Old Error Calculation"); + uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 200,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); + uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 290,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); + uiBlockEndAlign(block); + uiDefButS(block, NUM, B_DIFF, "MinS:", 10,80,100,20, &sb->minloops, 0.00, 30000.0, 10, 0, "Minimal # solver steps/frame "); + uiDefButS(block, NUM, B_DIFF, "MaxS:", 110,80,100,20, &sb->maxloops, 0.00, 30000.0, 10, 0, "Maximal # solver steps/frame "); + uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); + } + else{ + uiBlockEndAlign(block); + uiBlockBeginAlign(block); + uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 210,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); + uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 290,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); + uiBlockEndAlign(block); + uiDefButS(block, NUM, B_DIFF, "Steps:", 10,80,100,20, &sb->minloops, 1.00, 30000.0, 10, 0, "Solver steps/frame "); + uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); + } + + } /* OTHER OBJECTS COLLISION STUFF */ if (ob->type==OB_MESH){ @@ -3734,7 +3760,8 @@ static void object_softbodies(Object *ob) uiDefButF(block, NUM, B_DIFF, "E Pull:", 10,30,100,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness"); uiDefButF(block, NUM, B_DIFF, "E Push:", 110,30,100,20, &sb->inpush, 0.0, 0.999, 10, 0, "Edge spring stiffness"); uiDefButF(block, NUM, B_DIFF, "E Damp:", 210,30,100,20, &sb->infrict, 0.0, 50.0, 10, 0, "Edge spring friction"); - uiDefButS(block, NUM, B_DIFF, "Aero:", 10,10,100,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'"); + uiDefButBitS(block, TOG,OB_SB_AERO_ANGLE,B_SOFTBODY_CHANGE, "N",10,10,20,20, softflag, 0, 0, 0, 0, "New aero(uses angle and lenght)"); + uiDefButS(block, NUM, B_DIFF, "Aero:", 30,10,80,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'"); if(ob->type==OB_MESH) { uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Bend:", 110,10,100,20, &sb->secondspring, 0.0, 10.0, 10, 0, "Strenght of Springs over 2 Edges"); if (*softflag & OB_SB_QUADS){ @@ -4366,7 +4393,7 @@ static void object_panel_particle_system(Object *ob) short butx=0, buty=160, butw=150, buth=20; char str[30]; static short partact; - short totpart; + short totpart, lock; block= uiNewBlock(&curarea->uiblocks, "object_panel_particle_system", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Particle System", "Particle", 0, 0, 318, 204)==0) return; @@ -4426,9 +4453,9 @@ static void object_panel_particle_system(Object *ob) uiBlockEndAlign(block); } - if(psys->flag & PSYS_EDITED || psys->flag & PSYS_PROTECT_CACHE) { + lock= (psys->flag & PSYS_EDITED || psys->flag & PSYS_PROTECT_CACHE); + if(lock) uiSetButLock(1, "Hair is edited or cache is protected!"); - } uiDefButS(block, MENU, B_PARTTYPE, "Type%t|Hair%x2|Reactor%x1|Emitter%x0", 210,buty,100,buth, &part->type, 14.0, 0.0, 0, 0, "Type of particle system"); @@ -4474,15 +4501,20 @@ static void object_panel_particle_system(Object *ob) uiDefBut(block, LABEL, 0, "Emit From:", butx,buty,butw,buth, NULL, 0.0, 0, 0, 0, ""); uiBlockBeginAlign(block); + + if(lock) uiClearButLock(); uiDefButBitI(block, TOG, PART_TRAND, B_PART_DISTR, "Random", butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Emit in random order of elements"); - + if(lock) uiSetButLock(1, "Hair is edited or cache is protected!"); + if(part->type==PART_REACTOR) uiDefButS(block, MENU, B_PART_DISTR, "Particle %x3|Volume %x2|Faces %x1|Verts %x0", butx+butw/2,buty,butw/2,buth, &part->from, 14.0, 0.0, 0, 0, "Where to emit particles from"); else uiDefButS(block, MENU, B_PART_DISTR, "Volume %x2|Faces %x1|Verts%x0", butx+butw/2,buty,butw/2,buth, &part->from, 14.0, 0.0, 0, 0, "Where to emit particles from"); if(ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)) { + if(lock) uiClearButLock(); uiDefButBitI(block, TOG, PART_EDISTR, B_PART_DISTR, "Even",butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Use even distribution from faces based on face areas or edge lengths"); + if(lock) uiSetButLock(1, "Hair is edited or cache is protected!"); uiDefButS(block, MENU, B_PART_DISTR, "Distribution %t|Grid%x2|Random%x1|Jittered%x0", butx+butw/2,buty,butw/2,buth, &part->distr, 14.0, 0.0, 0, 0, "How to distribute particles on selected element"); if(part->distr==PART_DISTR_JIT) { uiDefButF(block, NUM, B_PART_DISTR, "Amount:", butx,(buty-=buth),butw,buth, &part->jitfac, 0, 2.0, 1, 1, "Amount of jitter applied to the sampling"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 6d846e69308..4eef6b29599 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -142,6 +142,11 @@ static char *mapto_blendtype_pup(void) str += sprintf(str, formatstr, "Darken", MTEX_DARK); str += sprintf(str, formatstr, "Lighten", MTEX_LIGHT); + str += sprintf(str, formatstr, "Hue", MTEX_BLEND_HUE); + str += sprintf(str, formatstr, "Saturation", MTEX_BLEND_SAT); + str += sprintf(str, formatstr, "Value", MTEX_BLEND_VAL); + str += sprintf(str, formatstr, "Color", MTEX_BLEND_COLOR); + return string; } @@ -3299,7 +3304,7 @@ static void material_panel_map_input(Object *ob, Material *ma) uiBlockBeginAlign(block); uiDefButS(block, ROW, B_MATPRV, "Glob", 630,180,45,18, &(mtex->texco), 4.0, (float)TEXCO_GLOB, 0, 0, "Uses global coordinates for the texture coordinates"); uiDefButS(block, ROW, B_MATPRV, "Object", 675,180,75,18, &(mtex->texco), 4.0, (float)TEXCO_OBJECT, 0, 0, "Uses linked object's coordinates for texture coordinates"); - if(mtex->texco == TEXCO_UV) { + if(mtex->texco == TEXCO_UV && !(mtex->texflag & MTEX_DUPLI_MAPTO)) { if(!verify_valid_uv_name(mtex->uvname)) uiBlockSetCol(block, TH_REDALERT); but=uiDefBut(block, TEX, B_MATPRV, "UV:", 750,180,158,18, mtex->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer"); @@ -3321,6 +3326,10 @@ static void material_panel_map_input(Object *ob, Material *ma) uiDefButS(block, ROW, B_MATPRV, "Stress", 630,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_STRESS, 0, 0, "Uses the difference of edge lengths compared to original coordinates of the mesh"); uiDefButS(block, ROW, B_MATPRV, "Tangent", 700,140,70,18, &(mtex->texco), 4.0, (float)TEXCO_TANGENT, 0, 0, "Uses the optional tangent vector as texture coordinates"); + uiBlockEndAlign(block); + + if(ELEM(mtex->texco, TEXCO_UV, TEXCO_ORCO)) + uiDefButBitS(block, TOG, MTEX_DUPLI_MAPTO, B_MATPRV, "From Dupli", 820,140,88,18, &(mtex->texflag), 0, 0, 0, 0, "If object is duplicated by vertices, faces or particles, inherit texture coordinate from parent object"); /* COORDS */ uiBlockBeginAlign(block); @@ -3855,7 +3864,7 @@ static uiBlock *strand_menu(void *mat_v) { Material *ma= mat_v; uiBlock *block; - int buth=20, butw=230, butx=10, buty=160; + int buth=20, butw=230, butx=10, buty=180; block= uiNewBlock(&curarea->uiblocks, "strand menu", UI_EMBOSS, UI_HELV, curarea->win); @@ -3885,6 +3894,7 @@ static uiBlock *strand_menu(void *mat_v) uiDefButF(block, NUMSLI, 0, "End ", butx,buty-=buth, butw,buth, &ma->strand_end, 0.25, 10.0, 2, 0, "End size of strands in pixels"); } uiDefButF(block, NUMSLI, 0, "Shape ", butx,buty-=buth, butw,buth, &ma->strand_ease, -0.9, 0.9, 2, 0, "Shape of strands, positive value makes it rounder, negative makes it spiky"); + uiDefButF(block, NUMSLI, 0, "Width Fade ", butx,buty-=buth, butw,buth, &ma->strand_widthfade, 0.0, 2.0, 2, 0, "Transparency along the width of the strand"); uiDefBut(block, TEX, B_MATPRV, "UV:", butx,buty-=buth,butw,buth, ma->strand_uvname, 0, 31, 0, 0, "Set name of UV layer to override"); uiBlockSetDirection(block, UI_TOP); diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c index 961cad5f840..cca13671017 100644 --- a/source/blender/src/drawnode.c +++ b/source/blender/src/drawnode.c @@ -348,7 +348,7 @@ static int node_buts_time(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *b if(cumap) cumap->flag |= CUMA_DRAW_CFRA; if(node->custom1custom2) - cumap->black[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1); + cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1); uiBlockBeginAlign(block); uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Sta:", @@ -380,9 +380,23 @@ static int node_buts_curvevec(uiBlock *block, bNodeTree *ntree, bNode *node, rct return (int)(node->width-NODE_DY); } +static float *_sample_col= NULL; // bad bad, 2.5 will do better? +void node_curvemap_sample(float *col) +{ + _sample_col= col; +} + static int node_buts_curvecol(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) { if(block) { + CurveMapping *cumap= node->storage; + if(_sample_col) { + cumap->flag |= CUMA_DRAW_SAMPLE; + VECCOPY(cumap->sample, _sample_col); + } + else + cumap->flag &= ~CUMA_DRAW_SAMPLE; + curvemap_buttons(block, node->storage, 'c', B_NODE_EXEC+node->nr, B_REDR, butr); } return (int)(node->width-NODE_DY); @@ -2112,7 +2126,40 @@ static void draw_nodespace_grid(SpaceNode *snode) glEnd(); } -static void draw_nodespace_back(ScrArea *sa, SpaceNode *snode) +static void draw_nodespace_back_pix(ScrArea *sa, SpaceNode *snode) +{ + + draw_nodespace_grid(snode); + + if(snode->flag & SNODE_BACKDRAW) { + Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + if(ibuf) { + int x, y; + /* somehow the offset has to be calculated inverse */ + + glaDefine2DArea(&sa->winrct); + /* ortho at pixel level curarea */ + myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375); + + x = (sa->winx-ibuf->x)/2 + snode->xof; + y = (sa->winx-ibuf->y)/2 + snode->yof; + + if(ibuf->rect) + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + else if(ibuf->channels==4) + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float); + + /* sort this out, this should not be needed */ + myortho2(snode->v2d.cur.xmin, snode->v2d.cur.xmax, snode->v2d.cur.ymin, snode->v2d.cur.ymax); + bwin_clear_viewmat(sa->win); /* clear buttons view */ + glLoadIdentity(); + } + } +} + +/* note: needs to be userpref or opengl profile option */ +static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) { draw_nodespace_grid(snode); @@ -3062,7 +3109,7 @@ void drawnodespace(ScrArea *sa, void *spacedata) snode->curfont= uiSetCurFont_ext(snode->aspect); /* backdrop */ - draw_nodespace_back(sa, snode); + draw_nodespace_back_pix(sa, snode); /* nodes */ snode_set_context(snode); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 1016de5c603..fd23761c82c 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2228,9 +2228,79 @@ void do_viewbuts(unsigned short event) allqueue(REDRAWVIEW3D, 1); } break; + case B_TRANSFORMSPACEADD: + BIF_manageTransformOrientation(1, 0); + allqueue(REDRAWVIEW3D, 1); + break; + case B_TRANSFORMSPACECLEAR: + BIF_clearTransformOrientation(); + allqueue(REDRAWVIEW3D, 1); } } +void removeTransformOrientation_func(void *target, void *unused) +{ + BIF_removeTransformOrientation((TransformOrientation *) target); +} + +void selectTransformOrientation_func(void *target, void *unused) +{ + BIF_selectTransformOrientation((TransformOrientation *) target); +} + +static void view3d_panel_transform_spaces(short cntrl) +{ + ListBase *transform_spaces = &G.scene->transform_spaces; + TransformOrientation *ts = transform_spaces->first; + uiBlock *block; + uiBut *but; + int xco = 20, yco = 70, height = 140; + int index; + + block= uiNewBlock(&curarea->uiblocks, "view3d_panel_transform", UI_EMBOSS, UI_HELV, curarea->win); + uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); + uiSetPanelHandler(VIEW3D_HANDLER_TRANSFORM); // for close and esc + + if(uiNewPanel(curarea, block, "Transform Orientations", "View3d", 10, 230, 318, height)==0) return; + + uiNewPanelHeight(block, height); + + uiBlockBeginAlign(block); + + if (G.obedit) + uiDefBut(block, BUT, B_TRANSFORMSPACEADD, "Add", xco,120,80,20, 0, 0, 0, 0, 0, "Add the selected element as a Transform Orientation"); + else + uiDefBut(block, BUT, B_TRANSFORMSPACEADD, "Add", xco,120,80,20, 0, 0, 0, 0, 0, "Add the active object as a Transform Orientation"); + + uiDefBut(block, BUT, B_TRANSFORMSPACECLEAR, "Clear", xco + 80,120,80,20, 0, 0, 0, 0, 0, "Removal all Transform Orientations"); + + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + + uiDefButS(block, ROW, REDRAWHEADERS, "Global", xco, 90, 40,20, &G.vd->twmode, 5.0, (float)V3D_MANIP_GLOBAL,0, 0, "Global Transform Orientation"); + uiDefButS(block, ROW, REDRAWHEADERS, "Local", xco + 40, 90, 40,20, &G.vd->twmode, 5.0, (float)V3D_MANIP_LOCAL, 0, 0, "Local Transform Orientation"); + uiDefButS(block, ROW, REDRAWHEADERS, "Normal", xco + 80, 90, 40,20, &G.vd->twmode, 5.0, (float)V3D_MANIP_NORMAL,0, 0, "Normal Transform Orientation"); + uiDefButS(block, ROW, REDRAWHEADERS, "View", xco + 120, 90, 40,20, &G.vd->twmode, 5.0, (float)V3D_MANIP_VIEW, 0, 0, "View Transform Orientation"); + + for (index = V3D_MANIP_CUSTOM, ts = transform_spaces->first ; ts ; ts = ts->next, index++) { + + BIF_ThemeColor(TH_BUT_ACTION); + but = uiDefIconButS(block,ROW, REDRAWHEADERS, ICON_RIGHTARROW_THIN, xco,yco,XIC,YIC, &G.vd->twmode, 5.0, (float)index, 0, 0, "Use this Custom Transform Orientation"); + uiButSetFunc(but, selectTransformOrientation_func, ts, NULL); + uiDefBut(block, TEX, 0, "", xco+=XIC, yco,100+XIC,20, &ts->name, 0, 30, 0, 0, "Edits the name of this Transform Orientation"); + but = uiDefIconBut(block, BUT, REDRAWVIEW3D, ICON_X, xco+=100+XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Deletes this Transform Orientation"); + uiButSetFunc(but, removeTransformOrientation_func, ts, NULL); + + xco = 20; + yco -= 25; + } + uiBlockEndAlign(block); + + if(yco < 0) uiNewPanelHeight(block, height-yco); +} + + static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT { uiBlock *block; @@ -2565,6 +2635,9 @@ static void view3d_blockhandlers(ScrArea *sa) case VIEW3D_HANDLER_PREVIEW: view3d_panel_preview(sa, v3d->blockhandler[a+1]); break; + case VIEW3D_HANDLER_TRANSFORM: + view3d_panel_transform_spaces(v3d->blockhandler[a+1]); + break; } /* clear action value for event */ v3d->blockhandler[a+1]= 0; diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index fcd38ef16a7..138f0a438fd 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -952,7 +952,7 @@ static void make_trans_verts(float *min, float *max, int mode) /* I skip it for editmesh now (ton) */ if(G.obedit->type!=OB_MESH) { countall(); - if(mode) tottrans= G.totvert; + if(mode) tottrans= G.totvert; else tottrans= G.totvertsel; if(G.totvertsel==0) { @@ -1915,7 +1915,7 @@ int minmax_verts(float *min, float *max) tottrans=0; if ELEM5(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) - make_trans_verts(bmat[0], bmat[1], 0); + make_trans_verts(bmat[0], bmat[1], 2); if(tottrans==0) return 0; Mat3CpyMat4(bmat, G.obedit->obmat); diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 62ee9563b3f..311f2a653d5 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -2149,6 +2149,7 @@ void selectall_action_keys (short mval[], short mode, short select_mode) allqueue(REDRAWIPO, 0); } +/* Selects all visible keyframes between the specified markers */ void markers_selectkeys_between (void) { ListBase act_data = {NULL, NULL}; @@ -2188,6 +2189,7 @@ void markers_selectkeys_between (void) BLI_freelistN(&act_data); } +/* Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */ void selectkeys_leftright (short leftright, short select_mode) { ListBase act_data = {NULL, NULL}; @@ -2206,12 +2208,12 @@ void selectkeys_leftright (short leftright, short select_mode) data = get_action_context(&datatype); if (data == NULL) return; - if (leftright==1) { + if (leftright == 1) { min = -MAXFRAMEF; - max = (float)CFRA+0.1f; + max = (float)(CFRA + 0.1f); } else { - min = (float)CFRA-0.1f; + min = (float)(CFRA - 0.1f); max = MAXFRAMEF; } @@ -2219,7 +2221,7 @@ void selectkeys_leftright (short leftright, short select_mode) filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); actdata_filter(&act_data, filter, data, datatype); - /* select keys to the right */ + /* select keys on the side where most data occurs */ for (ale= act_data.first; ale; ale= ale->next) { if(NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); @@ -2237,22 +2239,95 @@ void selectkeys_leftright (short leftright, short select_mode) allqueue(REDRAWNLA, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); - } +/* ----------------------------------------- */ + +/* Jumps to the frame where the next/previous keyframe (that is visible) occurs + * dir: indicates direction + */ +void nextprev_action_keyframe (short dir) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + + ListBase elems= {NULL, NULL}; + CfraElem *ce, *nearest=NULL; + float dist, min_dist= 1000000; + + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* abort if no direction */ + if (dir == 0) + return; + + /* get list of keyframes that can be used (in global-time) */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + for (ale= act_data.first; ale; ale= ale->next) { + if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { + actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); + make_cfra_list(ale->key_data, &elems); + actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1); + } + else + make_cfra_list(ale->key_data, &elems); + } + + BLI_freelistN(&act_data); + + /* find nearest keyframe to current frame */ + for (ce= elems.first; ce; ce= ce->next) { + dist= ABS(ce->cfra - CFRA); + + if (dist < min_dist) { + min_dist= dist; + nearest= ce; + } + } + + /* if a nearest keyframe was found, use the one either side */ + if (nearest) { + short changed= 0; + + if ((dir > 0) && (nearest->next)) { + CFRA= nearest->next->cfra; + changed= 1; + } + else if ((dir < 0) && (nearest->prev)) { + CFRA= nearest->prev->cfra; + changed= 1; + } + + if (changed) { + update_for_newframe(); + allqueue(REDRAWALL, 0); + } + } + + /* free temp data */ + BLI_freelistN(&elems); +} /* ----------------------------------------- */ /* This function makes a list of the selected keyframes * in the ipo curves it has been passed */ -static void make_sel_cfra_list(Ipo *ipo, ListBase *elems) +static void make_sel_cfra_list (Ipo *ipo, ListBase *elems) { IpoCurve *icu; if (ipo == NULL) return; - for(icu= ipo->curve.first; icu; icu= icu->next) { + for (icu= ipo->curve.first; icu; icu= icu->next) { BezTriple *bezt; int a= 0; @@ -2266,7 +2341,7 @@ static void make_sel_cfra_list(Ipo *ipo, ListBase *elems) /* This function selects all key frames in the same column(s) as a already selected key(s) * or marker(s), or all the keyframes on a particular frame (triggered by a RMB on x-scrollbar) */ -void column_select_action_keys(int mode) +void column_select_action_keys (int mode) { ListBase elems= {NULL, NULL}; CfraElem *ce; @@ -2329,6 +2404,7 @@ void column_select_action_keys(int mode) BLI_freelistN(&elems); } + /* some quick defines for borderselect modes */ enum { ACTEDIT_BORDERSEL_ALL = 0, @@ -2713,9 +2789,9 @@ void top_sel_action () act = G.saction->action; if (!act) return; - for (achan= act->chanbase.first; achan; achan= achan->next){ + for (achan= act->chanbase.first; achan; achan= achan->next) { if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ + if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { /* take it out off the chain keep data */ BLI_remlink (&act->chanbase, achan); /* make it first element */ @@ -2727,12 +2803,12 @@ void top_sel_action () } } /* clear temp flags */ - for (achan= act->chanbase.first; achan; achan= achan->next){ + for (achan= act->chanbase.first; achan; achan= achan->next) { achan->flag = achan->flag & ~ACHAN_MOVED; } /* Clean up and redraw stuff */ - remake_action_ipos (act); + remake_action_ipos(act); BIF_undo_push("Top Action channel"); allspace(REMAKEIPO, 0); allqueue(REDRAWACTION, 0); @@ -2751,7 +2827,7 @@ void up_sel_action () for (achan=act->chanbase.first; achan; achan= achan->next) { if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ + if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { prev = achan->prev; if (prev) { /* take it out off the chain keep data */ @@ -2766,12 +2842,12 @@ void up_sel_action () } } /* clear temp flags */ - for (achan=act->chanbase.first; achan; achan= achan->next){ + for (achan=act->chanbase.first; achan; achan= achan->next) { achan->flag = achan->flag & ~ACHAN_MOVED; } /* Clean up and redraw stuff */ - remake_action_ipos (act); + remake_action_ipos(act); BIF_undo_push("Up Action channel"); allspace(REMAKEIPO, 0); allqueue(REDRAWACTION, 0); @@ -2790,7 +2866,7 @@ void down_sel_action () for (achan= act->chanbase.last; achan; achan= achan->prev) { if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ + if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { next = achan->next; if (next) next = next->next; if (next) { @@ -2811,12 +2887,12 @@ void down_sel_action () } } /* clear temp flags */ - for (achan= act->chanbase.first; achan; achan= achan->next){ + for (achan= act->chanbase.first; achan; achan= achan->next) { achan->flag = achan->flag & ~ACHAN_MOVED; } /* Clean up and redraw stuff */ - remake_action_ipos (act); + remake_action_ipos(act); BIF_undo_push("Down Action channel"); allspace(REMAKEIPO, 0); allqueue(REDRAWACTION, 0); @@ -2850,7 +2926,7 @@ void bottom_sel_action () } /* Clean up and redraw stuff */ - remake_action_ipos (act); + remake_action_ipos(act); BIF_undo_push("Bottom Action channel"); allspace(REMAKEIPO, 0); allqueue(REDRAWACTION, 0); @@ -2858,6 +2934,84 @@ void bottom_sel_action () allqueue(REDRAWNLA, 0); } + +/* Expand all channels to show full hierachy */ +void expand_all_action (void) +{ + bAction *act; + bActionChannel *achan; + short mode= 0; + + /* Get the selected action, exit if none are selected */ + // TODO: really this should be done with the "action editor api" stuff, but this will suffice for now + act = G.saction->action; + if (act == NULL) return; + + /* check if expand all, or close all */ + for (achan=act->chanbase.first; achan; achan= achan->next) { + if (VISIBLE_ACHAN(achan)) { + if (EXPANDED_ACHAN(achan)) + mode= 1; + break; + } + } + + /* expand/collapse depending on mode */ + for (achan=act->chanbase.first; achan; achan= achan->next) { + if (VISIBLE_ACHAN(achan)) { + if (mode == 1) + achan->flag |= (ACHAN_EXPANDED|ACHAN_SHOWIPO|ACHAN_SHOWCONS); + else + achan->flag &= ~(ACHAN_EXPANDED|ACHAN_SHOWIPO|ACHAN_SHOWCONS); + } + } + + /* Cleanup and do redraws */ + BIF_undo_push("Expand Action Hierachy"); + allqueue(REDRAWACTION, 0); +} + +/* For visible channels, expand/collapse one level */ +void openclose_level_action (short mode) +{ + bAction *act; + bActionChannel *achan; + + /* Get the selected action, exit if none are selected */ + // TODO: really this should be done with the "action editor api" stuff, but this will suffice for now + act = G.saction->action; + if (act == NULL) return; + + /* Abort if no operation required */ + if (mode == 0) return; + + /* Only affect selected channels */ + for (achan=act->chanbase.first; achan; achan= achan->next) { + if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) { + if (EXPANDED_ACHAN(achan)) { + if (FILTER_IPO_ACHAN(achan) || FILTER_CON_ACHAN(achan)) { + if (mode < 0) + achan->flag &= ~(ACHAN_SHOWIPO|ACHAN_SHOWCONS); + } + else { + if (mode > 0) + achan->flag |= (ACHAN_SHOWIPO|ACHAN_SHOWCONS); + else + achan->flag &= ~ACHAN_EXPANDED; + } + } + else { + if (mode > 0) + achan->flag |= ACHAN_EXPANDED; + } + } + } + + /* Cleanup and do redraws */ + BIF_undo_push("Expand/Collapse Action Level"); + allqueue(REDRAWACTION, 0); +} + /* **************************************************** */ /* ACTION MARKERS (PoseLib features) */ /* NOTE: yes, these duplicate code from edittime.c a bit, but these do a bit more... @@ -3243,30 +3397,40 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case PAGEUPKEY: if (datatype == ACTCONT_ACTION) { - if(G.qual & LR_SHIFTKEY) + if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) top_sel_action(); - else if (G.qual & LR_CTRLKEY) + else if (G.qual == LR_SHIFTKEY) up_sel_action(); + else if (G.qual == LR_CTRLKEY) + nextprev_action_keyframe(1); else nextprev_marker(1); } else if (datatype == ACTCONT_SHAPEKEY) { /* only jump to markers possible (key channels can't be moved yet) */ - nextprev_marker(1); + if (G.qual == LR_CTRLKEY) + nextprev_action_keyframe(1); + else + nextprev_marker(1); } break; case PAGEDOWNKEY: if (datatype == ACTCONT_ACTION) { - if(G.qual & LR_SHIFTKEY) + if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) bottom_sel_action(); - else if (G.qual & LR_CTRLKEY) + else if (G.qual == LR_SHIFTKEY) down_sel_action(); + else if (G.qual == LR_CTRLKEY) + nextprev_action_keyframe(-1); else nextprev_marker(-1); } else if (datatype == ACTCONT_SHAPEKEY) { /* only jump to markers possible (key channels can't be moved yet) */ - nextprev_marker(-1); + if (G.qual == LR_CTRLKEY) + nextprev_action_keyframe(-1); + else + nextprev_marker(-1); } break; @@ -3356,20 +3520,39 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) mouse_action(select_mode); } break; + + case ACCENTGRAVEKEY: + if (datatype == ACTCONT_ACTION) + expand_all_action(); + break; + case PADPLUSKEY: - view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy); - test_view2d(G.v2d, sa->winx, sa->winy); - view2d_do_locks(curarea, V2D_LOCK_COPY); - - doredraw= 1; + if (G.qual == LR_CTRLKEY) { + if (datatype == ACTCONT_ACTION) + openclose_level_action(1); + } + else { + view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy); + test_view2d(G.v2d, sa->winx, sa->winy); + view2d_do_locks(curarea, V2D_LOCK_COPY); + + doredraw= 1; + } break; case PADMINUS: - view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy); - test_view2d(G.v2d, sa->winx, sa->winy); - view2d_do_locks(curarea, V2D_LOCK_COPY); + if (G.qual == LR_CTRLKEY) { + if (datatype == ACTCONT_ACTION) + openclose_level_action(-1); + } + else { + view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy); + test_view2d(G.v2d, sa->winx, sa->winy); + view2d_do_locks(curarea, V2D_LOCK_COPY); + + doredraw= 1; + } + break; - doredraw= 1; - break; case MIDDLEMOUSE: case WHEELUPMOUSE: case WHEELDOWNMOUSE: diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index f66e3bfc22c..bf0bfaef595 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -2533,7 +2533,7 @@ void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcod int vartype; int matset=0; - if ((G.flags&G_AUTOMATKEYS)&&(match_adr_constraint(id, blocktype, actname, adrcode))) { + if ((IS_AUTOKEY_FLAG(AUTOMATKEY))&&(match_adr_constraint(id, blocktype, actname, adrcode))) { matset=insertmatrixkey(id, blocktype, actname, constname, adrcode); } if (matset==0) { diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index a75f5a211b7..05e030bf80b 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -581,7 +581,7 @@ static void add_nla_block(short event) /* simple prevention of zero strips */ if(strip->start>strip->end-2) strip->end= strip->start+100; - strip->repeat = 1.0; + strip->repeat = strip->scale= 1.0f; strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION; @@ -620,6 +620,7 @@ static void add_nla_block_by_name(char name[32], Object *ob, short hold, short a /* Initialize the new action block */ strip = MEM_callocN(sizeof(bActionStrip), "bActionStrip"); + strip->scale= 1.0f; deselect_nlachannel_keys(0); diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index c5215615618..0c29bceba37 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -97,6 +97,7 @@ #include "BSE_drawipo.h" #include "BSE_edit.h" #include "BSE_filesel.h" +#include "BSE_node.h" #include "BSE_trans_types.h" #include "BDR_editobject.h" @@ -1889,6 +1890,7 @@ void sima_sample_color(void) if(fx>=0.0 && fy>=0.0 && fx<1.0 && fy<1.0) { float *fp= NULL, *zpf= NULL; + float vec[3]; int *zp= NULL; char *cp= NULL; @@ -1907,14 +1909,14 @@ void sima_sample_color(void) if(ibuf->rect_float) fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x)); + if(fp==NULL) { + fp= vec; + vec[0]= (float)cp[0]/255.0f; + vec[1]= (float)cp[1]/255.0f; + vec[2]= (float)cp[2]/255.0f; + } + if(G.sima->cumap) { - float vec[3]; - if(fp==NULL) { - fp= vec; - vec[0]= (float)cp[0]/255.0f; - vec[1]= (float)cp[1]/255.0f; - vec[2]= (float)cp[2]/255.0f; - } if(ibuf->channels==4) { if(G.qual & LR_CTRLKEY) { @@ -1928,18 +1930,36 @@ void sima_sample_color(void) } } + { + ScrArea *sa, *cur= curarea; + + node_curvemap_sample(fp); /* sends global to node editor */ + for(sa= G.curscreen->areabase.first; sa; sa= sa->next) { + if(sa->spacetype==SPACE_NODE) { + areawinset(sa->win); + scrarea_do_windraw(sa); + } + } + node_curvemap_sample(NULL); /* clears global in node editor */ + curarea= cur; + } + + areawinset(curarea->win); scrarea_do_windraw(curarea); myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375); glLoadIdentity(); - sima_show_info(ibuf->channels, x, y, cp, fp, zp, zpf); + + sima_show_info(ibuf->channels, x, y, cp, (ibuf->rect_float)?fp:NULL, zp, zpf); + screen_swapbuffers(); + } - } BIF_wait_for_statechange(); } scrarea_queue_winredraw(curarea); + } /* Image functions */ diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index df3d74aa345..6e3686259da 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -2636,7 +2636,7 @@ void fly(void) G.vd->persp= 2; /* record the motion */ - if (G.flags & G_RECORDKEYS && (!playing_anim || cfra != G.scene->r.cfra)) { + if (IS_AUTOKEY_MODE(NORMAL) && (!playing_anim || cfra != G.scene->r.cfra)) { cfra = G.scene->r.cfra; if (xlock || zlock || moffset[0] || moffset[1]) { @@ -2683,7 +2683,7 @@ void fly(void) DAG_object_flush_update(G.scene, G.vd->camera, OB_RECALC_OB); - if (G.flags & G_RECORDKEYS) { + if (IS_AUTOKEY_MODE(NORMAL)) { allqueue(REDRAWIPO, 0); allspace(REMAKEIPO, 0); allqueue(REDRAWNLA, 0); diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index ab30c4cad52..c9edd6cd1f0 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -92,8 +92,13 @@ enum { ACTMENU_VIEW_SLIDERS, ACTMENU_VIEW_NEXTMARKER, ACTMENU_VIEW_PREVMARKER, + ACTMENU_VIEW_NEXTKEYFRAME, + ACTMENU_VIEW_PREVKEYFRAME, ACTMENU_VIEW_TIME, - ACTMENU_VIEW_NOHIDE + ACTMENU_VIEW_NOHIDE, + ACTMENU_VIEW_OPENLEVELS, + ACTMENU_VIEW_CLOSELEVELS, + ACTMENU_VIEW_EXPANDALL }; enum { @@ -286,7 +291,7 @@ static void do_action_viewmenu(void *arg, int event) break; case ACTMENU_VIEW_LOCK: G.v2d->flag ^= V2D_VIEWLOCK; - if(G.v2d->flag & V2D_VIEWLOCK) + if (G.v2d->flag & V2D_VIEWLOCK) view2d_do_locks(curarea, 0); break; case ACTMENU_VIEW_SLIDERS: /* Show sliders (when applicable) */ @@ -295,10 +300,10 @@ static void do_action_viewmenu(void *arg, int event) case ACTMENU_VIEW_MAXIMIZE: /* Maximize Window */ /* using event B_FULL */ break; - case ACTMENU_VIEW_NEXTMARKER: /* jump to next marker */ + case ACTMENU_VIEW_NEXTMARKER: /* Jump to next marker */ nextprev_marker(1); break; - case ACTMENU_VIEW_PREVMARKER: /* jump to previous marker */ + case ACTMENU_VIEW_PREVMARKER: /* Jump to previous marker */ nextprev_marker(-1); break; case ACTMENU_VIEW_TIME: /* switch between frames and seconds display */ @@ -307,6 +312,21 @@ static void do_action_viewmenu(void *arg, int event) case ACTMENU_VIEW_NOHIDE: /* Show hidden channels */ G.saction->flag ^= SACTION_NOHIDE; break; + case ACTMENU_VIEW_NEXTKEYFRAME: /* Jump to next keyframe */ + nextprev_action_keyframe(1); + break; + case ACTMENU_VIEW_PREVKEYFRAME: /* Jump to previous keyframe */ + nextprev_action_keyframe(-1); + break; + case ACTMENU_VIEW_OPENLEVELS: /* Unfold channels one step */ + openclose_level_action(1); + break; + case ACTMENU_VIEW_CLOSELEVELS: /* Fold channels one step */ + openclose_level_action(-1); + break; + case ACTMENU_VIEW_EXPANDALL: /* Expands all channels */ + expand_all_action(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -363,6 +383,26 @@ static uiBlock *action_viewmenu(void *arg_unused) menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_VIEW_AUTOUPDATE, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, + menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + /* only if editing action... */ + // TODO: improve this code! + + if (G.saction->action) { + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Toggle Show Hierachy|~", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_EXPANDALL, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Expand One Level|Ctrl NumPad+", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_OPENLEVELS, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Collapse One Level|Ctrl NumPad-", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_CLOSELEVELS, ""); + } + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -372,6 +412,13 @@ static uiBlock *action_viewmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Jump To Prev Marker|PageDown", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_PREVMARKER, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Jump To Next Keyframe|Ctrl PageUp", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_NEXTKEYFRAME, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Jump To Prev Keyframe|Ctrl PageDown", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_VIEW_PREVKEYFRAME, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -850,11 +897,11 @@ static uiBlock *action_keymenu_chanposmenu(void *arg_unused) uiBlockSetButmFunc(block, do_action_keymenu_chanposmenu, NULL); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Move Up|Ctrl Page Up", 0, yco-=20, + "Move Up|Shift Page Up", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_UP, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Move Down|Ctrl Page Down", 0, yco-=20, + "Move Down|Shift Page Down", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_DOWN, ""); @@ -862,11 +909,11 @@ static uiBlock *action_keymenu_chanposmenu(void *arg_unused) menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Move to Top|Shift Page Up", 0, yco-=20, + "Move to Top|Ctrl Shift Page Up", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_TOP, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Move to Bottom|Shift Page Down", 0, yco-=20, + "Move to Bottom|Ctrl Shift Page Down", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_BOTTOM, ""); diff --git a/source/blender/src/header_imasel.c b/source/blender/src/header_imasel.c index 1402e8c244e..3968cff4757 100644 --- a/source/blender/src/header_imasel.c +++ b/source/blender/src/header_imasel.c @@ -155,6 +155,11 @@ void imasel_buttons(void) xco+=20; type = simasel->type; + + if(!simasel->files) { + simasel->files = BIF_filelist_new(); + } + if (type == FILE_LOADLIB) { do_filter = !BIF_filelist_islibrary(simasel->files, dir, group); } else { diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index 23aa7576b12..6a1d7c29f58 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -303,6 +303,7 @@ Scene *copy_scene(Scene *sce, int level) scen->toolsettings= MEM_dupallocN(sce->toolsettings); duplicatelist(&(scen->markers), &(sce->markers)); + duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces)); duplicatelist(&(scen->r.layers), &(sce->r.layers)); scen->nodetree= ntreeCopyTree(sce->nodetree, 0); diff --git a/source/blender/src/header_time.c b/source/blender/src/header_time.c index 3da566bf418..7b98d2f5f4c 100644 --- a/source/blender/src/header_time.c +++ b/source/blender/src/header_time.c @@ -524,10 +524,18 @@ void time_buttons(ScrArea *sa) xco, 0, XIC, YIC, 0, 0, 0, 0, 0, "Skip to End frame (Shift UpArrow)"); xco+= XIC+8; - uiDefIconButBitI(block, TOG, G_RECORDKEYS, REDRAWINFO, ICON_REC, - xco, 0, XIC, YIC, &(G.flags), 0, 0, 0, 0, "Automatically insert keyframes in Object and Action Ipo curves"); + uiDefIconButBitS(block, TOG, AUTOKEY_ON, REDRAWINFO, ICON_REC, + xco, 0, XIC, YIC, &(U.autokey_mode), 0, 0, 0, 0, "Automatic keyframe insertion for Objects and Bones"); + xco+= XIC; + if (IS_AUTOKEY_ON) { + uiDefButS(block, MENU, REDRAWINFO, + "Auto-Keying Mode %t|Add/Replace Keys%x3|Replace Keys %x5", + xco, 0, 3*XIC, YIC, &(U.autokey_mode), 0, 1, 0, 0, + "Mode of automatic keyframe insertion for Objects and Bones"); + xco+= (4*XIC); + } - xco+= XIC+16; + xco+= 16; uiDefIconButBitI(block, TOG, TIME_WITH_SEQ_AUDIO, B_DIFF, ICON_SPEAKER, xco, 0, XIC, YIC, &(stime->redraws), 0, 0, 0, 0, "Play back and sync with audio from Sequence Editor"); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index e34890c4313..8102e60c7fb 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -601,6 +601,9 @@ static void do_view3d_viewmenu(void *arg, int event) case 19: /* zoom within border */ view3d_border_zoom(); break; + case 20: /* Transform Space Panel */ + add_blockhandler(curarea, VIEW3D_HANDLER_TRANSFORM, UI_PNL_UNSTOW); + break; } allqueue(REDRAWVIEW3D, 1); } @@ -614,6 +617,7 @@ static uiBlock *view3d_viewmenu(void *arg_unused) block= uiNewBlock(&curarea->uiblocks, "view3d_viewmenu", UI_EMBOSSP, UI_HELV, curarea->headwin); uiBlockSetButmFunc(block, do_view3d_viewmenu, NULL); + uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Orientations...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 20, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Render Preview...|Shift P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 18, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "View Properties...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 16, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Background Image...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 15, ""); @@ -1814,7 +1818,7 @@ static uiBlock *view3d_transformmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center Cursor", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, ""); } - if (G.obedit != NULL && G.obedit->type==OB_MESH) + if (BIF_snappingSupported()) { uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -4374,16 +4378,19 @@ void do_view3d_sculpt_inputmenu(void *arg, int event) switch(event) { case 0: sd->flags ^= SCULPT_INPUT_SMOOTH; + BIF_undo_push("Smooth stroke"); break; case 1: val= sd->tablet_size; if(button(&val,0,10,"Tablet Size:")==0) return; sd->tablet_size= val; + BIF_undo_push("Tablet size"); break; case 2: val= sd->tablet_strength; if(button(&val,0,10,"Tablet Strength:")==0) return; sd->tablet_strength= val; + BIF_undo_push("Tablet strength"); break; } @@ -4404,24 +4411,35 @@ void do_view3d_sculptmenu(void *arg, int event) case 5: case 6: sd->brush_type= event+1; + BIF_undo_push("Brush type"); break; case 7: - br->airbrush= !br->airbrush; break; + br->airbrush= !br->airbrush; + BIF_undo_push("Airbrush"); + break; case 8: - sd->symm ^= SYMM_X; break; + sd->symm ^= SYMM_X; + BIF_undo_push("X Symmetry"); + break; case 9: - sd->symm ^= SYMM_Y; break; + sd->symm ^= SYMM_Y; + BIF_undo_push("Y Symmetry"); + break; case 10: - sd->symm ^= SYMM_Z; break; + sd->symm ^= SYMM_Z; + BIF_undo_push("Z Symmetry"); + break; case 11: - if(G.vd) + if(G.vd) G.vd->pivot_last= !G.vd->pivot_last; break; case 12: sd->flags ^= SCULPT_DRAW_FAST; + BIF_undo_push("Partial Redraw"); break; case 13: sd->flags ^= SCULPT_DRAW_BRUSH; + BIF_undo_push("Draw Brush"); break; case 14: add_blockhandler(curarea, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW); @@ -4436,7 +4454,9 @@ void do_view3d_sculptmenu(void *arg, int event) sculptmode_propset_init(PropsetSize); break; case 18: - br->dir= br->dir==1 ? 2 : 1; break; + br->dir= br->dir==1 ? 2 : 1; + BIF_undo_push("Add/Sub"); + break; } allqueue(REDRAWBUTSEDIT, 0); @@ -5092,7 +5112,9 @@ void do_view3d_buttons(short event) G.vd->twtype= V3D_MANIP_SCALE; allqueue(REDRAWVIEW3D, 1); break; - + case B_MAN_MODE: + allqueue(REDRAWVIEW3D, 1); + break; default: if(event>=B_LAY && eventaround), 0, 3.0, 0, 0, "Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period, Ctrl Period, Alt Period)"); xco+= XIC+10; @@ -5403,7 +5426,11 @@ void view3d_buttons(void) uiDefIconButBitS(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE, xco,0,XIC,YIC, &G.vd->twtype, 1.0, 0.0, 0, 0, "Scale manipulator mode (Ctrl Alt S)"); xco+= XIC; } - uiDefButS(block, MENU, B_NOP, "Orientation%t|Global%x0|Local%x1|Normal%x2|View%x3",xco,0,70,YIC, &G.vd->twmode, 0, 0, 0, 0, "Transform Orientation (Alt Space)"); + + str_menu = BIF_menustringTransformOrientation(); + uiDefButS(block, MENU, B_MAN_MODE, str_menu,xco,0,70,YIC, &G.vd->twmode, 0, 0, 0, 0, "Transform Orientation (ALT+Space)"); + MEM_freeN(str_menu); + xco+= 70; uiBlockEndAlign(block); xco+= 8; @@ -5449,7 +5476,7 @@ void view3d_buttons(void) } /* Snap */ - if(G.obedit && (G.obedit->type == OB_MESH)) { // Only Mesh for now + if (BIF_snappingSupported()) { uiBlockBeginAlign(block); if (G.scene->snap_flag & SCE_SNAP) { diff --git a/source/blender/src/interface_draw.c b/source/blender/src/interface_draw.c index 4f1d5056111..9ca260edefa 100644 --- a/source/blender/src/interface_draw.c +++ b/source/blender/src/interface_draw.c @@ -2234,10 +2234,35 @@ static void ui_draw_but_CURVE(uiBut *but) if(cumap->flag & CUMA_DRAW_CFRA) { glColor3ub(0x60, 0xc0, 0x40); glBegin(GL_LINES); - glVertex2f(but->x1 + zoomx*(cumap->black[0]-offsx), but->y1); - glVertex2f(but->x1 + zoomx*(cumap->black[0]-offsx), but->y2); + glVertex2f(but->x1 + zoomx*(cumap->sample[0]-offsx), but->y1); + glVertex2f(but->x1 + zoomx*(cumap->sample[0]-offsx), but->y2); glEnd(); } + /* sample option */ + if(cumap->flag & CUMA_DRAW_SAMPLE) { + if(cumap->cur==3) { + float lum= cumap->sample[0]*0.35f + cumap->sample[1]*0.45f + cumap->sample[2]*0.2f; + glColor3ub(240, 240, 240); + + glBegin(GL_LINES); + glVertex2f(but->x1 + zoomx*(lum-offsx), but->y1); + glVertex2f(but->x1 + zoomx*(lum-offsx), but->y2); + glEnd(); + } + else { + if(cumap->cur==0) + glColor3ub(240, 100, 100); + else if(cumap->cur==1) + glColor3ub(100, 240, 100); + else + glColor3ub(100, 100, 240); + + glBegin(GL_LINES); + glVertex2f(but->x1 + zoomx*(cumap->sample[cumap->cur]-offsx), but->y1); + glVertex2f(but->x1 + zoomx*(cumap->sample[cumap->cur]-offsx), but->y2); + glEnd(); + } + } /* the curve */ BIF_ThemeColorBlend(TH_TEXT, TH_BUT_NEUTRAL, 0.35); diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index c87531ec8bd..441ba0eab52 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -48,6 +48,7 @@ #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_scene_types.h" +#include "DNA_userdef_types.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -692,7 +693,8 @@ static void poselib_keytag_pose (tPoseLib_PreviewData *pld) pchan= get_pose_channel(pose, achan->name); if (pchan) { - if (G.flags & G_RECORDKEYS) { + // TODO: use a standard autokeying function in future (to allow autokeying-editkeys to work) + if (IS_AUTOKEY_MODE(NORMAL)) { ID *id= &pld->ob->id; /* Set keys on pose */ @@ -1120,7 +1122,7 @@ static void poselib_preview_cleanup (tPoseLib_PreviewData *pld) DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); /* updates */ - if (G.flags & G_RECORDKEYS) { + if (IS_AUTOKEY_MODE(NORMAL)) { remake_action_ipos(ob->action); allqueue(REDRAWIPO, 0); diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index e1854c0043e..cdcb86af239 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -45,6 +45,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_view3d_types.h" +#include "DNA_userdef_types.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -826,7 +827,7 @@ void paste_posebuf (int flip) EulToQuat(eul, pchan->quat); } - if (G.flags & G_RECORDKEYS) { + if (autokeyframe_cfra_can_key(ob)) { ID *id= &ob->id; /* Set keys on pose */ @@ -863,7 +864,7 @@ void paste_posebuf (int flip) /* Update event for pose and deformation children */ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - if (G.flags & G_RECORDKEYS) { + if ((IS_AUTOKEY_MODE(NORMAL))) { remake_action_ipos(ob->action); allqueue (REDRAWIPO, 0); allqueue (REDRAWVIEW3D, 0); @@ -1153,10 +1154,10 @@ void pose_relax() float frame_prev, frame_next; float quat_prev[4], quat_next[4], quat_interp[4], quat_orig[4]; - /*int do_scale = 0; + int do_scale = 0; int do_loc = 0; int do_quat = 0; - int flag = 0;*/ + int flag = 0; int do_x, do_y, do_z; if (!ob) return; @@ -1167,36 +1168,25 @@ void pose_relax() if (!pose || !act || !arm) return; - for (pchan=pose->chanbase.first; pchan; pchan= pchan->next){ - if(pchan->bone->layer & arm->layer) { - if(pchan->bone->flag & BONE_SELECTED) { + for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->bone->layer & arm->layer) { + if (pchan->bone->flag & BONE_SELECTED) { /* do we have an ipo curve? */ achan= get_action_channel(act, pchan->name); - if(achan && achan->ipo) { + + if (achan && achan->ipo) { /*calc_ipo(achan->ipo, ctime);*/ do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_X), framef, &pchan->loc[0], NULL, NULL); do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Y), framef, &pchan->loc[1], NULL, NULL); do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Z), framef, &pchan->loc[2], NULL, NULL); - /* do_loc = do_x + do_y + do_z */ - - if (G.flags & G_RECORDKEYS) { - if (do_x) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - if (do_y) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - if (do_z) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); - } + do_loc += do_x + do_y + do_z; do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_X), framef, &pchan->size[0], NULL, NULL); do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Y), framef, &pchan->size[1], NULL, NULL); do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Z), framef, &pchan->size[2], NULL, NULL); - /* do_scale = do_x + do_y + do_z */ - - if (G.flags & G_RECORDKEYS) { - if (do_x) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); - if (do_y) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); - if (do_z) insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); - } - + do_scale += do_x + do_y + do_z; + if( ((icu_w = find_ipocurve(achan->ipo, AC_QUAT_W))) && ((icu_x = find_ipocurve(achan->ipo, AC_QUAT_X))) && ((icu_y = find_ipocurve(achan->ipo, AC_QUAT_Y))) && @@ -1225,20 +1215,12 @@ void pose_relax() QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f); /* done */ #endif - /*do_quat++;*/ - - if (G.flags & G_RECORDKEYS) { - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - } + do_quat++; } } - if (G.flags & G_RECORDKEYS) { - pchan->bone->flag &= ~BONE_UNKEYED; - } + /* apply BONE_TRANSFORM tag so that autokeying will pick it up */ + pchan->bone->flag |= BONE_TRANSFORM; } } } @@ -1246,16 +1228,17 @@ void pose_relax() ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); -#if 0 -// /* auto-keyframing - dosnt work, no idea why, do manually above */ + /* do auto-keying */ if (do_loc) flag |= TFM_TRANSLATION; if (do_scale) flag |= TFM_RESIZE; if (do_quat) flag |= TFM_ROTATION; autokeyframe_pose_cb_func(ob, flag, 0); -#endif - + + /* clear BONE_TRANSFORM flags */ + for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) + pchan->bone->flag &= ~ BONE_TRANSFORM; + /* do depsgraph flush */ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); BIF_undo_push("Relax Pose"); - } diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index f3bfb645315..a1341fd60c3 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -1311,6 +1311,8 @@ void sculptmode_propset_end(SculptSession *ss, int cancel) sculptmode_brush()->strength= pd->origstrength; if(pd->mode != PropsetTexRot) set_tex_angle(pd->origtexrot); + + BIF_undo_push("Brush property set"); } glDeleteTextures(1, &pd->tex); MEM_freeN(pd->num); @@ -1480,6 +1482,8 @@ void sculptmode_selectbrush_menu(void) if(val>0) { sd->brush_type= val; + + BIF_undo_push("Brush type"); allqueue(REDRAWVIEW3D, 1); allqueue(REDRAWBUTSEDIT, 1); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 81a5606d7c4..9f3754f32da 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1570,8 +1570,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) /* Shift-Tabe handling (other cases are in toets) */ if (G.qual == LR_SHIFTKEY) { - /* Snap toggle (only edit mesh right now) */ - if (G.obedit && G.obedit->type==OB_MESH) + /* Snap toggle only when supported */ + if (BIF_snappingSupported()) { G.scene->snap_flag ^= SCE_SNAP; allqueue(REDRAWHEADERS, 0); @@ -1798,6 +1798,10 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } else if(G.qual==(LR_ALTKEY|LR_CTRLKEY)) add_constraint(0); /* editconstraint.c, generic for objects and posemode */ + else if(G.qual==(LR_CTRLKEY|LR_SHIFTKEY)) { + BIF_manageTransformOrientation(0, 1); + allqueue(REDRAWVIEW3D, 0); + } else if((G.qual==LR_SHIFTKEY)) { view3d_home(1); curs= give_cursor(); @@ -3667,34 +3671,37 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiBlockEndAlign(block); - uiDefBut(block, LABEL,0,"Auto keyframe", - (xpos+(2*edgsp)+(2*mpref)+midsp),y5label,mpref,buth, + uiDefBut(block, LABEL,0,"Auto Keyframe", + (xpos+(2*edgsp)+(2*mpref)+midsp),y6label,mpref,buth, 0, 0, 0, 0, 0, ""); - - uiDefButBitI(block, TOG, G_RECORDKEYS, REDRAWTIME, "Action and Object", - (xpos+edgsp+(2*mpref)+(2*midsp)),y4,mpref, buth, - &(G.flags), 0, 0, 0, 0, "Automatic keyframe insertion in Object and Action Ipo curves"); + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, AUTOKEY_ON, REDRAWTIME, "Auto-Keying Enabled", + (xpos+edgsp+(2*mpref)+(2*midsp)),y5,mpref, buth, + &(U.autokey_mode), 0, 0, 0, 0, "Automatic keyframe insertion for Objects and Bones"); + + if (IS_AUTOKEY_ON) { + uiDefButS(block, MENU, REDRAWTIME, + "Auto-Keying Mode %t|Add/Replace Keys%x3|Replace Keys %x5", + (xpos+edgsp+(2*mpref)+(2*midsp)),y4,mpref, buth, + &(U.autokey_mode), 0, 1, 0, 0, + "Mode of automatic keyframe insertion for Objects and Bones"); + } + uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, USER_KEYINSERTAVAI, REDRAWTIME, "Available", - (xpos+edgsp+(2*mpref)+(2*midsp)),y3,mpref, buth, - &(U.uiflag), 0, 0, 0, 0, "Automatic keyframe insertion in available curves"); - - uiDefButBitI(block, TOG, USER_KEYINSERTNEED, REDRAWTIME, "Needed", - (xpos+edgsp+(2*mpref)+(2*midsp)),y2,mpref, buth, - &(U.uiflag), 0, 0, 0, 0, "Automatic keyframe insertion only when keyframe needed"); - - uiDefButBitI(block, TOG, G_AUTOMATKEYS, REDRAWTIME, "Use Visual Keying", - (xpos+edgsp+(2*mpref)+(2*midsp)),y1,mpref, buth, - &(G.flags), 0, 0, 0, 0, "Use Visual keying automatically for constrained objects"); + uiDefButBitS(block, TOG, AUTOKEY_FLAG_INSERTAVAIL, REDRAWTIME, "Available", + (xpos+edgsp+(2*mpref)+(2*midsp)),y3,mpref, buth, + &(U.autokey_flag), 0, 0, 0, 0, "Automatic keyframe insertion in available curves"); + + uiDefButBitS(block, TOG, AUTOKEY_FLAG_INSERTNEEDED, REDRAWTIME, "Needed", + (xpos+edgsp+(2*mpref)+(2*midsp)),y2,mpref, buth, + &(U.autokey_flag), 0, 0, 0, 0, "Automatic keyframe insertion only when keyframe needed"); + + uiDefButBitS(block, TOG, AUTOKEY_FLAG_AUTOMATKEY, REDRAWTIME, "Use Visual Keying", + (xpos+edgsp+(2*mpref)+(2*midsp)),y1,mpref, buth, + &(U.autokey_flag), 0, 0, 0, 0, "Use Visual keying automatically for constrained objects"); uiBlockEndAlign(block); - -/* uiDefButBitS(block, TOG, USER_KEYINSERTACT, 0, "Action", - (xpos+edgsp+(2*mpref)+(2*midsp)),y2,(spref+edgsp),buth, - &(U.uiflag), 0, 0, 0, 0, "Automatic keyframe insertion in Action Ipo curve"); - uiDefButBitS(block, TOG, USER_KEYINSERTOBJ, 0, "Object", - (xpos+edgsp+(2*mpref)+(3*midsp)+spref-edgsp),y2,(spref+edgsp),buth, - &(U.uiflag), 0, 0, 0, 0, "Automatic keyframe insertion in Object Ipo curve"); */ uiDefBut(block, LABEL,0,"Duplicate with object:", @@ -4602,16 +4609,6 @@ static void winqreadseqspace(ScrArea *sa, void *spacedata, BWinEvent *evt) test_view2d(G.v2d, sa->winx, sa->winy); view2d_do_locks(sa, V2D_LOCK_COPY); } - else if((G.qual==LR_SHIFTKEY)) { - insert_gap(25, CFRA); - BIF_undo_push("Insert gaps Sequencer"); - allqueue(REDRAWSEQ, 0); - } - else if(G.qual==LR_ALTKEY) { - insert_gap(250, CFRA); - BIF_undo_push("Insert gaps Sequencer"); - allqueue(REDRAWSEQ, 0); - } } doredraw= 1; break; diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 1b9f8752103..32c152488d1 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -157,6 +157,305 @@ static void helpline(TransInfo *t, float *vec) glDrawBuffer(GL_BACK); } } + +/* *********************** TransSpace ************************** */ + +void BIF_clearTransformOrientation(void) +{ + ListBase *transform_spaces = &G.scene->transform_spaces; + BLI_freelistN(transform_spaces); + + if (G.vd->twmode >= V3D_MANIP_CUSTOM) + G.vd->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ +} + +void BIF_manageTransformOrientation(int confirm, int set) { + int index = -1; + + if (G.obedit) { + if (G.obedit->type == OB_MESH) + index = manageMeshSpace(confirm, set); + } + else { + index = manageObjectSpace(confirm, set); + } + + if (set && index != -1) + { + BIF_selectTransformOrientationFromIndex(index); + } +} + +int manageObjectSpace(int confirm, int set) { + Base *base = BASACT; + + if (base == NULL) + return -1; + + if (confirm == 0) { + if (set && pupmenu("Custome Space %t|Add and Use Active Object%x1") != 1) { + return -1; + } + else if (set == 0 && pupmenu("Custome Space %t|Add Active Object%x1") != 1) { + return -1; + } + } + + return addObjectSpace(base->object); +} + +int manageMeshSpace(int confirm, int set) { + EditMesh *em = G.editMesh; + float mat[3][3], vec[3] = {0.0f, 0.0f, 1.0f}; + int index; + char name[36] = ""; + + if (G.scene->selectmode & SCE_SELECT_VERTEX && G.totvertsel == 1) { + EditVert *eve; + + if (confirm == 0) { + if (set && pupmenu("Custome Space %t|Add and Use Vertex%x1") != 1) { + return -1; + } + else if (set == 0 && pupmenu("Custome Space %t|Add Vertex%x1") != 1) { + return -1; + } + } + + for(eve = em->verts.first; eve; eve= eve->next) { + if(eve->h == 0 && (eve->f & SELECT)) + break; + } + + if (eve == NULL) + return -1; + + VECCOPY(mat[2], eve->no); + if (Normalize(mat[2]) == 0.0f) { + error("Cannot use vertex with zero-length normal"); + return -1; + } + + strcpy(name, "Vertex"); + } + else if(G.scene->selectmode & SCE_SELECT_EDGE && G.totedgesel == 1) { + EditEdge *eed; + + if (confirm == 0) { + if (set && pupmenu("Custome Space %t|Add and Use Edge%x1") != 1) { + return -1; + } + else if (set == 0 && pupmenu("Custome Space %t|Add Edge%x1") != 1) { + return -1; + } + } + + for(eed = em->edges.first; eed; eed= eed->next) { + if(eed->h == 0 && (eed->f & SELECT)) + break; + } + + if (eed == NULL) + return -1; + + VecSubf(mat[2], eed->v2->co, eed->v1->co); + if (Normalize(mat[2]) == 0.0f) { + error("Cannot use zero-length edges"); + return -1; + } + + strcpy(name, "Edge"); + } + else if(G.scene->selectmode & SCE_SELECT_FACE && G.totfacesel == 1) { + EditFace *efa; + + if (confirm == 0) { + if (set && pupmenu("Custome Space %t|Add and Use Face%x1") != 1) { + return -1; + } + else if (set == 0 && pupmenu("Custome Space %t|Add Face%x1") != 1) { + return -1; + } + } + + for(efa = em->faces.first; efa; efa= efa->next) { + if(efa->h == 0 && (efa->f & SELECT)) + break; + } + + if (efa == NULL) + return -1; + + VECCOPY(mat[2], efa->n); + if (Normalize(mat[2]) == 0.0f) { + error("Cannot use face with zero-length normal"); + return -1; + } + + VecSubf(vec, efa->v2->co, efa->v1->co); + + strcpy(name, "Face"); + } + else { + notice("You need to select only one vertex, edge or face"); + return -1; + } + + /* Applying matrix for global space */ + Mat4Mul3Vecfl(G.obedit->obmat, mat[2]); + Mat4Mul3Vecfl(G.obedit->obmat, vec); + + /* Calculating the other axis */ + + Crossf(mat[0], mat[2], vec); + if (Normalize(mat[0]) == 0.0f) { + vec[0] = 1.0f; + vec[1] = vec[2] = 0.0f; + Crossf(mat[0], vec, mat[2]); + } + + Crossf(mat[1], mat[2], mat[0]); + + Mat3Ortho(mat); + + /* Input name */ + sbutton(name, 1, 35, "name: "); + + index = addMatrixSpace(mat, name); + return index; +} + +int addObjectSpace(Object *ob) { + float mat[3][3]; + char name[36] = ""; + + Mat3CpyMat4(mat, ob->obmat); + Mat3Ortho(mat); + + strncpy(name, ob->id.name+2, 35); + + /* Input name */ + sbutton(name, 1, 35, "name: "); + + return addMatrixSpace(mat, name); +} + +int addMatrixSpace(float mat[3][3], char name[]) { + ListBase *transform_spaces = &G.scene->transform_spaces; + TransformOrientation *ts; + int index = 0; + + /* if name is found in list, reuse that transform space */ + for (index = 0, ts = transform_spaces->first; ts; ts = ts->next, index++) { + if (strncmp(ts->name, name, 35) == 0) { + break; + } + } + + /* if not, create a new one */ + if (ts == NULL) + { + ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix"); + BLI_addtail(transform_spaces, ts); + strncpy(ts->name, name, 35); + } + + /* copy matrix into transform space */ + Mat3CpyMat3(ts->mat, mat); + + BIF_undo_push("Add/Update Transform Orientation"); + + return BIF_countTransformOrientation() - 1; +} + +void BIF_removeTransformOrientation(TransformOrientation *target) { + ListBase *transform_spaces = &G.scene->transform_spaces; + TransformOrientation *ts = transform_spaces->first; + int selected_index = (G.vd->twmode - V3D_MANIP_CUSTOM); + int i; + + for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) { + if (ts == target) { + if (selected_index == i) { + G.vd->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ + } + else if (selected_index > i) + G.vd->twmode--; + + BLI_freelinkN(transform_spaces, ts); + break; + } + } + BIF_undo_push("Remove Transform Orientation"); +} + +void BIF_selectTransformOrientation(TransformOrientation *target) { + ListBase *transform_spaces = &G.scene->transform_spaces; + TransformOrientation *ts = transform_spaces->first; + int i; + + for (i = 0, ts = transform_spaces->first; ts; ts = ts->next, i++) { + if (ts == target) { + G.vd->twmode = V3D_MANIP_CUSTOM + i; + break; + } + } +} + +void BIF_selectTransformOrientationFromIndex(int index) { + G.vd->twmode = V3D_MANIP_CUSTOM + index; +} + +char * BIF_menustringTransformOrientation() { + char menu[] = "Orientation%t|Global%x0|Local%x1|Normal%x2|View%x3"; + ListBase *transform_spaces = &G.scene->transform_spaces; + TransformOrientation *ts; + int i = V3D_MANIP_CUSTOM; + char *str_menu, *p; + + + str_menu = MEM_callocN(strlen(menu) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); + p = str_menu; + + p += sprintf(str_menu, "%s", menu); + + for (ts = transform_spaces->first; ts; ts = ts->next) { + p += sprintf(p, "|%s%%x%d", ts->name, i++); + } + + return str_menu; +} + +int BIF_countTransformOrientation() { + ListBase *transform_spaces = &G.scene->transform_spaces; + TransformOrientation *ts; + int count = 0; + + for (ts = transform_spaces->first; ts; ts = ts->next) { + count++; + } + + return count; +} + +void applyTransformOrientation() { + TransInfo *t = BIF_GetTransInfo(); + TransformOrientation *ts; + int selected_index = (G.vd->twmode - V3D_MANIP_CUSTOM); + int i; + + if (selected_index >= 0) { + for (i = 0, ts = G.scene->transform_spaces.first; ts; ts = ts->next, i++) { + if (selected_index == i) { + strcpy(t->spacename, ts->name); + Mat3CpyMat3(t->spacemtx, ts->mat); + Mat4CpyMat3(G.vd->twmat, ts->mat); + break; + } + } + } +} + /* ************************** INPUT FROM MOUSE *************************** */ float InputScaleRatio(TransInfo *t, short mval[2]) { @@ -465,12 +764,12 @@ static void viewRedrawPost(TransInfo *t) void BIF_selectOrientation() { short val; - val= pupmenu("Orientation%t|Global|Local|Normal|View"); - if(val>0) { - if(val==1) G.vd->twmode= V3D_MANIP_GLOBAL; - else if(val==2) G.vd->twmode= V3D_MANIP_LOCAL; - else if(val==3) G.vd->twmode= V3D_MANIP_NORMAL; - else if(val==4) G.vd->twmode= V3D_MANIP_VIEW; + char *str_menu = BIF_menustringTransformOrientation(); + val= pupmenu(str_menu); + MEM_freeN(str_menu); + + if(val >= 0) { + G.vd->twmode = val; } } @@ -1345,9 +1644,83 @@ static void constraintTransLim(TransInfo *t, TransData *td) /* Evaluate valid constraints */ for (con= td->con; con; con= con->next) { - /* we're only interested in Limit-Location constraints */ + float tmat[4][4]; + + /* only use it if it's tagged for this purpose (and the right type) */ if (con->type == CONSTRAINT_TYPE_LOCLIMIT) { bLocLimitConstraint *data= con->data; + if ((data->flag2 & LIMIT_TRANSFORM)==0) + continue; + } + else if (con->type == CONSTRAINT_TYPE_ROTLIMIT) { + bRotLimitConstraint *data= con->data; + if ((data->flag2 & LIMIT_TRANSFORM)==0) + continue; + } + else if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { + bSizeLimitConstraint *data= con->data; + if ((data->flag2 & LIMIT_TRANSFORM)==0) + continue; + } + else { + /* not supported */ + continue; + } + + /* do space conversions */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + Mat4CpyMat4(tmat, cob.matrix); + Mat4MulMat34(cob.matrix, td->mtx, tmat); + } + else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { + /* skip... incompatable spacetype */ + continue; + } + + /* do constraint */ + cti->evaluate_constraint(con, &cob, NULL); + + /* convert spaces again */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + Mat4CpyMat4(tmat, cob.matrix); + Mat4MulMat34(cob.matrix, td->smtx, tmat); + } + } + + /* copy results from cob->matrix */ + if (td->tdi) { + TransDataIpokey *tdi= td->tdi; + tdi->locx[0]= cob.matrix[3][0]; + tdi->locy[0]= cob.matrix[3][1]; + tdi->locz[0]= cob.matrix[3][2]; + } + else { + VECCOPY(td->loc, cob.matrix[3]); + } + } +} + +static void constraintRotLim(TransInfo *t, TransData *td) +{ + if (td->con && td->ext) { + bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT); + bConstraintOb cob; + bConstraint *con; + + /* Make a temporary bConstraintOb for using these limit constraints + * - they only care that cob->matrix is correctly set ;-) + * - current space should be local + */ + memset(&cob, 0, sizeof(bConstraintOb)); + // FIXME: todo + + /* Evaluate valid constraints */ + for (con= td->con; con; con= con->next) { + /* we're only interested in Limit-Scale constraints */ + if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { + bSizeLimitConstraint *data= con->data; float tmat[4][4]; /* only use it if it's tagged for this purpose */ @@ -1358,7 +1731,7 @@ static void constraintTransLim(TransInfo *t, TransData *td) if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ Mat4CpyMat4(tmat, cob.matrix); - Mat4MulMat34(cob.matrix, td->mtx, tmat); // checkme + Mat4MulMat34(cob.matrix, td->mtx, tmat); } else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { /* skip... incompatable spacetype */ @@ -1372,7 +1745,79 @@ static void constraintTransLim(TransInfo *t, TransData *td) if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ Mat4CpyMat4(tmat, cob.matrix); - Mat4MulMat34(cob.matrix, td->smtx, tmat); // checkme + Mat4MulMat34(cob.matrix, td->smtx, tmat); + } + } + } + + /* copy results from cob->matrix */ + // fixme: todo + } +} + +static void constraintSizeLim(TransInfo *t, TransData *td) +{ + if (td->con && td->ext) { + bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT); + bConstraintOb cob; + bConstraint *con; + + /* Make a temporary bConstraintOb for using these limit constraints + * - they only care that cob->matrix is correctly set ;-) + * - current space should be local + */ + memset(&cob, 0, sizeof(bConstraintOb)); + if (td->tdi) { + TransDataIpokey *tdi= td->tdi; + float size[3]; + + size[0]= tdi->sizex[0]; + size[1]= tdi->sizey[0]; + size[2]= tdi->sizez[0]; + SizeToMat4(size, cob.matrix); + } + else if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { + /* scale val and reset size */ + return; // TODO: fix this case + } + else { + /* Reset val if SINGLESIZE but using a constraint */ + if (td->flag & TD_SINGLESIZE) + return; + + SizeToMat4(td->ext->size, cob.matrix); + } + + /* Evaluate valid constraints */ + for (con= td->con; con; con= con->next) { + /* we're only interested in Limit-Scale constraints */ + if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { + bSizeLimitConstraint *data= con->data; + float tmat[4][4]; + + /* only use it if it's tagged for this purpose */ + if ((data->flag2 & LIMIT_TRANSFORM)==0) + continue; + + /* do space conversions */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + Mat4CpyMat4(tmat, cob.matrix); + Mat4MulMat34(cob.matrix, td->mtx, tmat); + } + else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { + /* skip... incompatable spacetype */ + continue; + } + + /* do constraint */ + cti->evaluate_constraint(con, &cob, NULL); + + /* convert spaces again */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + Mat4CpyMat4(tmat, cob.matrix); + Mat4MulMat34(cob.matrix, td->smtx, tmat); } } } @@ -1380,12 +1825,24 @@ static void constraintTransLim(TransInfo *t, TransData *td) /* copy results from cob->matrix */ if (td->tdi) { TransDataIpokey *tdi= td->tdi; - tdi->locx[0]= cob.matrix[3][0]; - tdi->locy[0]= cob.matrix[3][1]; - tdi->locz[0]= cob.matrix[3][2]; + float size[3]; + + Mat4ToSize(cob.matrix, size); + + tdi->sizex[0]= size[0]; + tdi->sizey[0]= size[1]; + tdi->sizez[0]= size[2]; + } + else if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { + /* scale val and reset size */ + return; // TODO: fix this case } else { - VECCOPY(td->loc, cob.matrix[3]); + /* Reset val if SINGLESIZE but using a constraint */ + if (td->flag & TD_SINGLESIZE) + return; + + Mat4ToSize(cob.matrix, td->ext->size); } } } @@ -1799,7 +2256,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { if (td->ext) { float fsize[3]; - + if (t->flag & (T_OBJECT|T_TEXTURE|T_POSE)) { float obsizemat[3][3]; // Reorient the size mat to fit the oriented object. @@ -1828,11 +2285,11 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { add_tdi_poin(tdi->sizey, tdi->oldsize+1, vec[1]); add_tdi_poin(tdi->sizez, tdi->oldsize+2, vec[2]); - } + } else if((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)){ /* scale val and reset size */ *td->val = td->ival * fsize[0] * td->factor; - + td->ext->size[0] = td->ext->isize[0]; td->ext->size[1] = td->ext->isize[1]; td->ext->size[2] = td->ext->isize[2]; @@ -1841,13 +2298,16 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { /* Reset val if SINGLESIZE but using a constraint */ if (td->flag & TD_SINGLESIZE) *td->val = td->ival; - + td->ext->size[0] = td->ext->isize[0] * (fsize[0]) * td->factor; td->ext->size[1] = td->ext->isize[1] * (fsize[1]) * td->factor; td->ext->size[2] = td->ext->isize[2] * (fsize[2]) * td->factor; } } + + constraintSizeLim(t, td); } + /* For individual element center, Editmode need to use iloc */ if (t->flag & T_POINTS) VecSubf(vec, td->iloc, center); @@ -1877,6 +2337,8 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { add_tdi_poin(tdi->locz, tdi->oldloc+2, vec[2]); } else VecAddf(td->loc, td->iloc, vec); + + constraintTransLim(t, td); } int Resize(TransInfo *t, short mval[2]) @@ -2341,7 +2803,7 @@ int Rotation(TransInfo *t, short mval[2]) outputNumInput(&(t->num), c); - sprintf(str, "Rot: %s %s", &c[0], t->proptext); + sprintf(str, "Rot: %s %s %s", &c[0], t->con.text, t->proptext); /* Clamp between -180 and 180 */ while (final >= 180.0) diff --git a/source/blender/src/transform_constraints.c b/source/blender/src/transform_constraints.c index 99e5123a953..33311210ec5 100644 --- a/source/blender/src/transform_constraints.c +++ b/source/blender/src/transform_constraints.c @@ -539,6 +539,10 @@ void setUserConstraint(TransInfo *t, int mode, const char ftext[]) { sprintf(text, ftext, "view"); setConstraint(t, t->spacemtx, mode, text); break; + default: /* V3D_MANIP_CUSTOM */ + sprintf(text, ftext, t->spacename); + setConstraint(t, t->spacemtx, mode, text); + break; } t->con.mode |= CON_USER; diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 6e5f808c490..f9abfd69cdd 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -123,6 +123,7 @@ #include "BSE_editipo_types.h" #include "BSE_editaction_types.h" +#include "BDR_drawaction.h" // list of keyframes in action #include "BDR_editobject.h" // reset_slowparents() #include "BDR_unwrapper.h" @@ -2861,6 +2862,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) VECCOPY(td->ext->dsize, ob->dsize); VECCOPY(td->center, ob->obmat[3]); + + Mat4CpyMat4(td->ext->obmat, ob->obmat); /* is there a need to set the global<->data space conversion matrices? */ if (ob->parent || constinv) { @@ -2958,6 +2961,51 @@ static void clear_trans_object_base_flags(void) } } +/* auto-keyframing feature - checks for whether anything should be done for the current frame */ +short autokeyframe_cfra_can_key(Object *ob) +{ + ListBase keys = {NULL, NULL}; + ActKeyColumn *ak; + float cfra; + short found= 0; + + /* only filter if auto-key mode requires this */ + if (IS_AUTOKEY_ON == 0) + return 0; + else if (IS_AUTOKEY_MODE(NORMAL)) + return 1; + + /* sanity check */ + if (ob == NULL) + return 0; + + /* get keyframes that object has (bone anim is stored on ob too) */ + if (ob->action) + action_to_keylist(ob->action, &keys, NULL); + else if (ob->ipo) + ipo_to_keylist(ob->ipo, &keys, NULL); + else + return 0; + + /* get current frame (will apply nla-scaling as necessary) */ + // ack... this is messy... + cfra= frame_to_float(CFRA); + cfra= get_action_frame(ob, cfra); + + /* check if a keyframe occurs on current frame */ + for (ak= keys.first; ak; ak= ak->next) { + if (IS_EQ(cfra, ak->cfra)) { + found= 1; + break; + } + } + + /* free temp list */ + BLI_freelistN(&keys); + + return found; +} + /* auto-keyframing feature - for objects * tmode: should be a transform mode */ @@ -2966,11 +3014,11 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) IpoCurve *icu; char *actname=""; - if (G.flags & G_RECORDKEYS) { + if (autokeyframe_cfra_can_key(ob)) { if (ob->ipoflag & OB_ACTION_OB) actname= "Object"; - if (U.uiflag & USER_KEYINSERTAVAI) { + if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { if (ob->ipo || ob->action) { ID *id= (ID *)(ob); @@ -2989,7 +3037,7 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) while (icu) { icu->flag &= ~IPO_SELECT; - if (U.uiflag & USER_KEYINSERTNEED) + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); else insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); @@ -2997,7 +3045,7 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) } } } - else if (U.uiflag & USER_KEYINSERTNEED) { + else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) { short doLoc=0, doRot=0, doScale=0; /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ @@ -3077,8 +3125,8 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) pose= ob->pose; act= ob->action; - if (G.flags & G_RECORDKEYS) { - if (!act) + if (autokeyframe_cfra_can_key(ob)) { + if (act == NULL) act= ob->action= add_empty_action("Action"); for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { @@ -3087,14 +3135,14 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) pchan->bone->flag &= ~BONE_UNKEYED; /* only insert into available channels? */ - if (U.uiflag & USER_KEYINSERTAVAI) { + if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { bActionChannel *achan; - for (achan = act->chanbase.first; achan; achan=achan->next){ - if (achan->ipo && !strcmp (achan->name, pchan->name)){ - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ + for (achan = act->chanbase.first; achan; achan=achan->next) { + if (achan->ipo && !strcmp (achan->name, pchan->name)) { + for (icu = achan->ipo->curve.first; icu; icu=icu->next) { /* only insert keyframe if needed? */ - if (U.uiflag & USER_KEYINSERTNEED) + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode); else insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode, 0); @@ -3104,7 +3152,7 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) } } /* only insert keyframe if needed? */ - else if (U.uiflag & USER_KEYINSERTNEED) { + else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) { short doLoc=0, doRot=0, doScale=0; /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ @@ -3174,8 +3222,7 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) if (arm->pathflag & ARM_PATH_ACFRA) { //pose_clear_paths(ob); pose_recalculate_paths(ob); - } - + } } else { /* tag channels that should have unkeyed data */ diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c index 7a6d4c69442..13a8552b844 100644 --- a/source/blender/src/transform_manipulator.c +++ b/source/blender/src/transform_manipulator.c @@ -531,6 +531,9 @@ int calc_manipulator_stats(ScrArea *sa) Mat4CpyMat3(v3d->twmat, mat); } break; + default: /* V3D_MANIP_CUSTOM */ + applyTransformOrientation(); + break; } } diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 355c150657e..3279e6e6f09 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -90,10 +90,22 @@ float RotationBetween(TransInfo *t, float p1[3], float p2[3]); float TranslationBetween(TransInfo *t, float p1[3], float p2[3]); // Trickery -int findNearestVertFromObjects(int *dist, float *loc); +int findNearestVertFromObjects(int *dist, float *loc, int selected); /****************** IMPLEMENTATIONS *********************/ +int BIF_snappingSupported(void) +{ + int status = 0; + + if (G.obedit == NULL || G.obedit->type==OB_MESH) /* only support object or mesh */ + { + status = 1; + } + + return status; +} + void drawSnapping(TransInfo *t) { if ((t->tsnap.status & (SNAP_ON|POINT_INIT|TARGET_INIT)) == (SNAP_ON|POINT_INIT|TARGET_INIT) && @@ -168,7 +180,13 @@ int handleSnapping(TransInfo *t, int event) { int status = 0; - // Put keyhandling code here + if (BIF_snappingSupported() && event == TABKEY && (G.qual & LR_SHIFTKEY) == LR_SHIFTKEY) + { + /* toggle snap and reinit */ + G.scene->snap_flag ^= SCE_SNAP; + initSnapping(t); + status = 1; + } return status; } @@ -211,10 +229,19 @@ void initSnapping(TransInfo *t) if (t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) { // Only 3D view or UV setSnappingCallback(t); + /* Edit mode */ if (t->tsnap.applySnap != NULL && // A snapping function actually exist - (G.obedit != NULL && G.obedit->type==OB_MESH) && // Temporary limited to edit mode meshes (G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on - (t->flag & T_PROP_EDIT) == 0) // No PET, obviously + (G.obedit != NULL && G.obedit->type==OB_MESH) && // Temporary limited to edit mode meshes + ((t->flag & T_PROP_EDIT) == 0) ) // No PET, obviously + { + t->tsnap.status |= SNAP_ON; + t->tsnap.modePoint = SNAP_GEO; + } + /* Object mode */ + else if (t->tsnap.applySnap != NULL && // A snapping function actually exist + (G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on + (G.obedit == NULL) ) // Object Mode { t->tsnap.status |= SNAP_ON; t->tsnap.modePoint = SNAP_GEO; @@ -364,7 +391,28 @@ void CalcSnapGrid(TransInfo *t, float *vec) void CalcSnapGeometry(TransInfo *t, float *vec) { - if (G.obedit != NULL && G.obedit->type==OB_MESH) + if (G.obedit == NULL) + { + if (t->spacetype == SPACE_VIEW3D) + { + float vec[3]; + int found = 0; + int dist = 40; // Use a user defined value here + + found = findNearestVertFromObjects(&dist, vec, 0); + if (found == 1) + { + VECCOPY(t->tsnap.snapPoint, vec); + + t->tsnap.status |= POINT_INIT; + } + else + { + t->tsnap.status &= ~POINT_INIT; + } + } + } + else if (G.obedit != NULL && G.obedit->type==OB_MESH) { /*if (G.scene->selectmode & B_SEL_VERT)*/ @@ -378,7 +426,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec) // use findnearestverts in vert mode, others in other modes nearest = findnearestvert(&dist, SELECT, 1); - found = findNearestVertFromObjects(&dist, vec); + found = findNearestVertFromObjects(&dist, vec, SELECT); if (found == 1) { VECCOPY(t->tsnap.snapPoint, vec); @@ -479,7 +527,7 @@ void TargetSnapMedian(TransInfo *t) for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) { - VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->iloc); + VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->center); } VecMulf(t->tsnap.snapTarget, 1.0 / t->total); @@ -500,28 +548,64 @@ void TargetSnapClosest(TransInfo *t) { TransData *closest = NULL, *td = NULL; - // Base case, only one selected item - if (t->total == 1) + /* Object mode */ + if (t->flag & T_OBJECT) { - VECCOPY(t->tsnap.snapTarget, t->data[0].iloc); - - if(t->flag & (T_EDIT|T_POSE)) { - Object *ob= G.obedit?G.obedit:t->poseobj; - Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); - } - - t->tsnap.dist = t->tsnap.distance(t, t->tsnap.snapTarget, t->tsnap.snapPoint); - } - // More than one selected item - else + int i; + for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) { + struct BoundBox *bb = object_get_boundbox(td->ob); + + /* use boundbox if possible */ + if (bb) + { + int j; + + for (j = 0; j < 8; j++) { + float loc[3]; + float dist; + + VECCOPY(loc, bb->vec[j]); + Mat4MulVecfl(td->ext->obmat, loc); + + dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); + + if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) + { + VECCOPY(t->tsnap.snapTarget, loc); + closest = td; + t->tsnap.dist = dist; + } + } + } + /* use element center otherwise */ + else + { + float loc[3]; + float dist; + + VECCOPY(loc, td->center); + + dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); + + if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) + { + VECCOPY(t->tsnap.snapTarget, loc); + closest = td; + t->tsnap.dist = dist; + } + } + } + } + else + { int i; for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++) { float loc[3]; float dist; - VECCOPY(loc, td->iloc); + VECCOPY(loc, td->center); if(t->flag & (T_EDIT|T_POSE)) { Object *ob= G.obedit?G.obedit:t->poseobj; @@ -544,7 +628,7 @@ void TargetSnapClosest(TransInfo *t) } /*================================================================*/ -int findNearestVertFromObjects(int *dist, float *loc) { +int findNearestVertFromObjects(int *dist, float *loc, int selected) { Base *base; int retval = 0; short mval[2]; @@ -553,7 +637,7 @@ int findNearestVertFromObjects(int *dist, float *loc) { base= FIRSTBASE; for ( base = FIRSTBASE; base != NULL; base = base->next ) { - if ( TESTBASE(base) && base != BASACT ) { + if ( base != BASACT && BASE_SELECTABLE(base) && (base->flag & SELECT) == selected ) { Object *ob = base->object; if (ob->type == OB_MESH) { diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index f3801342b3a..88df4c8d34f 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -198,6 +198,16 @@ static void init_userdef_file(void) if(U.flag & USER_CUSTOM_RANGE) vDM_ColorBand_store(&U.coba_weight); /* signal for derivedmesh to use colorband */ + /* Auto-keyframing settings */ + if(U.autokey_mode == 0) { + /* AUTOKEY_MODE_NORMAL - AUTOKEY_ON = x <==> 3 - 1 = 2 */ + U.autokey_mode |= 2; + + if(U.flag & (1<<15)) U.autokey_flag |= AUTOKEY_FLAG_INSERTAVAIL; + if(U.flag & (1<<19)) U.autokey_flag |= AUTOKEY_FLAG_INSERTNEEDED; + if(G.flags & (1<<30)) U.autokey_flag |= AUTOKEY_FLAG_AUTOMATKEY; + } + if (G.main->versionfile <= 191) { strcpy(U.plugtexdir, U.textudir); strcpy(U.sounddir, "/"); diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 52f9ff06227..655fa59a4c1 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -1300,8 +1300,7 @@ void initlocalview() if(G.vd->localvd) return; - min[0]= min[1]= min[2]= 1.0e10; - max[0]= max[1]= max[2]= -1.0e10; + INIT_MINMAX(min, max); locallay= free_localbit(); @@ -1396,9 +1395,7 @@ void centerview() /* like a localview without local! */ float new_ofs[3]; float new_dist; - - min[0]= min[1]= min[2]= 1.0e10; - max[0]= max[1]= max[2]= -1.0e10; + INIT_MINMAX(min, max); if (G.f & G_WEIGHTPAINT) { /* hardcoded exception, we look for the one selected armature */ @@ -1577,8 +1574,7 @@ void view3d_home(int center) max[0]= max[1]= max[2]= 0.0; } else { - min[0]= min[1]= min[2]= 1.0e10; - max[0]= max[1]= max[2]= -1.0e10; + INIT_MINMAX(min, max); } for(base= FIRSTBASE; base; base= base->next) {