svn merge -r 13382:13415 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Sat, 26 Jan 2008 21:54:09 +0000 (21:54 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Sat, 26 Jan 2008 21:54:09 +0000 (21:54 +0000)
46 files changed:
release/scripts/lightwave_import.py
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/BKE_utildefines.h
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenlib/intern/storage.c
source/blender/blenloader/intern/readfile.c
source/blender/include/BDR_sculptmode.h
source/blender/include/BIF_transform.h
source/blender/include/butspace.h
source/blender/include/transform.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_particle_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/python/api2_2x/doc/Render.py
source/blender/python/api2_2x/sceneRender.c
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/occlusion.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/strand.h
source/blender/render/intern/include/zbuf.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/occlusion.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/sss.c
source/blender/render/intern/source/strand.c
source/blender/render/intern/source/zbuf.c
source/blender/src/buttons_object.c
source/blender/src/buttons_scene.c
source/blender/src/buttons_shading.c
source/blender/src/drawaction.c
source/blender/src/editaction.c
source/blender/src/editconstraint.c
source/blender/src/editipo.c
source/blender/src/editmesh_tools.c
source/blender/src/editnode.c
source/blender/src/editobject.c
source/blender/src/editseq.c
source/blender/src/header_view3d.c
source/blender/src/outliner.c
source/blender/src/previewrender.c
source/blender/src/sculptmode-stroke.c
source/blender/src/sculptmode.c
source/blender/src/transform.c

index 24e072f018a011315662f3d7a7dbbd39e8a775d4..2049fbd23802425b4ba0746236c440406dfd6395 100644 (file)
@@ -656,7 +656,12 @@ def read_clip(lwochunk, dir_part):
 # ima, IMAG, g_IMAG refers to clip dictionary 'ID' entries: refer to blok and surf
        clip_dict = {}
        data = cStringIO.StringIO(lwochunk.read())
-       image_index, = struct.unpack(">L", data.read(4))
+       data_str = data.read(4)
+       if len(data_str) < 4: # can be zero also??? :/
+               # Should not happen but lw can import so we should too
+               return 
+       
+       image_index, = struct.unpack(">L", data_str)
        clip_dict['ID'] = image_index
        i = 4
        while(i < lwochunk.chunksize):
@@ -1634,11 +1639,11 @@ def main():
                return
        
        Blender.Window.FileSelector(read, "Import LWO", '*.lwo')
-       
 
 if __name__=='__main__':
        main()
 
+
 # Cams debugging lwo loader
 """
 TIME= Blender.sys.time()
index af5713b565d88c98c7e8c0fe0343fac062ecc1a2..3358cfbfd2bbd968ab8e7136b85b80fd022cd217 100644 (file)
@@ -215,7 +215,7 @@ void free_keyed_keys(struct ParticleSystem *psys);
 void psys_free(struct Object * ob, struct ParticleSystem * psys);
 void psys_free_children(struct ParticleSystem *psys);
 
-void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy);
+void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset);
 void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
 int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot);
 int psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
index d08f42375ac785f6456cdbf6e6487a924f4dd392..fc22f6787b130f2be64dc05bf3716f7c7bc483a7 100644 (file)
 #define VECADD(v1,v2,v3)       {*(v1)= *(v2) + *(v3); *(v1+1)= *(v2+1) + *(v3+1); *(v1+2)= *(v2+2) + *(v3+2);}
 #define VECSUB(v1,v2,v3)       {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1); *(v1+2)= *(v2+2) - *(v3+2);}
 #define VECADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac);}
+#define QUATADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac); *(v1+3)= *(v2+3) + *(v3+3)*(fac);}
 
 #define INPR(v1, v2)           ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] )
 
index 7d7180da27103650bb43116d1c1e2a0659826956..38f25b54fd8707407814cd119af479b7018a6e39 100644 (file)
@@ -2382,6 +2382,118 @@ static bConstraintTypeInfo CTI_LOCKTRACK = {
        locktrack_evaluate /* evaluate */
 };
 
+/* ---------- Limit Distance Constraint ----------- */
+
+static void distlimit_new_data (void *cdata)
+{
+       bDistLimitConstraint *data= (bDistLimitConstraint *)cdata;
+       
+       data->dist= 0.0;
+}
+
+static void distlimit_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bDistLimitConstraint *data= con->data;
+               bConstraintTarget *ct;
+               
+               /* standard target-getting macro for single-target constraints */
+               SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
+       }
+}
+
+static void distlimit_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bDistLimitConstraint *data= con->data;
+               bConstraintTarget *ct= list->first;
+               
+               /* the following macro is used for all standard single-target constraints */
+               SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
+       }
+}
+
+static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bDistLimitConstraint *data= con->data;
+       bConstraintTarget *ct= targets->first;
+       
+       /* only evaluate if there is a target */
+       if (VALID_CONS_TARGET(ct)) {
+               float dvec[3], dist=0.0f, sfac=1.0f;
+               short clamp_surf= 0;
+               
+               /* calculate our current distance from the target */
+               dist= VecLenf(cob->matrix[3], ct->matrix[3]);
+               
+               /* set distance (flag is only set when user demands it) */
+               if (data->dist == 0)
+                       data->dist= dist;
+               
+               /* check if we're which way to clamp from, and calculate interpolation factor (if needed) */
+               if (data->mode == LIMITDIST_OUTSIDE) {
+                       /* if inside, then move to surface */
+                       if (dist <= data->dist) {
+                               clamp_surf= 1;
+                               sfac= data->dist / dist;
+                       }
+                       /* if soft-distance is enabled, start fading once owner is dist+softdist from the target */
+                       else if (data->flag & LIMITDIST_USESOFT) {
+                               if (dist <= (data->dist + data->soft)) {
+                                       
+                               }
+                       }
+               }
+               else if (data->mode == LIMITDIST_INSIDE) {
+                       /* if outside, then move to surface */
+                       if (dist >= data->dist) {
+                               clamp_surf= 1;
+                               sfac= data->dist / dist;
+                       }
+                       /* if soft-distance is enabled, start fading once owner is dist-soft from the target */
+                       else if (data->flag & LIMITDIST_USESOFT) {
+                               // FIXME: there's a problem with "jumping" when this kicks in
+                               if (dist >= (data->dist - data->soft)) {
+                                       sfac = data->soft*(1.0 - exp(-(dist - data->dist)/data->soft)) + data->dist;
+                                       sfac /= dist;
+                                       
+                                       clamp_surf= 1;
+                               }
+                       }
+               }
+               else {
+                       if (IS_EQ(dist, data->dist)==0) {
+                               clamp_surf= 1;
+                               sfac= data->dist / dist;
+                       }
+               }
+               
+               /* clamp to 'surface' (i.e. move owner so that dist == data->dist) */
+               if (clamp_surf) {
+                       /* simply interpolate along line formed by target -> owner */
+                       VecLerpf(dvec, ct->matrix[3], cob->matrix[3], sfac);
+                       
+                       /* copy new vector onto owner */
+                       VECCOPY(cob->matrix[3], dvec);
+               }
+       }
+}
+
+static bConstraintTypeInfo CTI_DISTLIMIT = {
+       CONSTRAINT_TYPE_DISTLIMIT, /* type */
+       sizeof(bDistLimitConstraint), /* size */
+       "Limit Distance", /* name */
+       "bDistLimitConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       distlimit_new_data, /* new data */
+       distlimit_get_tars, /* get constraint targets */
+       distlimit_flush_tars, /* flush constraint targets */
+       default_get_tarmat, /* get a target matrix */
+       distlimit_evaluate /* evaluate */
+};
+
 /* ---------- Stretch To ------------ */
 
 static void stretchto_new_data (void *cdata)
@@ -3067,12 +3179,12 @@ static void constraints_init_typeinfo () {
        constraintsTypeInfo[11]= &CTI_PYTHON;                   /* Python/Script Constraint */
        constraintsTypeInfo[12]= &CTI_ACTION;                   /* Action Constraint */
        constraintsTypeInfo[13]= &CTI_LOCKTRACK;                /* Locked-Track Constraint */
-       constraintsTypeInfo[14]= NULL;                                  /* 'Distance Limit' Constraint */
+       constraintsTypeInfo[14]= &CTI_DISTLIMIT;                /* Limit Distance Constraint */
        constraintsTypeInfo[15]= &CTI_STRETCHTO;                /* StretchTo Constaint */ 
        constraintsTypeInfo[16]= &CTI_MINMAX;                   /* Floor Constraint */
        constraintsTypeInfo[17]= &CTI_RIGIDBODYJOINT;   /* RigidBody Constraint */
        constraintsTypeInfo[18]= &CTI_CLAMPTO;                  /* ClampTo Constraint */        
-       constraintsTypeInfo[19]= &CTI_TRANSFORM;                /* Transformation Constraint */ 
+       constraintsTypeInfo[19]= &CTI_TRANSFORM;                /* Transformation Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only
index 5b92eb12d4fb664112ff39f9b39488c549b2d659..e09d6a7f06c797b573c2596917e1472210eb8bf2 100644 (file)
@@ -394,6 +394,7 @@ typedef struct ParticleRenderData {
        int winx, winy;
 
        int dosimplify;
+       int timeoffset;
        ParticleRenderElem *elems;
        int *origindex;
 } ParticleRenderData;
@@ -455,13 +456,15 @@ static float psys_render_projected_area(ParticleSystem *psys, float *center, flo
        return area;
 }
 
-void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy)
+void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset)
 {
        ParticleRenderData*data;
        ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
 
        if(!G.rendering)
                return;
+       if(psys->renderdata)
+               return;
 
        data= MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
 
@@ -489,6 +492,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float
        data->winx= winx;
        data->winy= winy;
 
+       data->timeoffset= timeoffset;
+
        psys->renderdata= data;
 }
 
@@ -554,7 +559,13 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
 
        if(part->draw_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
                return tot;
-       if(!ctx->psys->renderdata || !(part->simplify_flag & PART_SIMPLIFY_ENABLE))
+       if(!ctx->psys->renderdata)
+               return tot;
+
+       data= ctx->psys->renderdata;
+       if(data->timeoffset)
+               return 0;
+       if(!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
                return tot;
 
        mvert= dm->getVertArray(dm);
@@ -571,7 +582,6 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
        facetotvert= MEM_callocN(sizeof(int)*totorigface, "SimplifyFaceArea");
        elems= MEM_callocN(sizeof(ParticleRenderElem)*totorigface, "SimplifyFaceElem");
 
-       data= ctx->psys->renderdata;
        if(data->elems)
                MEM_freeN(data->elems);
 
@@ -2076,7 +2086,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
                        rough_t = t;
 
                if(part->rough1 != 0.0 && pa_rough1 != 0.0)
-                               do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state);
+                       do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state);
 
                if(part->rough2 != 0.0 && pa_rough2 != 0.0)
                        do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state);
@@ -2262,6 +2272,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
        float sel_col[3];
        float nosel_col[3];
        float length, vec[3];
+       float *vg_effector= NULL, effector=0.0f;
 
        /* we don't have anything valid to create paths from so let's quit here */
        if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0)
@@ -2310,6 +2321,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
        ma= give_current_material(ob, psys->part->omat);
        if(ma && (psys->part->draw & PART_DRAW_MAT_COL))
                VECCOPY(col, &ma->r)
+       
+       if(psys->part->from!=PART_FROM_PARTICLE)
+               vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR);
 
        /*---first main loop: create all actual particles' paths---*/
        for(i=0,pa=psys->particles; i<totpart; i++, pa++){
@@ -2446,6 +2460,10 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
                VecSubf(vec,(cache[i]+1)->co,cache[i]->co);
                length = VecLength(vec);
 
+               effector= 1.0f;
+               if(vg_effector)
+                       effector*= psys_interpolate_value_from_verts(psmd->dm,psys->part->from,pa->num,pa->fuv,vg_effector);
+
                for(k=0, ca=cache[i]; k<=steps; k++, ca++) {
                        /* apply effectors */
                        if(edit==0 && k) {
@@ -2458,7 +2476,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
 
                                do_effectors(i, pa, &eff_key, ob, psys, force, vel, dfra, cfra);
 
-                               VecMulf(force, pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps);
+                               VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps);
 
                                VecAddf(force, force, vec);
 
@@ -2571,6 +2589,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
                end_latt_deform();
                psys->lattice=0;
        }
+
+       if(vg_effector)
+               MEM_freeN(vg_effector);
 }
 /************************************************/
 /*                     Particle Key handling                           */
@@ -3517,7 +3538,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
                        part->kink_amp, part->kink, part->kink_axis, ob->obmat);
 
                if(part->rough1 != 0.0)
-                               do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state);
+                       do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state);
 
                if(part->rough2 != 0.0)
                        do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state);
index e71c4f90d483a4473d3ad3fc336fa02b41877934..3db42f091d4267c16c53ee6c66bf8b165d77419d 100644 (file)
@@ -2724,7 +2724,8 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti
                force[0]=force[1]=force[2]=0.0;
                tvel[0]=tvel[1]=tvel[2]=0.0;
                /* add effectors */
-               do_effectors(pa_no,pa,states+i,ob,psys,force,tvel,dfra,fra);
+               if(part->type != PART_HAIR)
+                       do_effectors(pa_no,pa,states+i,ob,psys,force,tvel,dfra,fra);
 
                /* calculate air-particle interaction */
                if(part->dragfac!=0.0f){
index c6011bb6fd999dac80e6c6312793449bd51b5939..5902b7dd68a54101ecfc97be262cdc27eb5cb524 100644 (file)
@@ -50,7 +50,9 @@
 #include <time.h>
 #include <sys/stat.h>
 
-#if !defined(linux) && (defined(__sgi) || defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__))
+#if defined (__sun__) || defined (__sun)
+#include <sys/statvfs.h> /* Other modern unix os's should probably use this also */
+#elif !defined(linux) && (defined(__sgi) || defined(__sparc) || defined(__sparc__))
 #include <sys/statfs.h>
 #endif
 
@@ -179,7 +181,12 @@ double BLI_diskfree(char *dir)
 
        return (double) (freec*bytesps*sectorspc);
 #else
+
+#if defined (__sun__) || defined (__sun)
+       struct statvfs disk;
+#else
        struct statfs disk;
+#endif
        char name[FILE_MAXDIR],*slash;
        int len = strlen(dir);
        
@@ -199,12 +206,12 @@ double BLI_diskfree(char *dir)
 #ifdef __BeOS
        return -1;
 #endif
-#if !defined(linux) && (defined (__sgi) || defined (__sun__) || defined (__sun) || defined(__sparc) || defined(__sparc__))
 
-       if (statfs(name, &disk, sizeof(struct statfs), 0)){
-               /* printf("diskfree: Couldn't get information about %s.\n",dir); */
-               return(-1);
-       }
+#if defined (__sun__) || defined (__sun)
+       if (statvfs(name, &disk)) return(-1);   
+#elif !defined(linux) && (defined (__sgi) || defined(__sparc) || defined(__sparc__))
+       /* WARNING - This may not be supported by geeneric unix os's - Campbell */
+       if (statfs(name, &disk, sizeof(struct statfs), 0)) return(-1);
 #endif
 
        return ( ((double) disk.f_bsize) * ((double) disk.f_bfree));
index c725b3d63ac9ab714bfcf7e1a0ecb8238ee8c496..a9d2e7d05a1c1fb633d4f3acb6356726140ac7a4 100644 (file)
@@ -1754,6 +1754,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                data->tar = newlibadr(fd, id->lib, data->tar);
                        }
                        break;
+               case CONSTRAINT_TYPE_DISTLIMIT:
+                       {
+                               bDistLimitConstraint *data;
+                               data= ((bDistLimitConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       }
+                       break;
                case CONSTRAINT_TYPE_NULL:
                        break;
                }
@@ -1767,6 +1774,7 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
        link_list(fd, lb);
        for (cons=lb->first; cons; cons=cons->next) {
                cons->data = newdataadr(fd, cons->data);
+               
                if (cons->type == CONSTRAINT_TYPE_PYTHON) {
                        bPythonConstraint *data= cons->data;
                        link_list(fd, &data->targets);
@@ -7844,6 +7852,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
                                expand_doit(fd, mainvar, data->tar);
                        }
                        break;
+               case CONSTRAINT_TYPE_DISTLIMIT: 
+                       {
+                               bDistLimitConstraint *data = (bDistLimitConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
+                       }
+                       break;
                default:
                        break;
                }
index 8b0b65be4dea655121eba318efac778c6bec9b47..e36b867461295e5a598f002423e959819cf8cc05 100644 (file)
@@ -35,8 +35,8 @@
 #include "BKE_sculpt.h"
 
 struct uiBlock;
+struct BrushAction;
 struct BrushData;
-struct EditData;
 struct IndexNode;
 struct KeyBlock;
 struct Mesh;
@@ -65,7 +65,7 @@ void sculpt_stroke_draw();
 void sculpt_radialcontrol_start(int mode);
 
 struct BrushData *sculptmode_brush(void);
-void do_symmetrical_brush_actions(struct EditData *e, short *, short *);
+void do_symmetrical_brush_actions(struct BrushAction *a, short *, short *);
 
 void sculptmode_update_tex(void);
 char sculpt_modifiers_active(struct Object *ob);
@@ -76,8 +76,8 @@ void set_sculptmode(void);
 void sculpt_stroke_new(const int max);
 void sculpt_stroke_free();
 void sculpt_stroke_add_point(const short x, const short y);
-void sculpt_stroke_apply(struct EditData *);
-void sculpt_stroke_apply_all(struct EditData *e);
+void sculpt_stroke_apply(struct BrushAction *);
+void sculpt_stroke_apply_all(struct BrushAction *);
 void sculpt_stroke_draw();
 
 
index c8e2a4832ab0724a1301b36b564083e11313c095..a0f991f2631aeabb3d22321199ad25a733147f93 100644 (file)
 #define CTX_NO_PET                     4
 #define CTX_TWEAK                      8
 #define CTX_NO_MIRROR          16
+#define CTX_AUTOCONFIRM                32
 
 void initTransform(int mode, int context);
 void Transform(void);
-void Mirror(short mode);
 
 /* Standalone call to get the transformation center corresponding to the current situation
  * returns 1 if successful, 0 otherwise (usually means there's no selection)
index a7759f799ba4e7f84849c4fdc95580a0bc0d3874..28a58f7f9e4e40ac32bffaef615370b103278acf 100644 (file)
@@ -700,7 +700,7 @@ enum {
        B_CONSTRAINT_ADD_ACTION,
        B_CONSTRAINT_ADD_LOCKTRACK,
        B_CONSTRAINT_ADD_FOLLOWPATH,
-       B_CONSTRAINT_ADD_DISTANCELIMIT,
+       B_CONSTRAINT_ADD_DISTLIMIT,
        B_CONSTRAINT_ADD_STRETCHTO,
        B_CONSTRAINT_ADD_LOCLIMIT,
        B_CONSTRAINT_ADD_ROTLIMIT,
index 30b9bbf3f51ba945af7240fe6b84010febdad38e..48e840a7128dde94e315ebe29852a21f6d8c7282 100644 (file)
@@ -363,6 +363,9 @@ int TimeScale(TransInfo *t, short mval[2]);
 void initBakeTime(TransInfo *t);
 int BakeTime(TransInfo *t, short mval[2]);
 
+void initMirror(TransInfo *t);
+int Mirror(TransInfo *t, short mval[2]);
+
 /*********************** transform_conversions.c ********** */
 struct ListBase;
 void flushTransIpoData(TransInfo *t);
index 4ae8d6b39e6a1944c766bd390a5267e79bba92ba..2bcf2412588b5846f76888bd3df76d22bdefe015 100644 (file)
@@ -307,6 +307,19 @@ typedef struct bSizeLimitConstraint {
        short           flag2;
 } bSizeLimitConstraint;
 
+/* Limit Distance Constraint */
+typedef struct bDistLimitConstraint {
+       Object          *tar;
+       char            subtarget[32];
+       
+       float           dist;                   /* distance (radius of clamping sphere) from target */
+       float           soft;                   /* distance from clamping-sphere to start applying 'fade' */
+       
+       short           flag;                   /* settings */
+       short           mode;                   /* how to limit in relation to clamping sphere */
+       int             pad;
+} bDistLimitConstraint;
+
 /* ------------------------------------------ */
 
 /* bConstraint->type 
@@ -328,13 +341,14 @@ typedef enum B_CONSTAINT_TYPES {
        CONSTRAINT_TYPE_PYTHON,                         /* Unimplemented no longer :) - Aligorith. Scripts */
        CONSTRAINT_TYPE_ACTION,
        CONSTRAINT_TYPE_LOCKTRACK,                      /* New Tracking constraint that locks an axis in place - theeth */
-       CONSTRAINT_TYPE_DISTANCELIMIT,          /* was never properly coded - removed! */
+       CONSTRAINT_TYPE_DISTLIMIT,                      /* limit distance */
        CONSTRAINT_TYPE_STRETCHTO,                      /* claiming this to be mine :) is in tuhopuu bjornmose */ 
        CONSTRAINT_TYPE_MINMAX,                         /* floor constraint */
        CONSTRAINT_TYPE_RIGIDBODYJOINT,         /* rigidbody constraint */
        CONSTRAINT_TYPE_CLAMPTO,                        /* clampto constraint */        
        CONSTRAINT_TYPE_TRANSFORM,                      /* transformation (loc/rot/size -> loc/rot/size) constraint */  
        
+       
        /* NOTE: everytime a new constraint is added, update this */
        NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_TRANSFORM
 } B_CONSTRAINT_TYPES; 
@@ -478,6 +492,15 @@ typedef enum B_CONSTRAINTCHANNEL_FLAG {
 #define LIMIT_NOPARENT 0x01
        /* for all Limit constraints - allow to be used during transform? */
 #define LIMIT_TRANSFORM 0x02
+
+/* distance limit constraint */
+       /* bDistLimitConstraint->flag */
+#define LIMITDIST_USESOFT              (1<<0)
+
+       /* bDistLimitConstraint->mode */
+#define LIMITDIST_INSIDE               0
+#define LIMITDIST_OUTSIDE              1
+#define LIMITDIST_ONSURFACE            2
        
 /* python constraint -> flag */
 #define PYCON_USETARGETS       0x01
index d39fbbbc679ddda30911f3f61205731ca5a66dab..6fcedcd934a55a2ad07d7b2cb1c8390dc08838c1 100644 (file)
@@ -415,7 +415,7 @@ typedef struct ParticleSystem{
 #define PARS_ALIVE                     3
 
 /* psys->vg */
-#define PSYS_TOT_VG                    11
+#define PSYS_TOT_VG                    12
 
 #define PSYS_VG_DENSITY                0
 #define PSYS_VG_VEL                    1
@@ -428,6 +428,7 @@ typedef struct ParticleSystem{
 #define PSYS_VG_SIZE           8
 #define PSYS_VG_TAN                    9
 #define PSYS_VG_ROT                    10
+#define PSYS_VG_EFFECTOR       11
 
 /* part->boidrules */
 #define BOID_TOT_RULES         8
index b342bc5afe849410958d2e7f68aee8ea46d09c9d..8bdea93b1f416505ff9e1338fbfa963bb0dfe042 100644 (file)
@@ -120,7 +120,11 @@ typedef struct SceneRenderLayer {
        struct Group *light_override;
        
        unsigned int lay;               /* scene->lay itself has priority over this */
+       unsigned int lay_zmask; /* has to be after lay, this is for Z-masking */
        int layflag;
+       
+       int pad;
+       
        int passflag;                   /* pass_xor has to be after passflag */
        int pass_xor;
 } SceneRenderLayer;
@@ -137,6 +141,7 @@ typedef struct SceneRenderLayer {
 #define SCE_LAY_ALL_Z  0x8000
 #define SCE_LAY_XOR            0x10000
 #define SCE_LAY_DISABLE        0x20000
+#define SCE_LAY_ZMASK  0x40000
 
 /* srl->passflag */
 #define SCE_PASS_COMBINED      1
index 7ab3d7b90a9b43c506dd48abc406b91d01d78c9b..ddcc5a239af97f57d2a3eb552ee83aa32633dbac 100644 (file)
@@ -432,6 +432,15 @@ class RenderData:
     sequences.
     """
 
+  def getFrameFilename( frame ):
+    """
+    Get the filename used for the remdered image.
+    @type frame: int
+    @param path: the frame to use in the filename, if no argument given, use the current frame.
+    @rtype: string
+    @return: Returns the filename that blender would render to, taking into account output path, extension and frame number.
+    """
+
   def setBackbufPath(path):
     """
     Set the path to a background image and load it.
index ec160ddf4cee6d5fbf32552d31202a310d22a80d..f5861995073fe500b4d6cb18a56033256b2a99b8 100644 (file)
@@ -2201,6 +2201,19 @@ static int RenderData_setRenderPath( BPy_RenderData * self, PyObject * value )
        return 0;
 }
 
+static PyObject *RenderData_getFrameFilename( BPy_RenderData * self, PyObject *args )
+{
+       char name[FILE_MAX];
+       int frame = self->renderContext->cfra;
+       
+       if( !PyArg_ParseTuple( args, "|i", &( frame ) ) )
+               return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
+                                                                               "expected int argument or nothing" ) );
+       
+       BKE_makepicstring(name, self->renderContext->pic, frame, self->renderContext->imtype);
+       return PyString_FromString( name );
+}
+
 PyObject *RenderData_getBackbufPath( BPy_RenderData * self )
 {
        return PyString_FromString( self->renderContext->backbuf );
@@ -2726,6 +2739,9 @@ static PyMethodDef BPy_RenderData_methods[] = {
        {"getRenderPath", ( PyCFunction ) RenderData_getRenderPath,
         METH_NOARGS,
         "() - get the path to directory where rendered images will go"},
+       {"getFrameFilename", ( PyCFunction ) RenderData_getFrameFilename,
+        METH_VARARGS,
+        "() - get the filename of the frame this will be rendered, taking into account extension and frame range"},
        {"setBackbufPath", ( PyCFunction ) RenderData_SetBackbufPath,
         METH_VARARGS,
         "(string) - get/set the path to a background image and load it"},
index 846b0867a765917a768acca46892301b873c67ef..de12f75300eeed143ca88321a122614d0da7f912 100644 (file)
@@ -73,7 +73,7 @@ typedef struct RenderLayer {
        
        /* copy of RenderData */
        char name[RE_MAXNAME];          
-       unsigned int lay;                       
+       unsigned int lay, lay_zmask;
        int layflag, passflag, pass_xor;                
        
        struct Material *mat_override;
index 3f10d50ab2e894e49dd94fa3a59d256bfa553b02..646ad30b318bb813d53d95d5e628bc9f1bc494f0 100644 (file)
@@ -45,7 +45,5 @@ void sample_occ(struct Render *re, struct ShadeInput *shi);
 void cache_occ_samples(struct Render *re, struct RenderPart *pa, struct ShadeSample *ssamp);
 void free_occ_samples(struct Render *re, struct RenderPart *pa);
 
-void *cache_occ_mesh(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4]);
-
 #endif
 
index 46b5face22a7962be7b1089ad82184b571fdb12f..16c46ec550feed0a44e328cf5a208874d7d7189c 100644 (file)
@@ -161,7 +161,7 @@ struct Render
 
        /* occlusion tree */
        void *occlusiontree;
-       ListBase occlusionmesh;
+       ListBase strandsurface;
        
        /* use this instead of R.r.cfra */
        float cfra;     
@@ -337,6 +337,18 @@ typedef struct StrandVert {
        float strandco;
 } StrandVert;
 
+typedef struct StrandSurface {
+       struct StrandSurface *next, *prev;
+       ObjectRen obr;
+       int (*face)[4];
+       float (*co)[3];
+       /* for occlusion caching */
+       float (*col)[3];                                        /* for occlusion */
+       /* for speedvectors */
+       float (*prevco)[3], (*nextco)[3];
+       int totvert, totface;
+} StrandSurface;
+
 typedef struct StrandBuffer {
        struct StrandBuffer *next, *prev;
        struct StrandVert *vert;
@@ -344,7 +356,7 @@ typedef struct StrandBuffer {
 
        struct ObjectRen *obr;
        struct Material *ma;
-       void *occlusionmesh;
+       struct StrandSurface *surface;
        unsigned int lay;
        int overrideuv;
        int flag, maxdepth;
index f1c0b6d1e3a521251af2a5f1481a22e68a690fc5..8e34fa273426bc0028f6bdca41b992e21254b22b 100644 (file)
@@ -44,6 +44,9 @@ struct RenderBuckets;
 struct RenderPrimitiveIterator;
 struct ZSpan;
 struct ObjectInstanceRen;
+struct StrandSurface;
+struct DerivedMesh;
+struct ObjectRen;
 
 typedef struct StrandPoint {
        /* position within segment */
@@ -89,6 +92,9 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint);
 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 StrandSurface *cache_strand_surface(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4], int timeoffset);
+void free_strand_surface(struct Render *re);
+
 struct RenderBuckets *init_buckets(struct Render *re);
 void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim);
 void free_buckets(struct RenderBuckets *buckets);
index 1d202fa45fa5eb224bf246c36a8680070cfeb39d..8feb18a7ab8c0c4be60208f33e9c14fb746f489c 100644 (file)
@@ -48,7 +48,7 @@ void projectverto(float *v1, float winmat[][4], float *adr);
 int testclip(float *v); 
 
 void zbuffer_shadow(struct Render *re, float winmat[][4], struct LampRen *lar, int *rectz, int size, float jitx, float jity);
-void zbuffer_solid(struct RenderPart *pa, unsigned int layer, short layflag, void (*fillfunc)(struct RenderPart*, struct ZSpan*, int, void*), void *data);
+void zbuffer_solid(struct RenderPart *pa, struct RenderLayer *rl, void (*fillfunc)(struct RenderPart*, struct ZSpan*, int, void*), void *data);
 
 unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass, struct ListBase *psmlist);
 unsigned short *zbuffer_strands_shade(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, float *pass);
index 69ae280dc4c73dabd0001145d8b7a4aebf54e195..7a8d151c73824fb08f4383424df12fb7be4e8a63 100644 (file)
 #include "radio.h"
 #include "shadbuf.h"
 #include "shading.h"
+#include "strand.h"
 #include "texture.h"
 #include "sss.h"
 #include "zbuf.h"
@@ -1465,7 +1466,7 @@ static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mat
                if(har) har->lay= obr->ob->lay;
        }
 }
-static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys)
+static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset)
 {
        Object *ob= obr->ob;
        Object *tob=0, *bb_ob=re->scene->camera;
@@ -1487,7 +1488,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        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, simplify[2];
-       int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0, doapproxao = 0;
+       int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0, dosurfacecache = 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}, num;
        char **uv_name=0;
@@ -1647,9 +1648,11 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
                                svert= strandbuf->vert;
 
-                               if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
+                               if(re->r.mode & R_SPEED)
+                                       dosurfacecache= 1;
+                               else if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
                                        if(ma->amb != 0.0f)
-                                               doapproxao= 1;
+                                               dosurfacecache= 1;
                        }
                }
        }
@@ -1827,7 +1830,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                VECCOPY(snor, surfnor);
                        }
 
-                       if(doapproxao && num >= 0) {
+                       if(dosurfacecache && num >= 0) {
                                int *facenum= RE_strandren_get_face(obr, strand, 1);
                                *facenum= num;
                        }
@@ -1931,8 +1934,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                        break;
        }
 
-       if(doapproxao)
-               strandbuf->occlusionmesh= cache_occ_mesh(re, obr, psmd->dm, mat);
+       if(dosurfacecache)
+               strandbuf->surface= cache_strand_surface(re, obr, psmd->dm, mat, timeoffset);
 
 /* 4. clean up */
        if(ma) do_mat_ipo(ma);
@@ -2543,7 +2546,7 @@ static void init_render_surf(Render *re, ObjectRen *obr)
        freedisplist(&displist);
 }
 
-static void init_render_curve(Render *re, ObjectRen *obr, int only_verts)
+static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
 {
        Object *ob= obr->ob;
        Curve *cu;
@@ -2621,7 +2624,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int only_verts)
                                }
                        }
                        
-                       if(only_verts==0) {
+                       if(timeoffset==0) {
                                startvlak= obr->totvlak;
                                index= dl->index;
                                for(a=0; a<dl->parts; a++, index+=3) {
@@ -2674,7 +2677,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int only_verts)
                                        }
                                }
 
-                               if(dl->bevelSplitFlag || only_verts==0) {
+                               if(dl->bevelSplitFlag || timeoffset==0) {
                                        startvlak= obr->totvlak;
 
                                        for(a=0; a<dl->parts; a++) {
@@ -2890,7 +2893,7 @@ static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge,
        }
 }
 
-static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts)
+static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 {
        Object *ob= obr->ob;
        Mesh *me;
@@ -2949,12 +2952,12 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts)
        /* check autosmooth and displacement, we then have to skip only-verts optimize */
        do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
        if(do_autosmooth)
-               only_verts= 0;
+               timeoffset= 0;
        if(test_for_displace(re, ob ) )
-               only_verts= 0;
+               timeoffset= 0;
        
        mask= CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL;
-       if(!only_verts)
+       if(!timeoffset)
                if(need_orco)
                        mask |= CD_MASK_ORCO;
 
@@ -3020,7 +3023,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts)
                        }
                }
                
-               if(!only_verts) {
+               if(!timeoffset) {
                        /* store customdata names, because DerivedMesh is freed */
                        RE_set_customdata_names(obr, &dm->faceData);
                        
@@ -3174,7 +3177,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int only_verts)
                }
        }
        
-       if(!only_verts) {
+       if(!timeoffset) {
                if (test_for_displace(re, ob ) ) {
                        calc_vertexnormals(re, obr, 0);
                        do_displacement(re, obr);
@@ -3834,7 +3837,7 @@ static void check_non_flat_quads(ObjectRen *obr)
        }
 }
 
-static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts)
+static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset)
 {
        Object *ob= obr->ob;
 
@@ -3845,7 +3848,7 @@ static void finalize_render_object(Render *re, ObjectRen *obr, int only_verts)
                if(ob->type!=OB_MESH && test_for_displace(re, ob)) 
                        do_displacement(re, obr);
        
-               if(!only_verts) {
+               if(!timeoffset) {
                        /* phong normal interpolation can cause error in tracing
                         * (terminator problem) */
                        ob->smoothresh= 0.0;
@@ -3934,7 +3937,7 @@ static ObjectRen *find_dupligroup_dupli(Render *re, Object *ob, int psysindex)
        return NULL;
 }
 
-static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts)
+static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
 {
        Object *ob= obr->ob;
        ParticleSystem *psys;
@@ -3952,20 +3955,20 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts)
                for(psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++)
                        psys= psys->next;
 
-               render_new_particle_system(re, obr, psys);
+               render_new_particle_system(re, obr, psys, timeoffset);
        }
        else {
                if ELEM(ob->type, OB_FONT, OB_CURVE)
-                       init_render_curve(re, obr, only_verts);
+                       init_render_curve(re, obr, timeoffset);
                else if(ob->type==OB_SURF)
                        init_render_surf(re, obr);
                else if(ob->type==OB_MESH)
-                       init_render_mesh(re, obr, only_verts);
+                       init_render_mesh(re, obr, timeoffset);
                else if(ob->type==OB_MBALL)
                        init_render_mball(re, obr);
        }
 
-       finalize_render_object(re, obr, only_verts);
+       finalize_render_object(re, obr, timeoffset);
        
        re->totvert += obr->totvert;
        re->totvlak += obr->totvlak;
@@ -3973,7 +3976,7 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int only_verts)
        re->totstrand += obr->totstrand;
 }
 
-static void add_render_object(Render *re, Object *ob, Object *par, int index, int only_verts, int instanceable)
+static void add_render_object(Render *re, Object *ob, Object *par, int index, int timeoffset, int instanceable)
 {
        ObjectRen *obr;
        ParticleSystem *psys;
@@ -3985,7 +3988,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in
                show_emitter= 0;
                for(psys=ob->particlesystem.first; psys; psys=psys->next) {
                        show_emitter += psys->part->draw & PART_DRAW_EMITTER;
-                       psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy);
+                       psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
                }
 
                /* if no psys has "show emitter" selected don't render emitter */
@@ -4000,7 +4003,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in
                        obr->flag |= R_INSTANCEABLE;
                        Mat4CpyMat4(obr->obmat, ob->obmat);
                }
-               init_render_object_data(re, obr, only_verts);
+               init_render_object_data(re, obr, timeoffset);
 
                /* only add instance for objects that have not been used for dupli */
                if(!(ob->transflag & OB_RENDER_DUPLI))
@@ -4018,7 +4021,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in
                                obr->flag |= R_INSTANCEABLE;
                                Mat4CpyMat4(obr->obmat, ob->obmat);
                        }
-                       init_render_object_data(re, obr, only_verts);
+                       init_render_object_data(re, obr, timeoffset);
                        psys_render_restore(ob, psys);
 
                        /* only add instance for objects that have not been used for dupli */
@@ -4032,7 +4035,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, int index, in
 
 /* par = pointer to duplicator parent, needed for object lookup table */
 /* index = when duplicater copies same object (particle), the counter */
-static void init_render_object(Render *re, Object *ob, Object *par, int index, int only_verts, int instanceable)
+static void init_render_object(Render *re, Object *ob, Object *par, int index, int timeoffset, int instanceable)
 {
        static double lasttime= 0.0;
        double time;
@@ -4041,7 +4044,7 @@ static void init_render_object(Render *re, Object *ob, Object *par, int index, i
        if(ob->type==OB_LAMP)
                add_render_lamp(re, ob);
        else if(render_object_type(ob->type))
-               add_render_object(re, ob, par, index, only_verts, instanceable);
+               add_render_object(re, ob, par, index, timeoffset, instanceable);
        else {
                MTC_Mat4MulMat4(mat, ob->obmat, re->viewmat);
                MTC_Mat4Invert(ob->imat, mat);
@@ -4119,6 +4122,7 @@ void RE_Database_Free(Render *re)
 
        free_sss(re);
        free_occ(re);
+       free_strand_surface(re);
        
        re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0;
        re->i.convertdone= 0;
@@ -4174,7 +4178,7 @@ 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)
+static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, 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 */
@@ -4190,7 +4194,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int level, int ena
                for(psys=ob->particlesystem.first; psys; psys=psys->next) {
                        if(ELEM(psys->part->draw_as, PART_DRAW_OB, PART_DRAW_GR)) {
                                if(enable)
-                                       psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy);
+                                       psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
                                else
                                        psys_render_restore(ob, psys);
                        }
@@ -4212,10 +4216,10 @@ static void dupli_render_particle_set(Render *re, Object *ob, int level, int ena
        group= ob->dup_group;
 
        for(go= group->gobject.first; go; go= go->next)
-               dupli_render_particle_set(re, go->ob, level+1, enable);
+               dupli_render_particle_set(re, go->ob, timeoffset, level+1, enable);
 }
 
-static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int only_verts)
+static void database_init_objects(Render *re, unsigned int lay, int nolamps, int onlyselected, Object *actob, int timeoffset)
 {
        Base *base;
        Object *ob;
@@ -4243,16 +4247,16 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int
                if(ob->flag & OB_DONE) {
                        if(ob->transflag & OB_RENDER_DUPLI)
                                if(allow_render_object(ob, nolamps, onlyselected, actob))
-                                       init_render_object(re, ob, NULL, 0, only_verts, 1);
+                                       init_render_object(re, ob, NULL, 0, timeoffset, 1);
                }
                else if((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->scene->lay)) ) {
                        if((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) {
                                DupliObject *dob;
                                ListBase *lb;
 
-                               dupli_render_particle_set(re, ob, 0, 1);
+                               dupli_render_particle_set(re, ob, timeoffset, 0, 1);
                                lb= object_duplilist(sce, ob);
-                               dupli_render_particle_set(re, ob, 0, 0);
+                               dupli_render_particle_set(re, ob, timeoffset, 0, 0);
 
                                for(dob= lb->first; dob; dob= dob->next) {
                                        Object *obd= dob->ob;
@@ -4294,7 +4298,7 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int
                                                        }
                                                }
                                                else
-                                                       init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated);
+                                                       init_render_object(re, obd, ob, dob->index, timeoffset, !dob->animated);
 
                                                psysindex= 1;
                                                for(psys=obd->particlesystem.first; psys; psys=psys->next) {
@@ -4319,17 +4323,17 @@ static void database_init_objects(Render *re, unsigned int lay, int nolamps, int
                                                }
                                        }
                                        else
-                                               init_render_object(re, obd, ob, dob->index, only_verts, !dob->animated);
+                                               init_render_object(re, obd, ob, dob->index, timeoffset, !dob->animated);
                                        
                                        if(re->test_break()) break;
                                }
                                free_object_duplilist(lb);
 
                                if(allow_render_object(ob, nolamps, onlyselected, actob))
-                                       init_render_object(re, ob, NULL, 0, only_verts, 0);
+                                       init_render_object(re, ob, NULL, 0, timeoffset, 0);
                        }
                        else if(allow_render_object(ob, nolamps, onlyselected, actob))
-                               init_render_object(re, ob, NULL, 0, only_verts, 0);
+                               init_render_object(re, ob, NULL, 0, timeoffset, 0);
                }
 
                if(re->test_break()) break;
@@ -4513,7 +4517,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, int timeoffset)
        }
        
        /* MAKE RENDER DATA */
-       database_init_objects(re, lay, 0, 0, 0, 1);
+       database_init_objects(re, lay, 0, 0, 0, timeoffset);
        
        if(!re->test_break())
                project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1);
@@ -4608,14 +4612,49 @@ static void calculate_speedvector(float *vectors, int step, float winsq, float w
        }
 }
 
+static float *calculate_strandsurface_speedvectors(Render *re, ObjectInstanceRen *obi, StrandSurface *mesh)
+{
+       float winsq= re->winx*re->winy, winroot= sqrt(winsq), (*winspeed)[4];
+       float ho[4], prevho[4], nextho[4], winmat[4][4], vec[2];
+       int a;
+
+       if(mesh->co && mesh->prevco && mesh->nextco) {
+               if(obi->flag & R_TRANSFORMED)
+                       Mat4MulMat4(winmat, obi->mat, re->winmat);
+               else
+                       Mat4CpyMat4(winmat, re->winmat);
+
+               winspeed= MEM_callocN(sizeof(float)*4*mesh->totvert, "StrandSurfWin");
+
+               for(a=0; a<mesh->totvert; a++) {
+                       projectvert(mesh->co[a], winmat, ho);
+
+                       projectvert(mesh->prevco[a], winmat, prevho);
+                       speedvector_project(NULL, vec, mesh->prevco[a], prevho);
+                       calculate_speedvector(vec, 0, winsq, winroot, mesh->co[a], ho, winspeed[a]);
+
+                       projectvert(mesh->nextco[a], winmat, nextho);
+                       speedvector_project(NULL, vec, mesh->nextco[a], nextho);
+                       calculate_speedvector(vec, 1, winsq, winroot, mesh->co[a], ho, winspeed[a]);
+               }
+
+               return (float*)winspeed;
+       }
+
+       return NULL;
+}
+
 static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *vectors, int step)
 {
        ObjectRen *obr= obi->obr;
        VertRen *ver= NULL;
        StrandRen *strand= NULL;
-       float *speed, ho[4], winmat[4][4];
+       StrandBuffer *strandbuf;
+       StrandSurface *mesh= NULL;
+       float *speed, (*winspeed)[4]=NULL, ho[4], winmat[4][4];
+       float *co1, *co2, *co3, *co4, w[4];
        float winsq= re->winx*re->winy, winroot= sqrt(winsq);
-       int a;
+       int a, *face, *index;
 
        if(obi->flag & R_TRANSFORMED)
                Mat4MulMat4(winmat, obi->mat, re->winmat);
@@ -4634,13 +4673,42 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve
        }
 
        if(obr->strandnodes) {
-               for(a=0; a<obr->totstrand; a++, vectors+=2) {
-                       if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
-                       else strand++;
+               strandbuf= obr->strandbufs.first;
+               mesh= (strandbuf)? strandbuf->surface: NULL;
+
+               /* compute speed vectors at surface vertices */
+               if(mesh)
+                       winspeed= (float(*)[4])calculate_strandsurface_speedvectors(re, obi, mesh);
 
-                       speed= RE_strandren_get_winspeed(obi, strand, 1);
-                       projectvert(strand->vert->co, winmat, ho);
-                       calculate_speedvector(vectors, step, winsq, winroot, strand->vert->co, ho, speed);
+               if(winspeed) {
+                       for(a=0; a<obr->totstrand; a++, vectors+=2) {
+                               if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
+                               else strand++;
+
+                               index= RE_strandren_get_face(obr, strand, 0);
+                               if(index && *index) {
+                                       speed= RE_strandren_get_winspeed(obi, strand, 1);
+
+                                       /* interpolate speed vectors from strand surface */
+                                       face= mesh->face[*index];
+
+                                       co1= mesh->co[face[0]];
+                                       co2= mesh->co[face[1]];
+                                       co3= mesh->co[face[2]];
+                                       co4= (face[3])? mesh->co[face[3]]: NULL;
+
+                                       InterpWeightsQ3Dfl(co1, co2, co3, co4, strand->vert->co, w);
+
+                                       speed[0]= speed[1]= speed[2]= speed[3]= 0.0f;
+                                       QUATADDFAC(speed, speed, winspeed[face[0]], w[0]);
+                                       QUATADDFAC(speed, speed, winspeed[face[1]], w[1]);
+                                       QUATADDFAC(speed, speed, winspeed[face[2]], w[2]);
+                                       if(face[3])
+                                               QUATADDFAC(speed, speed, winspeed[face[3]], w[3]);
+                               }
+                       }
+
+                       MEM_freeN(winspeed);
                }
        }
 }
@@ -4731,7 +4799,6 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb)
        ObjectInstanceRen *obi, *obilb;
        ObjectRen *obr;
        VertRen *ver= NULL;
-       StrandRen *strand= NULL;
        float *vec, ho[4], winmat[4][4];
        int a, totvector;
 
@@ -4742,7 +4809,7 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb)
                memcpy(obilb, obi, sizeof(ObjectInstanceRen));
                BLI_addtail(lb, obilb);
 
-               obilb->totvector= totvector= obr->totvert + obr->totstrand;
+               obilb->totvector= totvector= obr->totvert;
 
                if(totvector > 0) {
                        vec= obilb->vectors= MEM_mallocN(2*sizeof(float)*totvector, "vector array");
@@ -4759,14 +4826,6 @@ static void copy_dbase_object_vectors(Render *re, ListBase *lb)
                                projectvert(ver->co, winmat, ho);
                                speedvector_project(NULL, vec, ver->co, ho);
                        }
-
-                       for(a=0; a<obr->totstrand; a++, vec+=2) {
-                               if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
-                               else strand++;
-                               
-                               projectvert(strand->vert->co, winmat, ho);
-                               speedvector_project(NULL, vec, strand->vert->co, ho);
-                       }
                }
        }
 }
@@ -4784,8 +4843,10 @@ static void free_dbase_object_vectors(ListBase *lb)
 void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
 {
        ObjectInstanceRen *obi, *oldobi;
+       StrandSurface *mesh;
        ListBase *table;
        ListBase oldtable= {NULL, NULL}, newtable= {NULL, NULL};
+       ListBase strandsurface;
        int step;
        
        re->i.infostr= "Calculating previous vectors";
@@ -4800,7 +4861,10 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
        copy_dbase_object_vectors(re, &oldtable);
                
        /* free dbase and make the future one */
+       strandsurface= re->strandsurface;
+       memset(&re->strandsurface, 0, sizeof(ListBase));
        RE_Database_Free(re);
+       re->strandsurface= strandsurface;
        
        if(!re->test_break()) {
                /* creates entire dbase */
@@ -4812,7 +4876,10 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
        copy_dbase_object_vectors(re, &newtable);
        
        /* free dbase and make the real one */
+       strandsurface= re->strandsurface;
+       memset(&re->strandsurface, 0, sizeof(ListBase));
        RE_Database_Free(re);
+       re->strandsurface= strandsurface;
        
        if(!re->test_break())
                RE_Database_FromScene(re, sce, 1);
@@ -4829,7 +4896,7 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
                        for(obi= re->instancetable.first; obi && oldobi; obi= obi->next, oldobi= oldobi->next) {
                                int ok= 1;
 
-                               obi->totvector= obi->obr->totvert + obi->obr->totstrand;
+                               obi->totvector= obi->obr->totvert;
 
                                /* find matching object in old table */
                                if(oldobi->ob!=obi->ob || oldobi->par!=obi->par || oldobi->index!=obi->index || oldobi->psysindex!=obi->psysindex) {
@@ -4867,6 +4934,17 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
        
        free_dbase_object_vectors(&oldtable);
        free_dbase_object_vectors(&newtable);
+
+       for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) {
+               if(mesh->prevco) {
+                       MEM_freeN(mesh->prevco);
+                       mesh->prevco= NULL;
+               }
+               if(mesh->nextco) {
+                       MEM_freeN(mesh->nextco);
+                       mesh->nextco= NULL;
+               }
+       }
        
        re->i.infostr= NULL;
        re->stats_draw(&re->i);
index 7d7ed5bcdce1992afbbf59974bc716956be97df7..e1d491c69d9114ec00e2e109a8f293f86d041efd 100644 (file)
 #include "MEM_guardedalloc.h"
 
 #include "DNA_material_types.h"
-#include "DNA_meshdata_types.h"
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 #include "BLI_memarena.h"
 #include "BLI_threads.h"
 
-#include "BKE_DerivedMesh.h"
 #include "BKE_global.h"
 #include "BKE_utildefines.h"
 
@@ -74,15 +72,6 @@ typedef struct OcclusionCache {
        int x, y, w, h, step;
 } OcclusionCache;
 
-typedef struct OcclusionCacheMesh {
-       struct OcclusionCacheMesh *next, *prev;
-       ObjectRen *obr;
-       int (*face)[4];
-       float (*co)[3];
-       float (*col)[3];
-       int totvert, totface;
-} OcclusionCacheMesh;
-
 typedef struct OccFace {
        int obi;
        int facenr;
@@ -1418,10 +1407,10 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int
        return 0;
 }
 
-static void sample_occ_cache_mesh(ShadeInput *shi)
+static void sample_occ_surface(ShadeInput *shi)
 {
        StrandRen *strand= shi->strand;
-       OcclusionCacheMesh *mesh= strand->buffer->occlusionmesh;
+       StrandSurface *mesh= strand->buffer->surface;
        int *face, *index = RE_strandren_get_face(shi->obr, strand, 0);
        float w[4], *co1, *co2, *co3, *co4;
 
@@ -1449,53 +1438,11 @@ static void sample_occ_cache_mesh(ShadeInput *shi)
        }
 }
 
-void *cache_occ_mesh(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4])
-{
-       OcclusionCacheMesh *mesh;
-       MFace *mface;
-       MVert *mvert;
-       int a, totvert, totface;
-
-       totvert= dm->getNumVerts(dm);
-       totface= dm->getNumFaces(dm);
-
-       mesh= re->occlusionmesh.last;
-       if(mesh && mesh->obr->ob == obr->ob && mesh->obr->par == obr->par
-               && mesh->totvert==totvert && mesh->totface==totface)
-               return mesh;
-
-       mesh= MEM_callocN(sizeof(OcclusionCacheMesh), "OcclusionCacheMesh");
-       mesh->obr= obr;
-       mesh->totvert= totvert;
-       mesh->totface= totface;
-       mesh->co= MEM_callocN(sizeof(float)*3*mesh->totvert, "OcclusionMeshCo");
-       mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "OcclusionMeshFaces");
-       mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "OcclusionMeshCol");
-
-       mvert= dm->getVertArray(dm);
-       for(a=0; a<mesh->totvert; a++, mvert++) {
-               VECCOPY(mesh->co[a], mvert->co);
-               Mat4MulVecfl(mat, mesh->co[a]);
-       }
-
-       mface= dm->getFaceArray(dm);
-       for(a=0; a<mesh->totface; a++, mface++) {
-               mesh->face[a][0]= mface->v1;
-               mesh->face[a][1]= mface->v2;
-               mesh->face[a][2]= mface->v3;
-               mesh->face[a][3]= mface->v4;
-       }
-
-       BLI_addtail(&re->occlusionmesh, mesh);
-
-       return mesh;
-}
-
 /* ------------------------- External Functions --------------------------- */
 
 void make_occ_tree(Render *re)
 {
-       OcclusionCacheMesh *mesh;
+       StrandSurface *mesh;
        float col[3], co[3], n[3], *co1, *co2, *co3, *co4;
        int a, *face, *count;
 
@@ -1511,7 +1458,7 @@ void make_occ_tree(Render *re)
                if(re->wrld.ao_approx_passes)
                        occ_compute_passes(re, re->occlusiontree, re->wrld.ao_approx_passes);
 
-               for(mesh=re->occlusionmesh.first; mesh; mesh=mesh->next) {
+               for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) {
                        count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount");
 
                        for(a=0; a<mesh->totface; a++) {
@@ -1558,20 +1505,10 @@ void make_occ_tree(Render *re)
 
 void free_occ(Render *re)
 {
-       OcclusionCacheMesh *mesh;
-
        if(re->occlusiontree) {
                occ_free_tree(re->occlusiontree);
                re->occlusiontree = NULL;
        }
-
-       for(mesh=re->occlusionmesh.first; mesh; mesh=mesh->next) {
-               if(mesh->co) MEM_freeN(mesh->co);
-               if(mesh->col) MEM_freeN(mesh->col);
-               if(mesh->face) MEM_freeN(mesh->face);
-       }
-
-       BLI_freelistN(&re->occlusionmesh);
 }
 
 void sample_occ(Render *re, ShadeInput *shi)
@@ -1584,7 +1521,7 @@ void sample_occ(Render *re, ShadeInput *shi)
 
        if(tree) {
                if(shi->strand) {
-                       sample_occ_cache_mesh(shi);
+                       sample_occ_surface(shi);
                }
                /* try to get result from the cache if possible */
                else if(!sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) {
index 43f0a0d13e7d25443ac7fa8c66a563ccec896aa8..e4aa2326c0cff4bedb7a62ab113d411b9b5db27c 100644 (file)
@@ -505,6 +505,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
                
                strcpy(rl->name, srl->name);
                rl->lay= srl->lay;
+               rl->lay_zmask= srl->lay_zmask;
                rl->layflag= srl->layflag;
                rl->passflag= srl->passflag;
                rl->pass_xor= srl->pass_xor;
@@ -2358,6 +2359,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra)
                                continue;
                        }
                        if (scene->r.mode & R_TOUCH && !BLI_exist(name)) {
+                               BLI_make_existing_file(name); /* makes the dir if its not there */
                                BLI_touch(name);
                        }
 
index 50f3142f95afd557c8e0237ceec6737ebf4f3d67..220c06f1edefaa263ba2855e0d98fc760c2d8bfb 100644 (file)
@@ -897,7 +897,7 @@ void zbufshadeDA_tile(RenderPart *pa)
                        sdata.rl= rl;
                        sdata.psmlist= &psmlist;
                        sdata.edgerect= edgerect;
-                       zbuffer_solid(pa, rl->lay, rl->layflag, make_pixelstructs, &sdata);
+                       zbuffer_solid(pa, rl, make_pixelstructs, &sdata);
                        if(R.test_break()) break; 
                }
                
@@ -1063,7 +1063,7 @@ void zbufshade_tile(RenderPart *pa)
                shade_sample_initialize(&ssamp, pa, rl);
                addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
                
-               zbuffer_solid(pa, rl->lay, rl->layflag, NULL, NULL);
+               zbuffer_solid(pa, rl, NULL, NULL);
                
                if(!R.test_break()) {   /* NOTE: this if() is not consistant */
                        
@@ -1364,12 +1364,12 @@ void zbufshade_sss_tile(RenderPart *pa)
        ShadeSample ssamp;
        ZBufSSSHandle handle;
        RenderResult *rr= pa->result;
-       RenderLayer *rl= rr->layers.first;
+       RenderLayer *rl;
        VlakRen *vlr;
        Material *mat= re->sss_mat;
-       float (*co)[3], (*color)[3], *area, *fcol= rl->rectf;
+       float (*co)[3], (*color)[3], *area, *fcol;
        int x, y, seed, quad, totpoint, display = !(re->r.scemode & R_PREVIEWBUTS);
-       int *ro, *rz, *rp, *rbo, *rbz, *rbp;
+       int *ro, *rz, *rp, *rbo, *rbz, *rbp, lay;
 #if 0
        PixStr *ps;
        long *rs;
@@ -1394,13 +1394,32 @@ void zbufshade_sss_tile(RenderPart *pa)
        pa->rectbackz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectbackz");
 #endif
 
+       /* setup shade sample with correct passes */
+       memset(&ssamp, 0, sizeof(ssamp));
+       shade_sample_initialize(&ssamp, pa, rr->layers.first);
+       ssamp.tot= 1;
+       
+       for(rl=rr->layers.first; rl; rl=rl->next) {
+               ssamp.shi[0].lay |= rl->lay;
+               ssamp.shi[0].layflag |= rl->layflag;
+               ssamp.shi[0].passflag |= rl->passflag;
+               ssamp.shi[0].combinedflag |= ~rl->pass_xor;
+       }
+
+       rl= rr->layers.first;
+       ssamp.shi[0].passflag |= SCE_PASS_RGBA|SCE_PASS_COMBINED;
+       ssamp.shi[0].combinedflag &= ~(SCE_PASS_SPEC);
+       lay= ssamp.shi[0].lay;
+
        /* create the pixelstrs to be used later */
-       zbuffer_sss(pa, rl->lay, &handle, addps_sss);
+       zbuffer_sss(pa, lay, &handle, addps_sss);
 
        if(handle.totps==0) {
                zbufshade_sss_free(pa);
                return;
        }
+       
+       fcol= rl->rectf;
 
        co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo");
        color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor");
@@ -1412,14 +1431,6 @@ void zbufshade_sss_tile(RenderPart *pa)
                ISB_create(pa, NULL);
 #endif
 
-       /* setup shade sample with correct passes */
-       memset(&ssamp, 0, sizeof(ssamp));
-       shade_sample_initialize(&ssamp, pa, rl);
-       ssamp.shi[0].passflag= SCE_PASS_DIFFUSE|SCE_PASS_AO|SCE_PASS_RADIO;
-       ssamp.shi[0].passflag |= SCE_PASS_RGBA;
-       ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
-       ssamp.tot= 1;
-
        if(display) {
                /* initialize scanline updates for main thread */
                rr->renrect.ymin= 0;
index 09a3b9ef66de12afba1b7c17f9a8286fe3a453a8..88333265a8445af207a544e30a08c8adef1a1cbc 100644 (file)
@@ -860,13 +860,13 @@ static void sss_create_tree_mat(Render *re, Material *mat)
           setting them back, maybe we need to create our own Render? */
 
        /* do SSS preprocessing render */
-       layers= re->r.layers;
+       rr= re->result;
+       layers= rr->layers;
        osa= re->osa;
        osaflag= re->r.mode & R_OSA;
        partsdone= re->i.partsdone;
-       rr= re->result;
 
-       re->r.layers.first= re->r.layers.last= NULL;
+       rr->layers.first= rr->layers.last= NULL;
        re->osa= 0;
        re->r.mode &= ~R_OSA;
        re->sss_points= &points;
@@ -881,7 +881,7 @@ static void sss_create_tree_mat(Render *re, Material *mat)
        re->i.partsdone= partsdone;
        re->sss_mat= NULL;
        re->sss_points= NULL;
-       re->r.layers= layers;
+       rr->layers= layers;
        re->osa= osa;
        if (osaflag) re->r.mode |= R_OSA;
 
index 3a1d98572ca11efd045b82afec771e0694933cb9..bf58c023998535a96eeba2efed4823a412393d5f 100644 (file)
 
 #include "DNA_key_types.h"
 #include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 #include "BLI_ghash.h"
 #include "BLI_memarena.h"
 
+#include "BKE_DerivedMesh.h"
 #include "BKE_key.h"
 #include "BKE_utildefines.h"
 
@@ -1313,3 +1315,70 @@ void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], fl
 #endif
 }
 
+StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4], int timeoffset)
+{
+       StrandSurface *mesh;
+       MFace *mface;
+       MVert *mvert;
+       float (*co)[3];
+       int a, totvert, totface;
+
+       totvert= dm->getNumVerts(dm);
+       totface= dm->getNumFaces(dm);
+
+       for(mesh=re->strandsurface.first; mesh; mesh=mesh->next)
+               if(mesh->obr.ob == obr->ob && mesh->obr.par == obr->par
+                       && mesh->obr.index == obr->index && mesh->totvert==totvert && mesh->totface==totface)
+                       break;
+
+       if(!mesh) {
+               mesh= MEM_callocN(sizeof(StrandSurface), "StrandSurface");
+               mesh->obr= *obr;
+               mesh->totvert= totvert;
+               mesh->totface= totface;
+               mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "StrandSurfFaces");
+               mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCol");
+               BLI_addtail(&re->strandsurface, mesh);
+       }
+
+       if(timeoffset == -1 && !mesh->prevco)
+               mesh->prevco= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo");
+       else if(timeoffset == 0 && !mesh->co)
+               mesh->co= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo");
+       else if(timeoffset == 1 && !mesh->nextco)
+               mesh->nextco= co= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCo");
+       else
+               return mesh;
+
+       mvert= dm->getVertArray(dm);
+       for(a=0; a<mesh->totvert; a++, mvert++) {
+               VECCOPY(co[a], mvert->co);
+               Mat4MulVecfl(mat, co[a]);
+       }
+
+       mface= dm->getFaceArray(dm);
+       for(a=0; a<mesh->totface; a++, mface++) {
+               mesh->face[a][0]= mface->v1;
+               mesh->face[a][1]= mface->v2;
+               mesh->face[a][2]= mface->v3;
+               mesh->face[a][3]= mface->v4;
+       }
+
+       return mesh;
+}
+
+void free_strand_surface(Render *re)
+{
+       StrandSurface *mesh;
+
+       for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) {
+               if(mesh->co) MEM_freeN(mesh->co);
+               if(mesh->prevco) MEM_freeN(mesh->prevco);
+               if(mesh->nextco) MEM_freeN(mesh->nextco);
+               if(mesh->col) MEM_freeN(mesh->col);
+               if(mesh->face) MEM_freeN(mesh->face);
+       }
+
+       BLI_freelistN(&re->strandsurface);
+}
+
index a8b6dfec667d5fb1abeef16a4dba114ec05d5cb2..6b103d4fce29aea66a7fe4cf8826772f31dbfaee 100644 (file)
@@ -196,7 +196,6 @@ static void zbuf_add_to_span(ZSpan *zspan, float *v1, float *v2)
 /* Functions                                                 */
 /*-----------------------------------------------------------*/ 
 
-
 void fillrect(int *rect, int x, int y, int val)
 {
        int len, *drect;
@@ -1922,10 +1921,78 @@ void zbufclip4(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3
        zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, vez+12);
 }
 
+/* ************** ZMASK ******************************** */
+
+#define EXTEND_PIXEL(a)        if(temprectp[a]) {z+= rectz[a]; tot++;}
+
+/* changes the zbuffer to be ready for z-masking: applies an extend-filter, and then clears */
+static void zmask_rect(int *rectz, int *rectp, int xs, int ys)
+{
+       int len=0, x, y;
+       int *temprectp;
+       int row1, row2, row3, *curp, *curz;
+       
+       temprectp= MEM_dupallocN(rectp);
+       
+       /* extend: if pixel is not filled in, we check surrounding pixels and average z value  */
+       
+       for(y=1; y<=ys; y++) {
+               /* setup row indices */
+               row1= (y-2)*xs;
+               row2= row1 + xs;
+               row3= row2 + xs;
+               if(y==1)
+                       row1= row2;
+               else if(y==ys)
+                       row3= row2;
+               
+               curp= rectp + (y-1)*xs;
+               curz= rectz + (y-1)*xs;
+               
+               for(x=0; x<xs; x++, curp++, curz++) {
+                       if(curp[0]==0) {
+                               int tot= 0;
+                               float z= 0.0f;
+                               
+                               EXTEND_PIXEL(row1);
+                               EXTEND_PIXEL(row2);
+                               EXTEND_PIXEL(row3);
+                               EXTEND_PIXEL(row1 + 1);
+                               EXTEND_PIXEL(row3 + 1);
+                               if(x!=xs-1) {
+                                       EXTEND_PIXEL(row1 + 2);
+                                       EXTEND_PIXEL(row2 + 2);
+                                       EXTEND_PIXEL(row3 + 2);
+                               }                                       
+                               if(tot) {
+                                       len++;
+                                       curz[0]= (int)(z/(float)tot);
+                                       curp[0]= -1;    /* env */
+                               }
+                       }
+                       
+                       if(x!=0) {
+                               row1++; row2++; row3++;
+                       }
+               }
+       }
+       MEM_freeN(temprectp);
+       
+       /* clear not filled z values */
+       for(len= xs*ys -1; len>=0; len--) {
+               if(rectp[len]==0) {
+                       rectz[len] = -0x7FFFFFFF;
+                       rectp[len]= -1; /* env code */
+               }       
+       }
+}
+
+
+
 
 /* ***************** ZBUFFER MAIN ROUTINES **************** */
 
-void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag, void(*fillfunc)(RenderPart*, ZSpan*, int, void*), void *data)
+void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*, ZSpan*, int, void*), void *data)
 {
        ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
        ZSpan zspans[16], *zspan; /* 16 = RE_MAX_OSA */
@@ -1935,9 +2002,11 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag, void(*fillfu
        ObjectInstanceRen *obi;
        ObjectRen *obr;
        float winmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
+       unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask;
        int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0;
-       short nofill=0, env=0, wire=0, all_z= layflag & SCE_LAY_ALL_Z;
-
+       short nofill=0, env=0, wire=0, zmaskpass=0;
+       short all_z= rl->layflag & SCE_LAY_ALL_Z;
+       
        samples= (R.osa? R.osa: 1);
        samples= MIN2(4, samples-pa->sample);
 
@@ -1988,98 +2057,123 @@ void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag, void(*fillfu
                zspan->zbuflinefunc= zbufline;
        }
 
-       for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
-               obr= obi->obr;
+       /* in case zmask we fill Z for objects in lay_zmask first, then clear Z, and then do normal zbuffering */
+       if(rl->layflag & SCE_LAY_ZMASK)
+               zmaskpass= 1;
+       
+       for(; zmaskpass >=0; zmaskpass--) {
+               /* regular zbuffering loop, does all sample buffers */
+               for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
+                       obr= obi->obr;
 
-               if(obi->flag & R_TRANSFORMED)
-                       zbuf_make_winmat(&R, obi->mat, winmat);
-               else
-                       zbuf_make_winmat(&R, NULL, winmat);
+                       /* continue happens in 2 different ways... zmaskpass only does lay_zmask stuff */
+                       if(zmaskpass) {
+                               if((obr->lay & lay_zmask)==0)
+                                       continue;
+                       }
+                       else {
+                               if(!all_z && !(obr->lay & lay))
+                                       continue;
+                       }
+                       
+                       if(obi->flag & R_TRANSFORMED)
+                               zbuf_make_winmat(&R, obi->mat, winmat);
+                       else
+                               zbuf_make_winmat(&R, NULL, winmat);
 
-               zbuf_project_cache_clear(cache, obr->totvert);
+                       zbuf_project_cache_clear(cache, obr->totvert);
 
-               for(v=0; v<obr->totvlak; v++) {
-                       if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
-                       else vlr++;
+                       for(v=0; v<obr->totvlak; v++) {
+                               if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
+                               else vlr++;
 
-                       /* three cases, visible for render, only z values and nothing */
-                       if(obr->lay & lay) {
-                               if(vlr->mat!=ma) {
-                                       ma= vlr->mat;
-                                       nofill= ma->mode & (MA_ZTRA|MA_ONLYCAST);
-                                       env= (ma->mode & MA_ENV);
-                                       wire= (ma->mode & MA_WIRE);
-                                       
-                                       for(zsample=0; zsample<samples; zsample++) {
-                                               if(ma->mode & MA_ZINV) zspans[zsample].zbuffunc= zbuffillGLinv4;
-                                               else zspans[zsample].zbuffunc= zbuffillGL4;
+                               /* the cases: visible for render, only z values, zmask, nothing */
+                               if(obr->lay & lay) {
+                                       if(vlr->mat!=ma) {
+                                               ma= vlr->mat;
+                                               nofill= ma->mode & (MA_ZTRA|MA_ONLYCAST);
+                                               env= (ma->mode & MA_ENV);
+                                               wire= (ma->mode & MA_WIRE);
+                                               
+                                               for(zsample=0; zsample<samples; zsample++) {
+                                                       if(ma->mode & MA_ZINV) zspans[zsample].zbuffunc= zbuffillGLinv4;
+                                                       else zspans[zsample].zbuffunc= zbuffillGL4;
+                                               }
                                        }
                                }
-                       }
-                       else if(all_z) {
-                               env= 1;
-                               nofill= 0;
-                               ma= NULL; 
-                       }
-                       else {
-                               nofill= 1;
-                               ma= NULL;       /* otherwise nofill can hang */
-                       }
-
-                       if(!(vlr->flag & R_HIDDEN) && nofill==0) {
-                               unsigned short partclip;
-                               
-                               v1= vlr->v1;
-                               v2= vlr->v2;
-                               v3= vlr->v3;
-                               v4= vlr->v4;
-
-                               c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1);
-                               c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2);
-                               c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3);
-
-                               /* partclipping doesn't need viewplane clipping */
-                               partclip= c1 & c2 & c3;
-                               if(v4) {
-                                       c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4);
-                                       partclip &= c4;
+                               else if(all_z || (obr->lay & lay_zmask)) {
+                                       env= 1;
+                                       nofill= 0;
+                                       ma= NULL; 
+                               }
+                               else {
+                                       nofill= 1;
+                                       ma= NULL;       /* otherwise nofill can hang */
                                }
 
-                               if(partclip==0) {
+                               if(!(vlr->flag & R_HIDDEN) && nofill==0) {
+                                       unsigned short partclip;
                                        
-                                       if(env) zvlnr= -1;
-                                       else zvlnr= v+1;
-
-                                       c1= testclip(ho1);
-                                       c2= testclip(ho2);
-                                       c3= testclip(ho3);
-                                       if(v4)
-                                               c4= testclip(ho4);
-
-                                       for(zsample=0; zsample<samples; zsample++) {
-                                               zspan= &zspans[zsample];
-
-                                               if(wire) {
-                                                       if(v4)
-                                                               zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
-                                                       else
-                                                               zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0);
-                                               }
-                                               else {
-                                                       /* strands allow to be filled in as quad */
-                                                       if(v4 && (vlr->flag & R_STRAND)) {
-                                                               zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+                                       v1= vlr->v1;
+                                       v2= vlr->v2;
+                                       v3= vlr->v3;
+                                       v4= vlr->v4;
+
+                                       c1= zbuf_part_project(cache, v1->index, winmat, bounds, v1->co, ho1);
+                                       c2= zbuf_part_project(cache, v2->index, winmat, bounds, v2->co, ho2);
+                                       c3= zbuf_part_project(cache, v3->index, winmat, bounds, v3->co, ho3);
+
+                                       /* partclipping doesn't need viewplane clipping */
+                                       partclip= c1 & c2 & c3;
+                                       if(v4) {
+                                               c4= zbuf_part_project(cache, v4->index, winmat, bounds, v4->co, ho4);
+                                               partclip &= c4;
+                                       }
+
+                                       if(partclip==0) {
+                                               
+                                               if(env) zvlnr= -1;
+                                               else zvlnr= v+1;
+
+                                               c1= testclip(ho1);
+                                               c2= testclip(ho2);
+                                               c3= testclip(ho3);
+                                               if(v4)
+                                                       c4= testclip(ho4);
+
+                                               for(zsample=0; zsample<samples; zsample++) {
+                                                       zspan= &zspans[zsample];
+
+                                                       if(wire) {
+                                                               if(v4)
+                                                                       zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+                                                               else
+                                                                       zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0);
                                                        }
                                                        else {
-                                                               zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
-                                                               if(v4)
-                                                                       zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
+                                                               /* strands allow to be filled in as quad */
+                                                               if(v4 && (vlr->flag & R_STRAND)) {
+                                                                       zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
+                                                               }
+                                                               else {
+                                                                       zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
+                                                                       if(v4)
+                                                                               zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
+                                                               }
                                                        }
                                                }
                                        }
                                }
                        }
                }
+               
+               /* clear all z to close value, so it works as mask for next passes (ztra+strand) */
+               if(zmaskpass) {
+                       for(zsample=0; zsample<samples; zsample++) {
+                               zspan= &zspans[zsample];
+                               zmask_rect(zspan->rectz, zspan->rectp, pa->rectx, pa->recty);
+                       }
+               }
        }
 
        for(zsample=0; zsample<samples; zsample++) {
@@ -2272,6 +2366,8 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int
 
                if(obr->ob==re->excludeob)
                        continue;
+               else if(!(obr->lay & lay))
+                       continue;
 
                if(obi->flag & R_TRANSFORMED)
                        Mat4MulMat4(obwinmat, obi->mat, winmat);
@@ -2495,6 +2591,9 @@ void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(vo
        for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
                obr= obi->obr;
 
+               if(!(obr->lay & lay))
+                       continue;
+
                if(obi->flag & R_TRANSFORMED)
                        zbuf_make_winmat(&R, obi->mat, winmat);
                else
@@ -3196,6 +3295,9 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un
        for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
                obr= obi->obr;
 
+               if(!(obr->lay & lay))
+                       continue;
+
                if(obi->flag & R_TRANSFORMED)
                        zbuf_make_winmat(&R, obi->mat, winmat);
                else
index 7b87dd2108c06c196eff6d28cde462260b217ac6..eb81c2562895a42c9322f78f9a68ec6fa0ffca9e 100644 (file)
@@ -604,13 +604,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                uiBlockBeginAlign(block);
                        uiBlockSetEmboss(block, UI_EMBOSS);
                        
-                       if ((prev_proxylock) || (con->prev==NULL)) {
-                               /* don't draw 'button' behind arrow if disabled (and button doesn't do anything anyways) */
-                               uiBlockSetEmboss(block, UI_EMBOSSN);
-                               uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
-                               uiBlockSetEmboss(block, UI_EMBOSS);
-                       }
-                       else {
+                       /* only show buttons that will do anything valid */
+                       if ((prev_proxylock==0) && (con->prev)) {
                                but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
                                uiButSetFunc(but, constraint_moveUp, ob, con);
                        }
@@ -619,12 +614,6 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
                                uiButSetFunc(but, constraint_moveDown, ob, con);
                        }
-                       else {
-                               /* don't draw 'button' behind arrow if no next constraint (it doesn't do anything anyways) */
-                               uiBlockSetEmboss(block, UI_EMBOSSN);
-                               uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
-                               uiBlockSetEmboss(block, UI_EMBOSS);
-                       }
                uiBlockEndAlign(block);
                
                
@@ -1441,6 +1430,54 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                draw_constraint_spaceselect(block, con, *xco, *yco-130, is_armature_owner(ob), -1);
                        }
                        break;
+               case CONSTRAINT_TYPE_DISTLIMIT:
+                       {
+                               bDistLimitConstraint *data = con->data;
+                               
+                               height = 105;
+                               uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
+                               
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               
+                               /* Draw target parameters */
+                               uiBlockBeginAlign(block);
+                                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
+                                       
+                                       if (is_armature_target(data->tar)) {
+                                               but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
+                                               uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
+                                       }
+                                       else if (is_geom_target(data->tar)) {
+                                               but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+                                               uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+                                       }
+                                       else {
+                                               strcpy(data->subtarget, "");
+                                       }
+                               uiBlockEndAlign(block);
+                               
+                               uiBlockBeginAlign(block);
+                                       if (is_armature_target(data->tar)) {
+                                               uiDefButF(block, BUT, B_CONSTRAINT_TEST, "R", *xco, *yco-60, 20, 18, &data->dist, 0, 0, 0, 0, "Recalculate distance"); 
+                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Distance:", *xco+18, *yco-60,139,18, &data->dist, 0.0, 100, 0.5, 0.5, "Radius of limiting sphere");
+                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Head/Tail:", *xco+155, *yco-60,100,18, &con->headtail, 0.0, 1, 0.1, 0.1, "Target along length of bone: Head=0, Tail=1");
+                                       }
+                                       else {
+                                               uiDefButF(block, BUT, B_CONSTRAINT_TEST, "R", *xco, *yco-60, 20, 18, &data->dist, 0, 0, 0, 0, "Recalculate distance"); 
+                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Distance:", *xco+18, *yco-60, 237, 18, &data->dist, 0.0, 100, 0.5, 0.5, "Radius of limiting sphere");
+                                       }
+                                       
+                                       /* disabled soft-distance controls... currently it doesn't work yet. It was intended to be used for soft-ik (see xsi-blog for details) */
+#if 0
+                                       uiDefButBitS(block, TOG, LIMITDIST_USESOFT, B_CONSTRAINT_TEST, "Soft", *xco, *yco-82, 50, 18, &data->flag, 0, 24, 0, 0, "Enables soft-distance");
+                                       if (data->flag & LIMITDIST_USESOFT)
+                                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Soft-Distance:", *xco+50, *yco-82, 187, 18, &data->soft, 0.0, 100, 0.5, 0.5, "Distance surrounding radius when transforms should get 'delayed'");
+#endif
+                               uiBlockEndAlign(block);
+                               
+                               uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Limit Mode%t|Inside %x0|Outside %x1|Surface %x2", *xco+((width/2)-50), *yco-104, 100, 18, &data->mode, 0, 24, 0, 0, "Distances in relation to sphere of influence to allow");
+                       }
+                       break;
                case CONSTRAINT_TYPE_RIGIDBODYJOINT:
                        {
                                bRigidBodyJointConstraint *data = con->data;
@@ -1750,6 +1787,7 @@ static uiBlock *add_constraintmenu(void *arg_unused)
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIMIT, "Limit Location", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIMIT, "Limit Rotation", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SIZELIMIT, "Limit Scale", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       uiDefBut(block, BUTM, B_CONSTRAINT_ADD_DISTLIMIT, "Limit Distance", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        
        uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
        
@@ -1982,6 +2020,14 @@ void do_constraintbuts(unsigned short event)
                        BIF_undo_push("Add constraint");
                }
                break;
+       case B_CONSTRAINT_ADD_DISTLIMIT:
+               {
+                       con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT);
+                       add_constraint_to_active(ob, con);
+                       
+                       BIF_undo_push("Add constraint");
+               }
+               break;
 
        default:
                break;
@@ -3490,7 +3536,7 @@ static char sbsolvers[] = "Solver %t|RKP almost SOFT not usable but for some ger
 /* SIF would have been candidate  .. well lack of time .. brecht is busy .. better make a stable version for peach now :) */
 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";
 #else
-static char sbsolvers[] = "SOFT  step size controlled midpoint(1rst choice for real softbodies)%x0";
+static char sbsolvers[] = "RKCP correct physics (harder to get stable but usefull for education :)%x1|SOFT  step size controlled midpoint(1rst choice for real softbodies)%x0";
 #endif
 
 static void object_softbodies_collision(Object *ob)
@@ -3582,42 +3628,7 @@ static void object_softbodies_collision(Object *ob)
 
                        uiBlockEndAlign(block);
                        /*SOLVER SETTINGS*/
-                       uiBlockBeginAlign(block);
                        /* done in another panel now*/
-                       /*
-                       uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,100,50,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver");
-                       sb->solver_ID = 0; 
-                       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){
@@ -3640,12 +3651,12 @@ static void object_softbodies_solver(Object *ob)
        static int val;
        short *softflag=&ob->softflag, psys_cur=0, adaptive_mode=0;
        int ob_has_hair=psys_ob_has_hair(ob);
-    if(!_can_softbodies_at_all(ob)) return;
+       if(!_can_softbodies_at_all(ob)) return;
        block= uiNewBlock(&curarea->uiblocks, "object_softbodies_solver", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "Soft Body Solver", "Physics", 651, 0, 318, 204)==0) return;
 
        uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
-    /* doubt that is really needed here but for now */ 
+       /* doubt that is really needed here but for now */ 
        if(ob_has_hair) {
                if(PE_get_current_num(ob) >= 0) {
                        ParticleSystem *psys = PE_get_current(ob);
@@ -3680,11 +3691,10 @@ static void object_softbodies_solver(Object *ob)
                        /*SOLVER SETTINGS*/
                        uiBlockBeginAlign(block);
                        uiDefBut(block, LABEL, 0, "Solver select",10,200,300,20, NULL, 0.0, 0, 0, 0, ""); 
-                       uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,180,300,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver (choose 1 of 1 i was working on some other but failed *sigh* BM) ");
+                       uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,180,300,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver");
                        uiBlockEndAlign(block);
-                       
+
                        /*some have adapive step size - some not*/
-                       sb->solver_ID = 0; /* ugly hack to prepare peach freeze */
                        switch (sb->solver_ID) {
                        case 0:
                        case 1:
@@ -3695,7 +3705,7 @@ static void object_softbodies_solver(Object *ob)
                        }
                        if(adaptive_mode){
                                uiBlockBeginAlign(block);
-                           uiDefBut(block, LABEL, 0, "Step size controls",10,160,300,20, NULL, 0.0, 0, 0, 0, "");
+                               uiDefBut(block, LABEL, 0, "Step size controls",10,160,300,20, NULL, 0.0, 0, 0, 0, "");
                                uiDefButF(block, NUM, B_DIFF, "Error Lim:",     10,140,280,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,"V", 290,140,20,20, &sb->solverflags,  0,  0, 0, 0, "Use velocities for automagic step sizes");
                                uiDefButS(block, NUM, B_DIFF, "MinS:", 10,120,150,20, &sb->minloops,  0.00,  30000.0, 10, 0, "Minimal # solver steps/frame ");
@@ -3703,11 +3713,11 @@ static void object_softbodies_solver(Object *ob)
                                uiBlockEndAlign(block);
 
                                uiBlockBeginAlign(block);
-                       uiDefBut(block, LABEL, 0, "Collision helpers",10,100,300,20, NULL, 0.0, 0, 0, 0, "");
+                               uiDefBut(block, LABEL, 0, "Collision helpers",10,100,300,20, NULL, 0.0, 0, 0, 0, "");
                                uiDefButS(block, NUM, B_DIFF, "Choke:", 10,80,150,20, &sb->choke, 0.00,  100.0, 10, 0, "'Viscosity' inside collision target ");
                                uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 160,80,150,20, &sb->fuzzyness,  1.00,  100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable");
                                uiBlockEndAlign(block);
-                               
+
                                uiBlockBeginAlign(block);
                                uiDefBut(block, LABEL, 0, "Diagnosis stuff",10,60,300,20, NULL, 0.0, 0, 0, 0, "");
                                uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"Print Performance to Console", 10,40,300,20, &sb->solverflags,  0,  0, 0, 0, "Turn on SB diagnose console prints");                              
@@ -3723,10 +3733,9 @@ static void object_softbodies_solver(Object *ob)
                                uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00,  100.0, 10, 0, "'Viscosity' inside collision target ");
                        }
 
-       uiBlockEndAlign(block);
+                       uiBlockEndAlign(block);
 
                }
-               //uiDefBut(block, LABEL, 0, "",10,10,1,2, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/
        }
        uiBlockEndAlign(block);
 }
@@ -3850,7 +3859,7 @@ static void object_softbodies(Object *ob)
                        uiBlockBeginAlign(block);
                        uiDefButF(block, NUM, B_DIFF, "Friction:", 10, 170,150,20, &sb->mediafrict, 0.0, 50.0, 10, 0, "General media friction for point movements");
                        uiDefButF(block, NUM, B_DIFF, "Mass:",     160, 170,150,20, &sb->nodemass , 0.001, 50000.0, 10, 0, str);
-                       uiDefButF(block, NUM, B_DIFF, "Grav:",     10,150,150,20, &sb->grav , 0.0, 10.0, 10, 0, "Apply gravitation to point movement");
+                       uiDefButF(block, NUM, B_DIFF, "Grav:",     10,150,150,20, &sb->grav , -10.0, 10.0, 10, 0, "Apply gravitation to point movement");
                        uiDefButF(block, NUM, B_DIFF, "Speed:",    160,150,150,20, &sb->physics_speed , 0.01, 100.0, 10, 0, "Tweak timing for physics to control frequency and speed");
                        uiBlockEndAlign(block);
 
@@ -4110,7 +4119,7 @@ static void object_panel_particle_extra(Object *ob)
 
                uiBlockBeginAlign(block);
                
-               uiDefButS(block, MENU, B_PART_REDRAW, "Attribute%t|TanRot%x10|TanVel%x9|Size%x8|RoughE%x7|Rough2%x6|Rough1%x5|Kink%x4|Clump%x3|Length%x2|Velocity%x1|Density%x0", butx,(buty-=buth),butw-40,buth, &vgnum, 14.0, 0.0, 0, 0, "Attribute effected by vertex group");
+               uiDefButS(block, MENU, B_PART_REDRAW, "Attribute%t|Effector%x11|TanRot%x10|TanVel%x9|Size%x8|RoughE%x7|Rough2%x6|Rough1%x5|Kink%x4|Clump%x3|Length%x2|Velocity%x1|Density%x0", butx,(buty-=buth),butw-40,buth, &vgnum, 14.0, 0.0, 0, 0, "Attribute effected by vertex group");
                but=uiDefButBitS(block, TOG, (1<<vgnum), B_PART_REDRAW, "Neg",  butx+butw-40,buty,40,buth, &psys->vg_neg, 0, 0, 0, 0, "Negate the effect of the vertex group");
                uiButSetFunc(but, particle_set_vg, (void *)ob, (void *)(&vgnum));
                
index 0dc6c485db5eeaf24029b6f3ddbd96eb328dae3a..d06028b09bc00cafaa9134b42a5ea0435932dc85 100644 (file)
@@ -2485,7 +2485,7 @@ static void layer_copy_func(void *lay_v, void *lay_p)
        unsigned int *lay= lay_p;
        int laybit= (int)lay_v;
 
-       if(G.qual & LR_SHIFTKEY) {
+       if(G.qual & (LR_SHIFTKEY|LR_CTRLKEY)) {
                if(*lay==0) *lay= 1<<laybit;
        }
        else
@@ -2556,29 +2556,29 @@ static char *scene_layer_menu(void)
        return str;
 }
 
-static void draw_3d_layer_buttons(uiBlock *block, unsigned int *poin, short xco, short yco, short dx, short dy)
+static void draw_3d_layer_buttons(uiBlock *block, int type, unsigned int *poin, short xco, short yco, short dx, short dy, char *tip)
 {
        uiBut *bt;
        long a;
        
        uiBlockBeginAlign(block);
        for(a=0; a<5; a++) {
-               bt= uiDefButBitI(block, TOG, 1<<a, B_NOP, "",   (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, "");
+               bt= uiDefButBitI(block, type, 1<<a, B_NOP, "",  (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, tip);
                uiButSetFunc(bt, layer_copy_func, (void *)a, poin);
        }
        for(a=0; a<5; a++) {
-               bt=uiDefButBitI(block, TOG, 1<<(a+10), B_NOP, "",       (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, "");
+               bt=uiDefButBitI(block, type, 1<<(a+10), B_NOP, "",      (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, tip);
                uiButSetFunc(bt, layer_copy_func, (void *)(a+10), poin);
        }
        
        xco+= 7;
        uiBlockBeginAlign(block);
        for(a=5; a<10; a++) {
-               bt=uiDefButBitI(block, TOG, 1<<a, B_NOP, "",    (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, "");
+               bt=uiDefButBitI(block, type, 1<<a, B_NOP, "",   (short)(xco+a*(dx/2)), yco+dy/2, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, tip);
                uiButSetFunc(bt, layer_copy_func, (void *)a, poin);
        }
        for(a=5; a<10; a++) {
-               bt=uiDefButBitI(block, TOG, 1<<(a+10), B_NOP, "",       (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, "");
+               bt=uiDefButBitI(block, type, 1<<(a+10), B_NOP, "",      (short)(xco+a*(dx/2)), yco, (short)(dx/2), (short)(dy/2), (int *)poin, 0, 0, 0, 0, tip);
                uiButSetFunc(bt, layer_copy_func, (void *)(a+10), poin);
        }
        
@@ -2603,7 +2603,7 @@ static void render_panel_layers(void)
        
        /* first, as reminder, the scene layers */
        uiDefBut(block, LABEL, 0, "Scene:",                             10,170,100,20, NULL, 0, 0, 0, 0, "");
-       draw_3d_layer_buttons(block, &G.scene->lay,             130, 170, 35, 30);
+       draw_3d_layer_buttons(block, TOG, &G.scene->lay,                130, 170, 35, 30, "Scene layers to render");
        
        /* layer disable, menu, name, delete button */
        uiBlockBeginAlign(block);
@@ -2623,10 +2623,11 @@ static void render_panel_layers(void)
 
        /* RenderLayer visible-layers */
        uiDefBut(block, LABEL, 0, "Layer:",                     10,110,100,20, NULL, 0, 0, 0, 0, "");
-       draw_3d_layer_buttons(block, &srl->lay,         130,110, 35, 30);
+       draw_3d_layer_buttons(block, BUT_TOGDUAL, &srl->lay,            130,110, 35, 30, "Scene-layers included in this render-layer (Hold CTRL for Z-mask)");
        
        uiBlockBeginAlign(block);
-       uiDefButBitI(block, TOG, SCE_LAY_ALL_Z, B_NOP,"AllZ",   10, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Fill in Z values for all not-rendered faces, for masking"); 
+       uiDefButBitI(block, TOG, SCE_LAY_ALL_Z, B_NOP,"AllZ",   10, 85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Fill in Z values for solid faces in invisible layers, for masking");        
+       uiDefButBitI(block, TOG, SCE_LAY_ZMASK, B_NOP,"Zmask",  10, 65, 40, 20, &srl->layflag, 0, 0, 0, 0, "Only render what's in front of the solid z values");        
        uiBlockBeginAlign(block);
        uiDefButBitI(block, TOG, SCE_LAY_SOLID, B_NOP,"Solid",  50,  85, 45, 20, &srl->layflag, 0, 0, 0, 0, "Render Solid faces in this Layer");        
        uiDefButBitI(block, TOG, SCE_LAY_HALO, B_NOP,"Halo",    95,  85, 40, 20, &srl->layflag, 0, 0, 0, 0, "Render Halos in this Layer (on top of Solid)");    
@@ -2635,8 +2636,8 @@ static void render_panel_layers(void)
        uiDefButBitI(block, TOG, SCE_LAY_EDGE, B_NOP,"Edge",    215, 85, 45, 20, &srl->layflag, 0, 0, 0, 0, "Render Edge-enhance in this Layer (only works for Solid faces)");  
        uiDefButBitI(block, TOG, SCE_LAY_STRAND, B_NOP,"Strand",260, 85, 50, 20, &srl->layflag, 0, 0, 0, 0, "Render Strands in this Layer");    
        
-       uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_SET_PASS, "Light:",  10, 65, 150, 20, &(srl->light_override), "Name of Group to use as Lamps instead");
-       uiDefIDPoinBut(block, test_matpoin_but, ID_MA, B_SET_PASS, "Mat:",      160, 65, 150, 20, &(srl->mat_override), "Name of Material to use as Materials instead");
+       uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_SET_PASS, "Light:",  50, 65, 130, 20, &(srl->light_override), "Name of Group to use as Lamps instead");
+       uiDefIDPoinBut(block, test_matpoin_but, ID_MA, B_SET_PASS, "Mat:",      180, 65, 130, 20, &(srl->mat_override), "Name of Material to use as Materials instead");
        uiBlockEndAlign(block);
 
        uiBlockBeginAlign(block);
index 2ac76942da742f75635437aa6563c0c11ae67491..be307a649b3199b8601d137ec08bc7fa4b605f6c 100644 (file)
@@ -2283,8 +2283,8 @@ static void world_panel_world(World *wrld)
 
        uiBlockBeginAlign(block);
        uiBlockSetCol(block, TH_BUT_SETTING1);
-       uiDefButF(block, NUMSLI,B_WORLDPRV, "Exp ",                     160,30,145,19,  &(wrld->exp), 0.0, 1.0, 0, 2, "Sets amount of exponential color correction for light");
-       uiDefButF(block, NUMSLI,B_WORLDPRV, "Range ",           160,10,145,19,  &(wrld->range), 0.2, 5.0, 0, 2, "Sets the color amount that will be mapped on color 1.0");
+       uiDefButF(block, NUMSLI,B_WORLDPRV2, "Exp ",                    160,30,145,19,  &(wrld->exp), 0.0, 1.0, 0, 2, "Sets amount of exponential color correction for light");
+       uiDefButF(block, NUMSLI,B_WORLDPRV2, "Range ",          160,10,145,19,  &(wrld->range), 0.2, 5.0, 0, 2, "Sets the color amount that will be mapped on color 1.0");
 
 
 }
@@ -2968,7 +2968,7 @@ void do_matbuts(unsigned short event)
                allqueue(REDRAWBUTSSHADING, 0);
                break;
        case B_WORLDPRV2:
-               BIF_preview_changed(ID_WO);
+               BIF_preview_changed(ID_TE);
                allqueue(REDRAWBUTSSHADING, 0);
                allqueue(REDRAWVIEW3D, 0);
                break;
index a169af6cf938851d74691df3891c3b5a06840de3..3339385d565d03de35a6f93638906d2d3c064ad5 100644 (file)
@@ -813,19 +813,32 @@ static void draw_channel_strips(void)
        if (NLA_ACTION_SCALED)
                map_active_strip(di, OBACT, 0);
        
-       /* draw keyframes */
+       /* Draw keyframes 
+        *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
+        *         This is to try to optimise this for heavier data sets
+        *      2) Keyframes which are out of view horizontally could be disregarded (probably as
+        *         option - 'drop-frames' or so). Todo...
+        */
        y = 0.0;
        for (ale= act_data.first; ale; ale= ale->next) {
-               switch (ale->datatype) {
-                       case ALE_GROUP:
-                               draw_agroup_channel(di, ale->data, y);
-                               break;
-                       case ALE_IPO:
-                               draw_ipo_channel(di, ale->key_data, y);
-                               break;
-                       case ALE_ICU:
-                               draw_icu_channel(di, ale->key_data, y);
-                               break;
+               float yminc= y-CHANNELHEIGHT/2;
+               float ymaxc= y+CHANNELHEIGHT/2;
+               
+               /* check if visible */
+               if ( IN_RANGE(yminc, G.v2d->cur.ymin, G.v2d->cur.ymax) ||
+                        IN_RANGE(ymaxc, G.v2d->cur.ymin, G.v2d->cur.ymax) ) 
+               {
+                       switch (ale->datatype) {
+                               case ALE_GROUP:
+                                       draw_agroup_channel(di, ale->data, y);
+                                       break;
+                               case ALE_IPO:
+                                       draw_ipo_channel(di, ale->key_data, y);
+                                       break;
+                               case ALE_ICU:
+                                       draw_icu_channel(di, ale->key_data, y);
+                                       break;
+                       }
                }
                
                y-=CHANNELHEIGHT+CHANNELSKIP;
index 6c9e6ce1f6fee583cef03942047da3bf8e6dfd09..1c091ed39d9ad8799a74f55bfffc84b87cd1c2ed 100644 (file)
@@ -1160,6 +1160,7 @@ void duplicate_action_keys (void)
        BLI_freelistN(&act_data);
        
        /* now, go into transform-grab mode, to move keys */
+       BIF_TransformSetUndo("Add Duplicate");
        transform_action_keys('g', 0);
 }
 
index ac5129dd02193a2732f32a2c0ff64cc0851a974c..ba73767387eb364f6108404e5051300f40ac21de 100644 (file)
@@ -364,21 +364,21 @@ void add_constraint (short only_IK)
        else {
                if (pchanact) {
                        if (pchansel)
-                               nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
                        else if ((obsel) && (obsel->type==OB_CURVE))
-                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
                        else if (obsel)
-                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
                        else
-                               nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
                }
                else {
                        if ((obsel) && (obsel->type==OB_CURVE))
-                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18");
                        else if (obsel)
-                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
                        else
-                               nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
                }
        }
        
@@ -475,6 +475,7 @@ void add_constraint (short only_IK)
                        }
                }
                else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
+               else if (nr==21) con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT);
                
                if (con==NULL) return;  /* paranoia */
                
index 6fe2e032eed7202f5e7c2730fb26613a5e0b122c..b3ea3e1931c5e81e7550e92eab5426fc93aadcea 100644 (file)
@@ -2515,7 +2515,7 @@ static int match_adr_constraint(ID * id, int blocktype, char *actname, int adrco
                                                case CONSTRAINT_TYPE_LOCKTRACK:
                                                        if (searchtype==2) foundmatch=1;
                                                        break;
-                                               case CONSTRAINT_TYPE_DISTANCELIMIT:
+                                               case CONSTRAINT_TYPE_DISTLIMIT:
                                                        if (searchtype==1) foundmatch=1;
                                                        break;
                                                case CONSTRAINT_TYPE_MINMAX:
index 1992ea8468aec7a65687559251cd6019b2b5fe16..9fc6f1896eaa65c9e3c94f7eb1c737ed7d00dfc4 100644 (file)
@@ -51,6 +51,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
 #include "DNA_mesh_types.h"
 #include "DNA_material_types.h"
 #include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
@@ -1283,6 +1284,19 @@ static EditVert *subdivide_edge_addvert(EditEdge *edge, float rad, int beauty, f
        /* offset for smooth or sphere or fractal */
        alter_co(co, edge, rad, beauty, percent);
        
+       /* clip if needed by mirror modifier */
+       if (edge->v1->f2) {
+               if ( edge->v1->f2 & edge->v2->f2 & 1) {
+                       co[0]= 0.0f;
+               }
+               if ( edge->v1->f2 & edge->v2->f2 & 2) {
+                       co[1]= 0.0f;
+               }
+               if ( edge->v1->f2 & edge->v2->f2 & 4) {
+                       co[2]= 0.0f;
+               }
+       }
+       
        ev = addvertlist(co, NULL);
        
        /* vert data (vgroups, ..) */
@@ -2403,12 +2417,39 @@ void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
        EditMesh *em = G.editMesh;
        EditFace *ef;
        EditEdge *eed, *cedge, *sort[4];
-       EditVert **templist;
+       EditVert *eve, **templist;
        struct GHash *gh;
        float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3];
        int i, j, edgecount, touchcount, facetype,hold;
+       ModifierData *md= G.obedit->modifiers.first;
        
        if(multires_test()) return;
+
+       for (; md; md=md->next) {
+               if (md->type==eModifierType_Mirror) {
+                       MirrorModifierData *mmd = (MirrorModifierData*) md;     
+               
+                       if(mmd->flag & MOD_MIR_CLIPPING) {
+                               for (eve= em->verts.first; eve; eve= eve->next) {
+                                       eve->f2= 0;
+                                       switch(mmd->axis){
+                                               case 0:
+                                                       if (fabs(eve->co[0]) < mmd->tolerance)
+                                                               eve->f2 |= 1;
+                                                       break;
+                                               case 1:
+                                                       if (fabs(eve->co[1]) < mmd->tolerance)
+                                                               eve->f2 |= 2;
+                                                       break;
+                                               case 2:
+                                                       if (fabs(eve->co[2]) < mmd->tolerance)
+                                                               eve->f2 |= 4;
+                                                       break;
+                                       }
+                               }
+                       }
+               }
+       }
        
        //Set faces f1 to 0 cause we need it later
        for(ef=em->faces.first;ef;ef = ef->next) {
index 645dc77c3372fd1495568d3af7a133db22b4d622..e42de1031e5c8eae1ee7597e61bf4cc31fa404f8 100644 (file)
@@ -300,8 +300,12 @@ static void composit_node_event(SpaceNode *snode, short event)
                                
                                /* not the best implementation of the world... but we need it to work now :) */
                                if(node->type==CMP_NODE_R_LAYERS && node->custom2) {
+                                       /* add event for this window (after render curarea can be changed) */
+                                       addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
+                                       
                                        composite_node_render(snode, node);
-                                       /* new event, a render can go fullscreen and open new window */
+                                       
+                                       /* add another event, a render can go fullscreen and open new window */
                                        addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC);
                                }
                                else {
index cb1ed4c3e5aa9ba9af68a14bbfcb07d37015f502..a7b8400fb9db26748df81dd693ece52ba179f667 100644 (file)
@@ -5148,7 +5148,7 @@ void selectlinks_menu(void)
        /* If you modify this menu, please remember to update view3d_select_linksmenu
         * in header_view3d.c and the menu in toolbox.c
         */
-       nr= pupmenu("Select Linked%t|Object Ipo%x1|ObData%x2|Material%x3|Texture%x4|DupliGroup%x5");
+       nr= pupmenu("Select Linked%t|Object Ipo%x1|ObData%x2|Material%x3|Texture%x4|DupliGroup%x5|ParticleSystem%x6");
        
        if (nr <= 0) return;
        
@@ -5171,6 +5171,7 @@ void selectlinks(int nr)
         * Current Material: 3
         * Current Texture: 4
         * DupliGroup: 5
+        * PSys: 6
         */
        
        
@@ -5196,6 +5197,9 @@ void selectlinks(int nr)
        else if(nr==5) {
                if(ob->dup_group==NULL) return;
        }
+       else if(nr==6) {
+               if(ob->particlesystem.first==NULL) return;
+       }
        else return;
        
        base= FIRSTBASE;
@@ -5224,6 +5228,7 @@ void selectlinks(int nr)
                                                                if(tex==mat1->mtex[b]->tex) {
                                                                        base->flag |= SELECT;
                                                                        changed = 1;
+                                                                       break;
                                                                }
                                                        }
                                                }
@@ -5236,6 +5241,25 @@ void selectlinks(int nr)
                                         changed = 1;
                                }
                        }
+                       else if(nr==6) {
+                               /* loop through other, then actives particles*/
+                               ParticleSystem *psys;
+                               ParticleSystem *psys_act;
+                               
+                               for(psys=base->object->particlesystem.first; psys; psys=psys->next) {
+                                       for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
+                                               if (psys->part == psys_act->part) {
+                                                       base->flag |= SELECT;
+                                                       changed = 1;
+                                                       break;
+                                               }
+                                       }
+                                       
+                                       if (base->flag & SELECT) {
+                                               break;
+                                       }
+                               }
+                       }
                        base->object->flag= base->flag;
                }
                base= base->next;
@@ -5580,17 +5604,9 @@ void mirrormenu(void)
        if(G.f & G_PARTICLEEDIT) {
                PE_mirror_x(0);
        }
-       else if (G.obedit==0) {
-               mode=pupmenu("Mirror Axis %t|X Local%x4|Y Local%x5|Z Local%x6|");
-
-               if (mode==-1) return; /* return */
-               Mirror(mode); /* separating functionality from interface | call*/
-       }
        else {
-               mode=pupmenu("Mirror Axis %t|X Global%x1|Y Global%x2|Z Global%x3|%l|X Local%x4|Y Local%x5|Z Local%x6|%l|X View%x7|Y View%x8|Z View%x9|");
-
-               if (mode==-1) return; /* return */
-               Mirror(mode); /* separating functionality from interface | call*/
+               initTransform(TFM_MIRROR, CTX_NO_PET);
+               Transform();
        }
 }
 
index 5d511b3563334a1959993721e4e18f7909179e59..a3bdbd0f7ab47606f9c7b4ad8933354ad79bed74 100644 (file)
@@ -788,7 +788,7 @@ void mouse_select_seq(void)
        int hand,seldir;
        TimeMarker *marker;
        
-       marker=find_nearest_marker(0, 1);
+       marker=find_nearest_marker(SCE_MARKERS, 1);
        
        if (marker) {
                int oldflag;
index f7cf9dd22cd840c6ee914ee832bced41c2851f93..4cbad8a9758d6160e88bbd434f0bfdaa463cad81 100644 (file)
@@ -1881,10 +1881,24 @@ static uiBlock *view3d_transformmenu(void *arg_unused)
 void do_view3d_object_mirrormenu(void *arg, int event)
 {
        switch(event) {
+               case 0:
+                       initTransform(TFM_MIRROR, CTX_NO_PET);
+                       Transform();
+                       break;
                case 1:
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setLocalAxisConstraint('X', " on X axis");
+                       Transform();
+                       break;
                case 2:
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setLocalAxisConstraint('Y', " on Y axis");
+                       Transform();
+                       break;
                case 3:
-                       Mirror(event + 3); /* + 3 because the first three modes are global*/
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setLocalAxisConstraint('Z', " on Z axis");
+                       Transform();
                        break;
        }
        allqueue(REDRAWVIEW3D, 0);
@@ -1898,9 +1912,11 @@ static uiBlock *view3d_object_mirrormenu(void *arg_unused)
        block= uiNewBlock(&curarea->uiblocks, "view3d_object_mirrormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
        uiBlockSetButmFunc(block, do_view3d_object_mirrormenu, NULL);
        
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, 1",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, 2",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, 3",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Interactive Mirror|Ctrl M",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+       uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, X",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, Y",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, Z",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
 
        uiBlockSetDirection(block, UI_RIGHT);
        uiTextBoundsBlock(block, 60);
@@ -2853,17 +2869,44 @@ static uiBlock *view3d_edit_mesh_normalsmenu(void *arg_unused)
 
 void do_view3d_edit_mirrormenu(void *arg, int event)
 {
+       float mat[3][3];
+       
+       Mat3One(mat);
+       
        switch(event) {
+               case 0:
+                       initTransform(TFM_MIRROR, CTX_NO_PET);
+                       Transform();
+                       break;
                case 1:
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setSingleAxisConstraint(mat[0], " on global X axis");
+                       Transform();
+                       break;
                case 2:
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setSingleAxisConstraint(mat[1], " on global Y axis");
+                       Transform();
+                       break;
                case 3:
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setSingleAxisConstraint(mat[2], "on global Z axis");
+                       Transform();
+                       break;
                case 4:
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setLocalAxisConstraint('X', " on local X axis");
+                       Transform();
+                       break;
                case 5:
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setLocalAxisConstraint('Y', " on local Y axis");
+                       Transform();
+                       break;
                case 6:
-               case 7:
-               case 8:
-               case 9:
-                       Mirror(event);
+                       initTransform(TFM_MIRROR, CTX_NO_PET|CTX_AUTOCONFIRM);
+                       BIF_setLocalAxisConstraint('Z', " on local Z axis");
+                       Transform();
                        break;
        }
        allqueue(REDRAWVIEW3D, 0);
@@ -2877,21 +2920,19 @@ static uiBlock *view3d_edit_mirrormenu(void *arg_unused)
        block= uiNewBlock(&curarea->uiblocks, "view3d_edit_mirrormenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
        uiBlockSetButmFunc(block, do_view3d_edit_mirrormenu, NULL);
        
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|Ctrl M, 1",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|Ctrl M, 2",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|Ctrl M, 3",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
-       
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Interactive Mirror|Ctrl M",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
        
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, 4",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, 5",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, 6",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Global|Ctrl M, X",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Global|Ctrl M, Y",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Global|Ctrl M, Z",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
        
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
        
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X View|Ctrl M, 7",                       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y View|Ctrl M, 8",                       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z View|Ctrl M, 9",                       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "X Local|Ctrl M, X X",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Y Local|Ctrl M, Y Y",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Z Local|Ctrl M, Z Z",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
 
        uiBlockSetDirection(block, UI_RIGHT);
        uiTextBoundsBlock(block, 60);
index 63f39608f5d75ff052b396851c83f5f449198857..c8ca48f64eb96f2e851986ba3f07cbb8e0eb8f2a 100644 (file)
@@ -2362,9 +2362,11 @@ void outliner_select(struct ScrArea *sa )
 
 /* ************ SELECTION OPERATIONS ********* */
 
-static int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0; // globals, euh... you can do better
-
-static void set_operation_types(SpaceOops *soops, ListBase *lb)
+static void set_operation_types(SpaceOops *soops, ListBase *lb,
+                               int *scenelevel,
+                               int *objectlevel,
+                               int *idlevel,
+                               int *datalevel)
 {
        TreeElement *te;
        TreeStoreElem *tselem;
@@ -2374,22 +2376,22 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb)
                if(tselem->flag & TSE_SELECTED) {
                        if(tselem->type) {
 #ifdef WITH_VERSE
-                               if(te->idcode==ID_VS) datalevel= TSE_VERSE_SESSION;
-                               else if(te->idcode==ID_VN) datalevel= TSE_VERSE_OBJ_NODE;
-                               else if(datalevel==0) datalevel= tselem->type;
+                               if(te->idcode==ID_VS) *datalevel= TSE_VERSE_SESSION;
+                               else if(te->idcode==ID_VN) *datalevel= TSE_VERSE_OBJ_NODE;
+                               else if(*datalevel==0) *datalevel= tselem->type;
 #else
-                               if(datalevel==0) datalevel= tselem->type;
+                               if(*datalevel==0) *datalevel= tselem->type;
 #endif
-                               else if(datalevel!=tselem->type) datalevel= -1;
+                               else if(*datalevel!=tselem->type) *datalevel= -1;
                        }
                        else {
                                int idcode= GS(tselem->id->name);
                                switch(idcode) {
                                        case ID_SCE:
-                                               scenelevel= 1;
+                                               *scenelevel= 1;
                                                break;
                                        case ID_OB:
-                                               objectlevel= 1;
+                                               *objectlevel= 1;
                                                break;
                                                
                                        case ID_ME: case ID_CU: case ID_MB: case ID_LT:
@@ -2397,13 +2399,16 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb)
                                        case ID_MA: case ID_TE: case ID_IP: case ID_IM:
                                        case ID_SO: case ID_KE: case ID_WO: case ID_AC:
                                        case ID_NLA: case ID_TXT: case ID_GR:
-                                               if(idlevel==0) idlevel= idcode;
-                                               else if(idlevel!=idcode) idlevel= -1;
+                                               if(*idlevel==0) *idlevel= idcode;
+                                               else if(*idlevel!=idcode) *idlevel= -1;
                                                        break;
                                }
                        }
                }
-               if((tselem->flag & TSE_CLOSED)==0) set_operation_types(soops, &te->subtree);
+               if((tselem->flag & TSE_CLOSED)==0) {
+                       set_operation_types(soops, &te->subtree,
+                                                               scenelevel, objectlevel, idlevel, datalevel);
+               }
        }
 }
 
@@ -2559,6 +2564,30 @@ static void id_local_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tse
        }
 }
 
+static void group_linkobs2scene_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem)
+{
+       Group *group= (Group *)tselem->id;
+       GroupObject *gob;
+       Base *base;
+       
+       for(gob=group->gobject.first; gob; gob=gob->next) {
+               base= object_in_scene(gob->ob, G.scene);
+               if (base) {
+                       base->object->flag |= SELECT;
+                       base->flag |= SELECT;
+               } else {
+                               
+                       /* link to scene */
+                       base= MEM_callocN( sizeof(Base), "add_base");
+                       BLI_addhead(&G.scene->base, base);
+                       base->lay= (1<<20)-1; /*G.vd->lay;*/ /* would be nice to use the 3d layer but the include's not here */
+                       gob->ob->flag |= SELECT;
+                       base->flag = gob->ob->flag;
+                       base->object= gob->ob;
+               }
+       }
+}
+
 static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb, 
                                                                                 void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *))
 {
@@ -2674,11 +2703,9 @@ void outliner_del(ScrArea *sa)
 void outliner_operation_menu(ScrArea *sa)
 {
        SpaceOops *soops= sa->spacedata.first;
+       int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0;
        
-       // bad globals
-       scenelevel= objectlevel= idlevel= datalevel=0;
-       
-       set_operation_types(soops, &soops->tree);
+       set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
        
        if(scenelevel) {
                if(objectlevel || datalevel || idlevel) error("Mixed selection");
@@ -2719,7 +2746,12 @@ void outliner_operation_menu(ScrArea *sa)
        else if(idlevel) {
                if(idlevel==-1 || datalevel) error("Mixed selection");
                else {
-                       short event= pupmenu("Unlink %x1|Make Local %x2");
+                       short event;
+                       if (idlevel==ID_GR)
+                               event = pupmenu("Unlink %x1|Make Local %x2|Link Group Objects to Scene%x3");
+                       else
+                               event = pupmenu("Unlink %x1|Make Local %x2");
+                       
                        
                        if(event==1) {
                                switch(idlevel) {
@@ -2747,6 +2779,10 @@ void outliner_operation_menu(ScrArea *sa)
                                BIF_undo_push("Localized Data");
                                allqueue(REDRAWALL, 0); 
                        }
+                       else if(event==3 && idlevel==ID_GR) {
+                               outliner_do_libdata_operation(soops, &soops->tree, group_linkobs2scene_cb);
+                               BIF_undo_push("Link Group Objects to Scene");
+                       }
                }
        }
        else if(datalevel) {
index 2f7b4754d76a00ca4f0c32745ed8596e67aeb0cb..383b73b76193f1b4df2a4b1db9dd90186093a24c 100644 (file)
@@ -270,6 +270,11 @@ static Scene *preview_prepare_scene(RenderInfo *ri, int id_type, ID *id, int pr_
                sce->r.scemode |= R_PREVIEWBUTS;
                /* set world always back, is used now */
                sce->world= pr_main->world.first;
+               /* now: exposure copy */
+               if(G.scene->world) {
+                       sce->world->exp= G.scene->world->exp;
+                       sce->world->range= G.scene->world->range;
+               }
                
                sce->r.cfra= G.scene->r.cfra;
                
index c2c96b04a1d07788eef1849826a73ee23614a8c4..69c20eeeddf2a641eefd3192b9c1fd915d0d38ff 100644 (file)
@@ -178,7 +178,7 @@ float sculpt_stroke_final_length(SculptStroke *stroke)
 }
 
 /* If partial is nonzero, cuts off apply after that length has been processed */
-static StrokePoint *sculpt_stroke_apply_generic(SculptStroke *stroke, struct EditData *e, const int partial)
+static StrokePoint *sculpt_stroke_apply_generic(SculptStroke *stroke, struct BrushAction *a, const int partial)
 {
        const int sdspace = sculpt_data()->spacing;
        const short spacing = sdspace > 0 ? sdspace : 2;
@@ -215,13 +215,13 @@ static StrokePoint *sculpt_stroke_apply_generic(SculptStroke *stroke, struct Edi
                co[0] = p->x*v + p->next->x*u;
                co[1] = p->y*v + p->next->y*u;
 
-               do_symmetrical_brush_actions(e, co, NULL);
+               do_symmetrical_brush_actions(a, co, NULL);
        }
 
        return p ? p->next : NULL;
 }
 
-void sculpt_stroke_apply(struct EditData *e)
+void sculpt_stroke_apply(struct BrushAction *a)
 {
        SculptStroke *stroke = sculpt_session()->stroke;
        /* TODO: make these values user-modifiable? */
@@ -232,7 +232,7 @@ void sculpt_stroke_apply(struct EditData *e)
                sculpt_stroke_create_final();
 
                if(sculpt_stroke_final_length(stroke) > min_len) {
-                       StrokePoint *p = sculpt_stroke_apply_generic(stroke, e, partial_len);
+                       StrokePoint *p = sculpt_stroke_apply_generic(stroke, a, partial_len);
 
                        /* Replace remaining values in stroke->loc with remaining stroke->final values */
                        stroke->index = -1;
@@ -249,14 +249,14 @@ void sculpt_stroke_apply(struct EditData *e)
        }
 }
 
-void sculpt_stroke_apply_all(struct EditData *e)
+void sculpt_stroke_apply_all(struct BrushAction *a)
 {
        SculptStroke *stroke = sculpt_session()->stroke;
 
        sculpt_stroke_create_final();
 
        if(stroke) {
-               sculpt_stroke_apply_generic(stroke, e, 0);
+               sculpt_stroke_apply_generic(stroke, a, 0);
        }
 }
 
index 9e1fa16a44c4422f69cb7c3b5fe90df348d433d9..dbefadb2646cc2eb40238856bfeafbc23237dda6 100644 (file)
@@ -125,36 +125,39 @@ typedef struct ActiveData {
        float dist;
 } ActiveData;
 
-typedef struct GrabData {
-       char firsttime;
-       ListBase active_verts[8];
-       unsigned char index;
-       vec3f delta, delta_symm;
-       float depth;
-} GrabData;
+typedef struct BrushActionSymm {
+       float center_3d[3];
+       char index;
 
-typedef struct EditData {
-       vec3f center;
-       float size;
-       char flip;
-       short mouse[2];
+       float up[3], right[3], out[3];
 
-       /* Adjust brush strength along each axis
-          to adjust for object scaling */
-       float scale[3];
+       // Grab brush
+       float grab_delta[3];
+} BrushActionSymm;
 
-       /* View normals */
-       vec3f up, right, out;
+typedef struct BrushAction {
+       BrushActionSymm symm;
+
+       char firsttime;
+
+       short mouse[2];
+       float size_3d;
 
-       GrabData *grabdata;
        float *layer_disps;
        vec3f *layer_store;
-       
+       char flip;
+
        char clip[3];
        float cliptol[3];
-       
-       char symm;
-} EditData;
+
+       // Grab brush
+       ListBase grab_active_verts[8];
+       float depth;
+
+       /* Adjust brush strength along each axis
+          to adjust for object scaling */
+       float scale[3];
+} BrushAction;
 
 typedef struct RectNode {
        struct RectNode *next, *prev;
@@ -178,7 +181,7 @@ SculptData *sculpt_data(void)
 }
 
 void sculpt_init_session(void);
-void init_editdata(EditData *e, short *, short *);
+void init_brushaction(BrushAction *a, short *, short *);
 void sculpt_undo_push(const short);
 
 SculptSession *sculpt_session(void)
@@ -294,18 +297,16 @@ float get_depth(short x, short y)
 
 /* Uses window coordinates (x,y) and depth component z to find a point in
    modelspace */
-vec3f unproject(const short x, const short y, const float z)
+void unproject(float out[3], const short x, const short y, const float z)
 {
        SculptSession *ss= sculpt_session();
        double ux, uy, uz;
-       vec3f p;
 
         gluUnProject(x,y,z, ss->mats->modelview, ss->mats->projection,
                     (GLint *)ss->mats->viewport, &ux, &uy, &uz );
-       p.x= ux;
-       p.y= uy;
-       p.z= uz;
-       return p;
+       out[0] = ux;
+       out[1] = uy;
+       out[2] = uz;
 }
 
 /* Convert a point in model coordinates to 2D screen coordinates. */
@@ -348,13 +349,13 @@ char brush_size()
 /* Return modified brush strength. Includes the direction of the brush, positive
    values pull vertices, negative values push. Uses tablet pressure and a
    special multiplier found experimentally to scale the strength factor. */
-float brush_strength(EditData *e)
+float brush_strength(BrushAction *a)
 {
        const BrushData* b= sculptmode_brush();
        float dir= b->dir==1 ? 1 : -1;
        float pressure= 1;
        short activedevice= get_activedevice();
-       float flip= e->flip ? -1:1;
+       float flip= a->flip ? -1:1;
 
        const float strength_factor= G.scene->sculptdata.tablet_strength / 10.0f;
        if(ELEM(activedevice, DEV_STYLUS, DEV_ERASER))
@@ -385,11 +386,11 @@ float brush_strength(EditData *e)
 }
 
 /* For clipping against a mirror modifier */
-void sculpt_clip(const EditData *e, float *co, const float val[3])
+void sculpt_clip(const BrushAction *a, float *co, const float val[3])
 {
        char i;
        for(i=0; i<3; ++i) {
-               if(e->clip[i] && (fabs(co[i]) <= e->cliptol[i]))
+               if(a->clip[i] && (fabs(co[i]) <= a->cliptol[i]))
                        co[i]= 0.0f;
                else
                        co[i]= val[i];
@@ -398,7 +399,7 @@ void sculpt_clip(const EditData *e, float *co, const float val[3])
 
 /* Currently only for the draw brush; finds average normal for all active
    vertices */
-vec3f calc_area_normal(const vec3f *outdir, const ListBase* active_verts)
+vec3f calc_area_normal(const float *outdir, const ListBase* active_verts)
 {
        Mesh *me= get_mesh(OBACT);
        vec3f area_normal= {0,0,0};
@@ -412,28 +413,30 @@ vec3f calc_area_normal(const vec3f *outdir, const ListBase* active_verts)
                node= node->next;
        }
        Normalize(&area_normal.x);
+
        if(outdir) {
-               area_normal.x= outdir->x * view + area_normal.x * (10-view);
-               area_normal.y= outdir->y * view + area_normal.y * (10-view);
-               area_normal.z= outdir->z * view + area_normal.z * (10-view);
+               area_normal.x= outdir[0] * view + area_normal.x * (10-view);
+               area_normal.y= outdir[1] * view + area_normal.y * (10-view);
+               area_normal.z= outdir[2] * view + area_normal.z * (10-view);
        }
+
        Normalize(&area_normal.x);
        return area_normal;
 }
-void do_draw_brush(const EditData *e, const ListBase* active_verts)
+void do_draw_brush(const BrushAction *a, const ListBase* active_verts)
 {
        Mesh *me= get_mesh(OBACT);
-       const vec3f area_normal= calc_area_normal(&e->out, active_verts);
+       const vec3f area_normal= calc_area_normal(a->symm.out, active_verts);
        ActiveData *node= active_verts->first;
 
        while(node){
                float *co= me->mvert[node->Index].co;
                
-               const float val[3]= {co[0]+area_normal.x*node->Fade*e->scale[0],
-                                    co[1]+area_normal.y*node->Fade*e->scale[1],
-                                    co[2]+area_normal.z*node->Fade*e->scale[2]};
+               const float val[3]= {co[0]+area_normal.x*node->Fade*a->scale[0],
+                                    co[1]+area_normal.y*node->Fade*a->scale[1],
+                                    co[2]+area_normal.z*node->Fade*a->scale[2]};
                                     
-               sculpt_clip(e, co, val);
+               sculpt_clip(a, co, val);
                
                node= node->next;
        }
@@ -489,7 +492,7 @@ vec3f neighbor_average(const int vert)
        return avg;
 }
 
-void do_smooth_brush(const EditData *e, const ListBase* active_verts)
+void do_smooth_brush(const BrushAction *a, const ListBase* active_verts)
 {
        ActiveData *node= active_verts->first;
        Mesh *me= get_mesh(OBACT);
@@ -500,53 +503,53 @@ void do_smooth_brush(const EditData *e, const ListBase* active_verts)
                const float val[3]= {co[0]+(avg.x-co[0])*node->Fade,
                                     co[1]+(avg.y-co[1])*node->Fade,
                                     co[2]+(avg.z-co[2])*node->Fade};
-               sculpt_clip(e, co, val);
+               sculpt_clip(a, co, val);
                node= node->next;
        }
 }
 
-void do_pinch_brush(const EditData *e, const ListBase* active_verts)
+void do_pinch_brush(const BrushAction *a, const ListBase* active_verts)
 {
        Mesh *me= get_mesh(OBACT);
        ActiveData *node= active_verts->first;
 
        while(node) {
                float *co= me->mvert[node->Index].co;
-               const float val[3]= {co[0]+(e->center.x-co[0])*node->Fade,
-                                    co[1]+(e->center.y-co[1])*node->Fade,
-                                    co[2]+(e->center.z-co[2])*node->Fade};
-               sculpt_clip(e, co, val);
+               const float val[3]= {co[0]+(a->symm.center_3d[0]-co[0])*node->Fade,
+                                    co[1]+(a->symm.center_3d[1]-co[1])*node->Fade,
+                                    co[2]+(a->symm.center_3d[2]-co[2])*node->Fade};
+               sculpt_clip(a, co, val);
                node= node->next;
        }
 }
 
-void do_grab_brush(EditData *e)
+void do_grab_brush(BrushAction *a)
 {
        Mesh *me= get_mesh(OBACT);
-       ActiveData *node= e->grabdata->active_verts[e->grabdata->index].first;
+       ActiveData *node= a->grab_active_verts[a->symm.index].first;
        float add[3];
 
        while(node) {
                float *co= me->mvert[node->Index].co;
                
-               VecCopyf(add, &e->grabdata->delta_symm.x);
+               VecCopyf(add, a->symm.grab_delta);
                VecMulf(add, node->Fade);
                VecAddf(add, add, co);
-               sculpt_clip(e, co, add);
+               sculpt_clip(a, co, add);
 
                node= node->next;
        }
 }
 
-void do_layer_brush(EditData *e, const ListBase *active_verts)
+void do_layer_brush(BrushAction *a, const ListBase *active_verts)
 {
        Mesh *me= get_mesh(OBACT);
        vec3f area_normal= calc_area_normal(NULL, active_verts);
        ActiveData *node= active_verts->first;
-       const float bstr= brush_strength(e);
+       const float bstr= brush_strength(a);
 
        while(node){
-               float *disp= &e->layer_disps[node->Index];
+               float *disp= &a->layer_disps[node->Index];
                
                if((bstr > 0 && *disp < bstr) ||
                  (bstr < 0 && *disp > bstr)) {
@@ -563,10 +566,10 @@ void do_layer_brush(EditData *e, const ListBase *active_verts)
                        }
 
                        {
-                               const float val[3]= {e->layer_store[node->Index].x+area_normal.x * *disp*e->scale[0],
-                                                    e->layer_store[node->Index].y+area_normal.y * *disp*e->scale[1],
-                                                    e->layer_store[node->Index].z+area_normal.z * *disp*e->scale[2]};
-                               sculpt_clip(e, co, val);
+                               const float val[3]= {a->layer_store[node->Index].x+area_normal.x * *disp*a->scale[0],
+                                                    a->layer_store[node->Index].y+area_normal.y * *disp*a->scale[1],
+                                                    a->layer_store[node->Index].z+area_normal.z * *disp*a->scale[2]};
+                               sculpt_clip(a, co, val);
                        }
                }
 
@@ -574,7 +577,7 @@ void do_layer_brush(EditData *e, const ListBase *active_verts)
        }
 }
 
-void do_inflate_brush(const EditData *e, const ListBase *active_verts)
+void do_inflate_brush(const BrushAction *a, const ListBase *active_verts)
 {
        ActiveData *node= active_verts->first;
        float add[3];
@@ -588,18 +591,18 @@ void do_inflate_brush(const EditData *e, const ListBase *active_verts)
                add[1]= no[1]/ 32767.0f;
                add[2]= no[2]/ 32767.0f;
                VecMulf(add, node->Fade);
-               add[0]*= e->scale[0];
-               add[1]*= e->scale[1];
-               add[2]*= e->scale[2];
+               add[0]*= a->scale[0];
+               add[1]*= a->scale[1];
+               add[2]*= a->scale[2];
                VecAddf(add, add, co);
                
-               sculpt_clip(e, co, add);
+               sculpt_clip(a, co, add);
 
                node= node->next;
        }
 }
 
-void calc_flatten_center(Mesh *me, ActiveData *node, const EditData *e, float co[3])
+void calc_flatten_center(Mesh *me, ActiveData *node, float co[3])
 {
        ActiveData *outer[FLATTEN_SAMPLE_SIZE];
        int i;
@@ -622,15 +625,15 @@ void calc_flatten_center(Mesh *me, ActiveData *node, const EditData *e, float co
        VecMulf(co, 1.0f / FLATTEN_SAMPLE_SIZE);
 }
 
-void do_flatten_brush(const EditData *e, const ListBase *active_verts)
+void do_flatten_brush(const BrushAction *a, const ListBase *active_verts)
 {
        Mesh *me= get_mesh(OBACT);
        ActiveData *node= active_verts->first;
        /* area_normal and cntr define the plane towards which vertices are squashed */
-       vec3f area_normal= calc_area_normal(&e->out, active_verts);
+       vec3f area_normal= calc_area_normal(a->symm.out, active_verts);
        float cntr[3];
        
-       calc_flatten_center(me, node, e, cntr);
+       calc_flatten_center(me, node, cntr);
 
        while(node){
                float *co= me->mvert[node->Index].co;
@@ -648,7 +651,7 @@ void do_flatten_brush(const EditData *e, const ListBase *active_verts)
                VecMulf(val, node->Fade);
                VecAddf(val, val, co);
                                     
-               sculpt_clip(e, co, val);
+               sculpt_clip(a, co, val);
                
                node= node->next;
        }
@@ -709,7 +712,7 @@ unsigned *get_texcache_pixel(const SculptSession *ss, int px, int py)
 }
 
 /* Return a multiplier for brush strength on a particular vertex. */
-float tex_strength(EditData *e, float *point, const float len,const unsigned vindex)
+float tex_strength(BrushAction *a, float *point, const float len,const unsigned vindex)
 {
        SculptData *sd= sculpt_data();
        SculptSession *ss= sculpt_session();
@@ -747,12 +750,12 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin
                /* If the active area is being applied for symmetry, flip it
                   across the symmetry axis in order to project it. This insures
                   that the brush texture will be oriented correctly. */
-               if(!e->symm)
+               if(!a->symm.index)
                        pv= ss->projverts[vindex];
                else {
                        float co[3];
                        VecCopyf(co, point);
-                       flip_coord(co, e->symm);
+                       flip_coord(co, a->symm.index);
                        project(co, pv.co);
                }
 
@@ -781,15 +784,15 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin
                                py %= sy-1;
                        p= get_texcache_pixel(ss, tcw*px/sx, tch*py/sy);
                } else {
-                       float fx= (pv.co[0] - e->mouse[0] + half) * (tcw*1.0f/bsize) - tcw/2;
-                       float fy= (pv.co[1] - e->mouse[1] + half) * (tch*1.0f/bsize) - tch/2;
-                       
+                       float fx= (pv.co[0] - a->mouse[0] + half) * (tcw*1.0f/bsize) - tcw/2;
+                       float fy= (pv.co[1] - a->mouse[1] + half) * (tch*1.0f/bsize) - tch/2;
+
                        float angle= atan2(fy, fx) - rot;
                        float len= sqrtf(fx*fx + fy*fy);
                        
                        px= tcw/2 + len * cos(angle);
                        py= tch/2 + len * sin(angle);
-                       
+
                        p= get_texcache_pixel(ss, px, py);
                }
                
@@ -801,7 +804,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin
        }
 
        if(sd->texfade)
-               avg*= curve_strength(len,e->size); /* Smooth curve */
+               avg*= curve_strength(len, a->size_3d); /* Smooth curve */
 
        return avg;
 }
@@ -809,7 +812,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin
 /* Mark area around the brush as damaged. projverts are marked if they are
    inside the area and the damaged rectangle in 2D screen coordinates is 
    added to damaged_rects. */
-void sculpt_add_damaged_rect(EditData *e)
+void sculpt_add_damaged_rect(BrushAction *a)
 {
        short p[2];
        const float radius= brush_size();
@@ -819,7 +822,7 @@ void sculpt_add_damaged_rect(EditData *e)
        unsigned i;
 
        /* Find center */
-       project(&e->center.x, p);
+       project(a->symm.center_3d, p);
        rn->r.xmin= p[0]-radius;
        rn->r.ymin= p[1]-radius;
        rn->r.xmax= p[0]+radius;
@@ -868,7 +871,7 @@ void sculpt_clear_damaged_areas(SculptSession *ss)
        }
 }
 
-void do_brush_action(EditData e)
+void do_brush_action(BrushAction *a)
 {
        int i;
        float av_dist;
@@ -876,29 +879,32 @@ void do_brush_action(EditData e)
        ActiveData *adata= 0;
        float *vert;
        Mesh *me= get_mesh(OBACT);
-       const float bstrength= brush_strength(&e);
+       const float bstrength= brush_strength(a);
        KeyBlock *keyblock= ob_get_keyblock(OBACT);
+       SculptData *sd = sculpt_data();
        SculptSession *ss = sculpt_session();
 
-       sculpt_add_damaged_rect(&e);
+       sculpt_add_damaged_rect(a);
 
        /* Build a list of all vertices that are potentially within the brush's
           area of influence. Only do this once for the grab brush. */
-       if(!e.grabdata || (e.grabdata && e.grabdata->firsttime)) {
+       if((sd->brush_type != GRAB_BRUSH) || a->firsttime) {
                for(i=0; i<me->totvert; ++i) {
                        /* Projverts.inside provides a rough bounding box */
                        if(ss->projverts[i].inside) {
                                vert= ss->vertexcosnos ? &ss->vertexcosnos[i*6] : me->mvert[i].co;
-                               av_dist= VecLenf(&e.center.x,vert);
-                               if(av_dist < e.size) {
+                               av_dist= VecLenf(a->symm.center_3d, vert);
+                               if(av_dist < a->size_3d) {
                                        adata= (ActiveData*)MEM_mallocN(sizeof(ActiveData), "ActiveData");
+
                                        adata->Index = i;
                                        /* Fade is used to store the final strength at which the brush
                                           should modify a particular vertex. */
-                                       adata->Fade= tex_strength(&e,vert,av_dist,i) * bstrength;
+                                       adata->Fade= tex_strength(a, vert, av_dist, i) * bstrength;
                                        adata->dist = av_dist;
-                                       if(e.grabdata && e.grabdata->firsttime)
-                                               BLI_addtail(&e.grabdata->active_verts[e.grabdata->index], adata);
+
+                                       if(sd->brush_type == GRAB_BRUSH && a->firsttime)
+                                               BLI_addtail(&a->grab_active_verts[a->symm.index], adata);
                                        else
                                                BLI_addtail(&active_verts, adata);
                                }
@@ -907,29 +913,29 @@ void do_brush_action(EditData e)
        }
 
        /* Only act if some verts are inside the brush area */
-       if(active_verts.first || (e.grabdata && e.grabdata->active_verts[e.grabdata->index].first)) {
+       if(active_verts.first || (sd->brush_type == GRAB_BRUSH && a->grab_active_verts[a->symm.index].first)) {
                /* Apply one type of brush action */
                switch(G.scene->sculptdata.brush_type){
                case DRAW_BRUSH:
-                       do_draw_brush(&e, &active_verts);
+                       do_draw_brush(a, &active_verts);
                        break;
                case SMOOTH_BRUSH:
-                       do_smooth_brush(&e, &active_verts);
+                       do_smooth_brush(a, &active_verts);
                        break;
                case PINCH_BRUSH:
-                       do_pinch_brush(&e, &active_verts);
+                       do_pinch_brush(a, &active_verts);
                        break;
                case INFLATE_BRUSH:
-                       do_inflate_brush(&e, &active_verts);
+                       do_inflate_brush(a, &active_verts);
                        break;
                case GRAB_BRUSH:
-                       do_grab_brush(&e);
+                       do_grab_brush(a);
                        break;
                case LAYER_BRUSH:
-                       do_layer_brush(&e, &active_verts);
+                       do_layer_brush(a, &active_verts);
                        break;
                case FLATTEN_BRUSH:
-                       do_flatten_brush(&e, &active_verts);
+                       do_flatten_brush(a, &active_verts);
                        break;
                }
        
@@ -937,7 +943,11 @@ void do_brush_action(EditData e)
                if(keyblock) {
                        float *co= keyblock->data;
                        if(co) {
-                               adata = e.grabdata ? e.grabdata->active_verts[e.grabdata->index].first : active_verts.first;
+                               if(sd->brush_type == GRAB_BRUSH)
+                                       adata = a->grab_active_verts[a->symm.index].first;
+                               else
+                                       adata = active_verts.first;
+
                                for(; adata; adata= adata->next)
                                        if(adata->Index < keyblock->totelem)
                                                VecCopyf(&co[adata->Index*3], me->mvert[adata->Index].co);
@@ -947,7 +957,7 @@ void do_brush_action(EditData e)
                if(ss->vertexcosnos)
                        BLI_freelistN(&active_verts);
                else {
-                       if(!e.grabdata)
+                       if(sd->brush_type != GRAB_BRUSH)
                                addlisttolist(&ss->damaged_verts, &active_verts);
                }
        }
@@ -955,51 +965,37 @@ void do_brush_action(EditData e)
 
 /* Flip all the editdata across the axis/axes specified by symm. Used to
    calculate multiple modifications to the mesh when symmetry is enabled. */
-EditData flip_editdata(EditData *e, const char symm)
+void calc_brushdata_symm(BrushAction *a, const char symm)
 {
-       EditData fe= *e;
-       GrabData *gd= fe.grabdata;
-       
-       flip_coord(&fe.center.x, symm);
-       flip_coord(&fe.up.x, symm);
-       flip_coord(&fe.right.x, symm);
-       flip_coord(&fe.out.x, symm);
+       flip_coord(a->symm.center_3d, symm);
+       flip_coord(a->symm.up, symm);
+       flip_coord(a->symm.right, symm);
+       flip_coord(a->symm.out, symm);
        
-       fe.symm= symm;
-
-       project(&e->center.x,fe.mouse);
-
-       if(gd) {
-               gd->index= symm;
-               gd->delta_symm= gd->delta;
-               flip_coord(&gd->delta_symm.x, symm);
-       }
+       a->symm.index= symm;
 
-       return fe;
+       flip_coord(a->symm.grab_delta, symm);
 }
 
-void do_symmetrical_brush_actions(EditData * e, short co[2], short pr_co[2])
+void do_symmetrical_brush_actions(BrushAction *a, short co[2], short pr_co[2])
 {
-       const char symm= sculpt_data()->symm;
+       const char symm = sculpt_data()->symm;
+       BrushActionSymm orig;
+       int i;
 
-       init_editdata(e, co, pr_co);
-       
-       do_brush_action(flip_editdata(e, 0));
+       init_brushaction(a, co, pr_co);
+       orig = a->symm;
+       do_brush_action(a);
        
-       if(symm & SYMM_X)
-               do_brush_action(flip_editdata(e, SYMM_X));
-       if(symm & SYMM_Y)
-               do_brush_action(flip_editdata(e, SYMM_Y));
-       if(symm & SYMM_Z)
-               do_brush_action(flip_editdata(e, SYMM_Z));
-       if(symm & SYMM_X && symm & SYMM_Y)
-               do_brush_action(flip_editdata(e, SYMM_X | SYMM_Y));
-       if(symm & SYMM_X && symm & SYMM_Z)
-               do_brush_action(flip_editdata(e, SYMM_X | SYMM_Z));
-       if(symm & SYMM_Y && symm & SYMM_Z)
-               do_brush_action(flip_editdata(e, SYMM_Y | SYMM_Z));
-       if(symm & SYMM_X && symm & SYMM_Y && symm & SYMM_Z)
-               do_brush_action(flip_editdata(e, SYMM_X | SYMM_Y | SYMM_Z));
+       for(i = 1; i <= symm; ++i) {
+               if(symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))) {
+                       // Restore the original symmetry data
+                       a->symm = orig;
+
+                       calc_brushdata_symm(a, i);
+                       do_brush_action(a);
+               }
+       }
 }
 
 void add_face_normal(vec3f *norm, const MFace* face)
@@ -1039,19 +1035,17 @@ void update_damaged_vert(Mesh *me, ListBase *lb)
        }
 }
 
-void calc_damaged_verts(ListBase *damaged_verts, GrabData *grabdata)
+void calc_damaged_verts(ListBase *damaged_verts, BrushAction *a)
 {
        Mesh *me= get_mesh(OBACT);
+       int i;
+       
+       for(i=0; i<8; ++i)
+               update_damaged_vert(me, &a->grab_active_verts[i]);
 
-       if(grabdata) {
-               int i;
-               for(i=0; i<8; ++i)
-                       update_damaged_vert(me,&grabdata->active_verts[i]);
-       } else {
-               update_damaged_vert(me,damaged_verts);
-               BLI_freelistN(damaged_verts);
-               damaged_verts->first = damaged_verts->last = NULL;
-       }
+       update_damaged_vert(me, damaged_verts);
+       BLI_freelistN(damaged_verts);
+       damaged_verts->first = damaged_verts->last = NULL;
 }
 
 void projverts_clear_inside(SculptSession *ss)
@@ -1137,83 +1131,80 @@ void sculptmode_update_tex()
 }
 
 /* pr_mouse is only used for the grab brush, can be NULL otherwise */
-void init_editdata(EditData *e, short *mouse, short *pr_mouse)
+void init_brushaction(BrushAction *a, short *mouse, short *pr_mouse)
 {
        SculptData *sd = sculpt_data();
-       const float mouse_depth= get_depth(mouse[0],mouse[1]);
-       vec3f brush_edge_loc, zero_loc, oldloc;
+       const float mouse_depth = get_depth(mouse[0], mouse[1]);
+       float brush_edge_loc[3], zero_loc[3], oldloc[3];
        ModifierData *md;
        int i;
        const char flip = (get_qual() == LR_SHIFTKEY);
 
-       e->flip= flip;
+       a->flip = flip;
+       a->symm.index = 0;
+       a->mouse[0] = mouse[0];
+       a->mouse[1] = mouse[1];
        
        /* Convert the location and size of the brush to
           modelspace coords */
-       e->center= unproject(mouse[0],mouse[1],mouse_depth);
-       brush_edge_loc= unproject(mouse[0] +
-                                 brush_size(),mouse[1],
-                                 mouse_depth);
-       e->size= VecLenf(&e->center.x,&brush_edge_loc.x);
+       unproject(a->symm.center_3d, mouse[0], mouse[1], mouse_depth);
+       unproject(brush_edge_loc, mouse[0] + brush_size(), mouse[1], mouse_depth);
+       a->size_3d = VecLenf(a->symm.center_3d, brush_edge_loc);
 
        /* Set the pivot to allow the model to rotate around the center of the brush */
        if(get_depth(mouse[0],mouse[1]) < 1.0)
-               sculpt_session()->pivot= e->center;
+               VecCopyf(&sculpt_session()->pivot.x, a->symm.center_3d);
 
        /* Now project the Up, Right, and Out normals from view to model coords */
-       zero_loc= unproject(0, 0, 0);
-       e->up= unproject(0, -1, 0);
-       e->right= unproject(1, 0, 0);
-       e->out= unproject(0, 0, -1);
-       VecSubf(&e->up.x, &e->up.x, &zero_loc.x);
-       VecSubf(&e->right.x, &e->right.x, &zero_loc.x);
-       VecSubf(&e->out.x, &e->out.x, &zero_loc.x);
-       Normalize(&e->up.x);
-       Normalize(&e->right.x);
-       Normalize(&e->out.x);
+       unproject(zero_loc, 0, 0, 0);
+       unproject(a->symm.up, 0, -1, 0);
+       unproject(a->symm.right, 1, 0, 0);
+       unproject(a->symm.out, 0, 0, -1);
+       VecSubf(a->symm.up, a->symm.up, zero_loc);
+       VecSubf(a->symm.right, a->symm.right, zero_loc);
+       VecSubf(a->symm.out, a->symm.out, zero_loc);
+       Normalize(a->symm.up);
+       Normalize(a->symm.right);
+       Normalize(a->symm.out);
        
        /* Initialize mirror modifier clipping */
        for(i=0; i<3; ++i) {
-               e->clip[i]= 0;
-               e->cliptol[i]= 0;
+               a->clip[i]= 0;
+               a->cliptol[i]= 0;
        }
        for(md= OBACT->modifiers.first; md; md= md->next) {
                if(md->type==eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
                        const MirrorModifierData *mmd = (MirrorModifierData*) md;
                        
                        if(mmd->flag & MOD_MIR_CLIPPING) {
-                               e->clip[mmd->axis]= 1;
-                               if(mmd->tolerance > e->cliptol[mmd->axis])
-                                       e->cliptol[mmd->axis]= mmd->tolerance;
+                               a->clip[mmd->axis]= 1;
+                               if(mmd->tolerance > a->cliptol[mmd->axis])
+                                       a->cliptol[mmd->axis] = mmd->tolerance;
                        }
                }
        }
 
        if(sd->brush_type == GRAB_BRUSH) {
-               vec3f gcenter;
-               if(!e->grabdata) {
-                       e->grabdata= MEM_callocN(sizeof(GrabData),"grab data");
-                       e->grabdata->firsttime= 1;
-                       e->grabdata->depth= mouse_depth;
-               }
-               else
-                       e->grabdata->firsttime= 0;
-               
+               float gcenter[3];
+
+               if(a->firsttime) 
+                       a->depth = mouse_depth;
+
                /* Find the delta */
-               gcenter= unproject(mouse[0],mouse[1],e->grabdata->depth);
-               oldloc= unproject(pr_mouse[0],pr_mouse[1],e->grabdata->depth);
-               VecSubf(&e->grabdata->delta.x,&gcenter.x,&oldloc.x);
+               unproject(gcenter, mouse[0], mouse[1], a->depth);
+               unproject(oldloc, pr_mouse[0], pr_mouse[1], a->depth);
+               VecSubf(a->symm.grab_delta, gcenter, oldloc);
        }
        else if(sd->brush_type == LAYER_BRUSH) {
                Mesh *me= get_mesh(OBACT);
 
-               if(!e->layer_disps)
-                       e->layer_disps= MEM_callocN(sizeof(float)*me->totvert,"Layer disps");
-               if(!e->layer_store) {
+               if(!a->layer_disps)
+                       a->layer_disps= MEM_callocN(sizeof(float)*me->totvert,"Layer disps");
+               if(!a->layer_store) {
                        unsigned i;
-                       e->layer_store= MEM_mallocN(sizeof(vec3f)*me->totvert,"Layer store");
+                       a->layer_store= MEM_mallocN(sizeof(vec3f)*me->totvert,"Layer store");
                        for(i=0; i<me->totvert; ++i)
-                               VecCopyf(&e->layer_store[i].x,me->mvert[i].co);
+                               VecCopyf(&a->layer_store[i].x, me->mvert[i].co);
                }
        }
 }
@@ -1470,11 +1461,11 @@ void sculpt(void)
        /* lastSigMouse is for the rake, to store the last place the mouse movement was significant */
        short mouse[2], mvalo[2], lastSigMouse[2],firsttime=1, mousebut;
        short modifier_calculations= 0;
-       EditData e;
+       BrushAction *a = MEM_callocN(sizeof(BrushAction), "brush action");
        short spacing= 32000;
        int scissor_box[4];
        float offsetRot;
-       int smooth_stroke = 0;
+       int smooth_stroke = 0, i;
 
        if(!(G.f & G_SCULPTMODE) || G.obedit || !ob || ob->id.lib || !get_mesh(ob) || (get_mesh(ob)->totface == 0))
                return;
@@ -1541,14 +1532,13 @@ void sculpt(void)
                ss->vertexcosnos= mesh_get_mapped_verts_nors(ob);
        sculptmode_update_all_projverts(ss->vertexcosnos);
 
-       e.grabdata= NULL;
-       e.layer_disps= NULL;
-       e.layer_store= NULL;
+       a->layer_disps= NULL;
+       a->layer_store= NULL;
 
        /* Set scaling adjustment */
-       e.scale[0]= 1.0f / ob->size[0];
-       e.scale[1]= 1.0f / ob->size[1];
-       e.scale[2]= 1.0f / ob->size[2];
+       a->scale[0]= 1.0f / ob->size[0];
+       a->scale[1]= 1.0f / ob->size[1];
+       a->scale[2]= 1.0f / ob->size[2];
 
        /* Capture original copy */
        if(sd->flags & SCULPT_DRAW_FAST)
@@ -1571,6 +1561,7 @@ void sculpt(void)
                }
                
                if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] || sculptmode_brush()->airbrush) {
+                       a->firsttime = firsttime;
                        firsttime= 0;
 
                        if(smooth_stroke)
@@ -1583,27 +1574,27 @@ void sculpt(void)
 
                        if(G.scene->sculptdata.brush_type != GRAB_BRUSH) {
                                if(smooth_stroke) {
-                                       sculpt_stroke_apply(&e);
+                                       sculpt_stroke_apply(a);
                                }
                                else if(sd->spacing==0 || spacing>sd->spacing) {
-                                       do_symmetrical_brush_actions(&e, mouse, NULL);
+                                       do_symmetrical_brush_actions(a, mouse, NULL);
                                        spacing= 0;
                                }
                        }
                        else {
-                               do_symmetrical_brush_actions(&e, mouse, mvalo);
-                               ss->pivot= unproject(mouse[0],mouse[1],e.grabdata->depth);
+                               do_symmetrical_brush_actions(a, mouse, mvalo);
+                               unproject(&ss->pivot.x, mouse[0], mouse[1], a->depth);
                        }
 
                        if(modifier_calculations || ob_get_keyblock(ob))
                                DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
 
                        if(modifier_calculations || sd->brush_type == GRAB_BRUSH || !(sd->flags & SCULPT_DRAW_FAST)) {
-                               calc_damaged_verts(&ss->damaged_verts,e.grabdata);
+                               calc_damaged_verts(&ss->damaged_verts, a);
                                scrarea_do_windraw(curarea);
                                screen_swapbuffers();
                        } else { /* Optimized drawing */
-                               calc_damaged_verts(&ss->damaged_verts,e.grabdata);
+                               calc_damaged_verts(&ss->damaged_verts, a);
 
                                /* Draw the stored image to the screen */
                                glAccum(GL_RETURN, 1);
@@ -1648,20 +1639,16 @@ void sculpt(void)
        set_tex_angle(offsetRot);
        
        if(smooth_stroke) {
-               sculpt_stroke_apply_all(&e);
-               calc_damaged_verts(&ss->damaged_verts,e.grabdata);
+               sculpt_stroke_apply_all(a);
+               calc_damaged_verts(&ss->damaged_verts, a);
                BLI_freelistN(&ss->damaged_rects);
        }
 
-       if(e.layer_disps) MEM_freeN(e.layer_disps);
-       if(e.layer_store) MEM_freeN(e.layer_store);
-       /* Free GrabData */
-       if(e.grabdata) {
-               int i;
-               for(i=0; i<8; ++i)
-                       BLI_freelistN(&e.grabdata->active_verts[i]);
-               MEM_freeN(e.grabdata);
-       }
+       if(a->layer_disps) MEM_freeN(a->layer_disps);
+       if(a->layer_store) MEM_freeN(a->layer_store);
+       for(i=0; i<8; ++i)
+               BLI_freelistN(&a->grab_active_verts[i]);
+       MEM_freeN(a);
        sculpt_stroke_free();
 
        sculpt_undo_push(G.scene->sculptdata.brush_type);
@@ -1728,7 +1715,7 @@ void set_sculptmode(void)
 static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode)
 {
        Mesh *me= get_mesh(ob);
-       vec3f hidebox[6];
+       float hidebox[6][3];
        vec3f plane_normals[4];
        float plane_ds[4];
        unsigned i, j;
@@ -1740,23 +1727,23 @@ static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode)
        const unsigned SHOW= 0, HIDE=1;
 
        /* Convert hide box from 2D to 3D */
-       hidebox[0]= unproject(hb_2d->xmin, hb_2d->ymax, 1);
-       hidebox[1]= unproject(hb_2d->xmax, hb_2d->ymax, 1);
-       hidebox[2]= unproject(hb_2d->xmax, hb_2d->ymin, 1);
-       hidebox[3]= unproject(hb_2d->xmin, hb_2d->ymin, 1);
-       hidebox[4]= unproject(hb_2d->xmin, hb_2d->ymax, 0);
-       hidebox[5]= unproject(hb_2d->xmax, hb_2d->ymin, 0);
+       unproject(hidebox[0], hb_2d->xmin, hb_2d->ymax, 1);
+       unproject(hidebox[1], hb_2d->xmax, hb_2d->ymax, 1);
+       unproject(hidebox[2], hb_2d->xmax, hb_2d->ymin, 1);
+       unproject(hidebox[3], hb_2d->xmin, hb_2d->ymin, 1);
+       unproject(hidebox[4], hb_2d->xmin, hb_2d->ymax, 0);
+       unproject(hidebox[5], hb_2d->xmax, hb_2d->ymin, 0);
        
        /* Calculate normals for each side of hide box */
-       CalcNormFloat(&hidebox[0].x,&hidebox[1].x,&hidebox[4].x,&plane_normals[0].x);
-       CalcNormFloat(&hidebox[1].x,&hidebox[2].x,&hidebox[5].x,&plane_normals[1].x);
-       CalcNormFloat(&hidebox[2].x,&hidebox[3].x,&hidebox[5].x,&plane_normals[2].x);
-       CalcNormFloat(&hidebox[3].x,&hidebox[0].x,&hidebox[4].x,&plane_normals[3].x);
+       CalcNormFloat(hidebox[0], hidebox[1], hidebox[4], &plane_normals[0].x);
+       CalcNormFloat(hidebox[1], hidebox[2], hidebox[5], &plane_normals[1].x);
+       CalcNormFloat(hidebox[2], hidebox[3], hidebox[5], &plane_normals[2].x);
+       CalcNormFloat(hidebox[3], hidebox[0], hidebox[4], &plane_normals[3].x);
        
        /* Calculate D for each side of hide box */
        for(i= 0; i<4; ++i)
-               plane_ds[i]= hidebox[i].x*plane_normals[i].x + hidebox[i].y*plane_normals[i].y +
-                       hidebox[i].z*plane_normals[i].z;
+               plane_ds[i]= hidebox[i][0]*plane_normals[i].x + hidebox[i][1]*plane_normals[i].y +
+                       hidebox[i][2]*plane_normals[i].z;
        
        /* Add partial visibility to mesh */
        if(!me->pv) {
index bbb5e5149423fca29d74cad84443f5f2a0564dbe..1855ad3d1477fd1ea22e11cff3eed9725aa0cbd0 100644 (file)
@@ -888,6 +888,8 @@ static char *transform_to_undostr(TransInfo *t)
                        return "Time Slide";
                case TFM_BAKE_TIME:
                        return "Key Time";
+               case TFM_MIRROR:
+                       return "Mirror";
        }
        return "Transform";
 }
@@ -1323,6 +1325,9 @@ void initTransform(int mode, int context) {
        case TFM_BAKE_TIME:
                initBakeTime(&Trans);
                break;
+       case TFM_MIRROR:
+               initMirror(&Trans);
+               break;
        }
 }
 
@@ -1359,6 +1364,13 @@ void Transform()
                        }
                        Trans.redraw = 0;
                }
+
+               /* If auto confirm is on, break after one pass */               
+               if (Trans.context & CTX_AUTOCONFIRM)
+               {
+                       Trans.state = TRANS_CONFIRM;
+                       break;
+               }
                
                /* essential for idling subloop */
                if( qtest()==0) PIL_sleep_ms(2);
@@ -4033,105 +4045,83 @@ int BakeTime(TransInfo *t, short mval[2])
        return 1;
 }
 
-
 /* ************************** MIRROR *************************** */
 
-void Mirror(short mode
+void initMirror(TransInfo *t
 {
-       TransData *td;
-       float mati[3][3], matview[3][3], mat[3][3];
-       float size[3];
-       int i;
-
-       Trans.context = CTX_NO_PET;
-
-       initTrans(&Trans);              // internal data, mouse, vectors
-
-       Mat3One(mati);
-       Mat3CpyMat4(matview, Trans.viewinv); // t->viewinv was set in initTrans
-       Mat3Ortho(matview);
-
-       createTransData(&Trans);        // make TransData structs from selection
-
-       calculatePropRatio(&Trans);
-       calculateCenter(&Trans);
-
-       initResize(&Trans);
-
-       if (Trans.total == 0) {
-               postTrans(&Trans);
-               return;
-       }
-
-       size[0] = size[1] = size[2] = 1.0f;
-       td = Trans.data;
-
-       switch (mode) {
-       case 1:
-               size[0] = -1.0f;
-               setConstraint(&Trans, mati, (CON_AXIS0), "");
-               break;
-       case 2:
-               size[1] = -1.0f;
-               setConstraint(&Trans, mati, (CON_AXIS1), "");
-               break;
-       case 3:
-               size[2] = -1.0f;
-               setConstraint(&Trans, mati, (CON_AXIS2), "");
-               break;
-       case 4:
-               size[0] = -1.0f;
-               setLocalConstraint(&Trans, (CON_AXIS0), "");
-               break;
-       case 5:
-               size[1] = -1.0f;
-               setLocalConstraint(&Trans, (CON_AXIS1), "");
-               break;
-       case 6:
-               size[2] = -1.0f;
-               setLocalConstraint(&Trans, (CON_AXIS2), "");
-               break;
-       case 7:
-               size[0] = -1.0f;
-               setConstraint(&Trans, matview, (CON_AXIS0), "");
-               break;
-       case 8:
-               size[1] = -1.0f;
-               setConstraint(&Trans, matview, (CON_AXIS1), "");
-               break;
-       case 9:
-               size[2] = -1.0f;
-               setConstraint(&Trans, matview, (CON_AXIS2), "");
-               break;
-       default:
-               return;
+       t->flag |= T_NULL_ONE;
+       if (!G.obedit) {
+               t->flag |= T_NO_ZERO;
        }
+       
+       t->transform = Mirror;
+}
 
-       SizeToMat3(size, mat);
-
-       if (Trans.con.applySize) {
-               Trans.con.applySize(&Trans, NULL, mat);
-       }
+int Mirror(TransInfo *t, short mval[2]) 
+{
+       TransData *td;
+       float size[3], mat[3][3];
+       int i;
+       char str[200];
 
-       for(i = 0 ; i < Trans.total; i++, td++) {
-               if (td->flag & TD_NOACTION)
-                       break;
+       /*
+        * OPTIMISATION:
+        * This still recalcs transformation on mouse move
+        * while it should only recalc on constraint change
+        * */
 
-               if (td->flag & TD_SKIP)
-                       continue;
+       /* if an axis has been selected */
+       if (t->con.mode & CON_APPLY) {
+               size[0] = size[1] = size[2] = -1;
+       
+               SizeToMat3(size, mat);
+               
+               if (t->con.applySize) {
+                       t->con.applySize(t, NULL, mat);
+               }
                
-               ElementResize(&Trans, td, mat);
+               sprintf(str, "Mirror%s", t->con.text);
+       
+               for(i = 0, td=t->data; i < t->total; i++, td++) {
+                       if (td->flag & TD_NOACTION)
+                               break;
+       
+                       if (td->flag & TD_SKIP)
+                               continue;
+                       
+                       ElementResize(t, td, mat);
+               }
+       
+               recalcData(t);
+       
+               headerprint(str);
+       
+               viewRedrawForce(t);
        }
-
-       recalcData(&Trans);
+       else
+       {
+               size[0] = size[1] = size[2] = 1;
        
-       BIF_undo_push("Mirror");
-
-       /* free data, reset vars */
-       postTrans(&Trans);
+               SizeToMat3(size, mat);
+               
+               for(i = 0, td=t->data; i < t->total; i++, td++) {
+                       if (td->flag & TD_NOACTION)
+                               break;
+       
+                       if (td->flag & TD_SKIP)
+                               continue;
+                       
+                       ElementResize(t, td, mat);
+               }
+       
+               recalcData(t);
+       
+               headerprint("Select a mirror axis (X, Y, Z)");
+       
+               viewRedrawForce(t);
+       }
 
-       /* send events out for redraws */
-       viewRedrawPost(&Trans);
+       return 1;
 }
 
 /* ************************** ANIM EDITORS - TRANSFORM TOOLS *************************** */